Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: claude code improvements #2637

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,36 +42,42 @@ class FirebaseTokenAuthenticationFilter(

private fun verifyToken(request: HttpServletRequest) {
val token: String? = tokenHelperUtils.getBearerToken(request)
if (token.isNullOrEmpty()) {
return
}

try {
val decodedToken: FirebaseToken = firebaseAuth.verifyIdToken(token, true)
try {
val user: UserDetails = brainUpUserDetailsService.loadUserByUsername(decodedToken.email)
val authentication = UsernamePasswordAuthenticationToken(
user,
UserAccountCredentials(decodedToken, token),
user.authorities
)
authentication.details = WebAuthenticationDetailsSource().buildDetails(request)
SecurityContextHolder.getContext().authentication = authentication
setAuthentication(user, decodedToken, token, request)
} catch (e: UsernameNotFoundException) {
log.warn("User with email: ${decodedToken.email} doesn't exist: create it")
val firebaseUserRecord = firebaseUserService.getUserByUuid(decodedToken.uid)
if (firebaseUserRecord != null) {
val createUser = userAccountService.createUser(firebaseUserRecord)
val user: UserDetails = brainUpUserDetailsService.loadUserByUsername(createUser.email)
val authentication = UsernamePasswordAuthenticationToken(
user,
UserAccountCredentials(decodedToken, token),
user.authorities
)
authentication.details = WebAuthenticationDetailsSource().buildDetails(request)
SecurityContextHolder.getContext().authentication = authentication
}
val firebaseUserRecord = firebaseUserService.getUserByUuid(decodedToken.uid) ?: return
val createdUser = userAccountService.createUser(firebaseUserRecord)
val user: UserDetails = brainUpUserDetailsService.loadUserByUsername(createdUser.email)
setAuthentication(user, decodedToken, token, request)
}
} catch (e: FirebaseAuthException) {
log.error("Error while validate token: ${e.message}", e)
} catch (e: Exception) {
log.error("Error: ${e.message}", e)
}
}

private fun setAuthentication(
user: UserDetails,
decodedToken: FirebaseToken,
token: String,
request: HttpServletRequest
) {
val authentication = UsernamePasswordAuthenticationToken(
user,
UserAccountCredentials(decodedToken, token),
user.authorities
).apply {
details = WebAuthenticationDetailsSource().buildDetails(request)
}
SecurityContextHolder.getContext().authentication = authentication
}
}
14 changes: 9 additions & 5 deletions src/main/kotlin/com/epam/brn/repo/SeriesRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,26 @@ import com.epam.brn.model.Series
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.CrudRepository
import org.springframework.stereotype.Repository
import java.util.Optional

@Repository
interface SeriesRepository : CrudRepository<Series, Long> {

fun findByNameLike(name: String): List<Series>

@Query("select distinct s from Series s where s.type=?1 and s.exerciseGroup.locale=?2")
@Query("select distinct s from Series s left join fetch s.exerciseGroup where s.type = :type and s.exerciseGroup.locale = :locale")
fun findByTypeAndLocale(type: String, locale: String): Series?

fun findByTypeAndName(type: String, name: String): Series?

fun findByNameIn(names: List<String>): List<Series>

@Query("select distinct s from Series s where s.exerciseGroup.id=?1")
fun findByExerciseGroupLike(groupId: Long): List<Series>
@Query("""
select s from Series s
where s.exerciseGroup.id = :groupId
""")
fun findByExerciseGroupId(groupId: Long): List<Series>

// @Query("select distinct s from Series s left JOIN FETCH s.exercises where s.id=?1")
// fun findSeriesWithExercisesById(groupId: Long): Optional<Series>
@Query("select distinct s from Series s left join fetch s.exercises where s.id = :seriesId")
fun findSeriesWithExercisesById(seriesId: Long): Optional<Series>
}
47 changes: 31 additions & 16 deletions src/main/kotlin/com/epam/brn/repo/StudyHistoryRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,31 @@ interface StudyHistoryRepository : CrudRepository<StudyHistory, Long> {
fun getDoneExercisesIdList(@Param("userId") userId: Long): List<Long>

@Query(
"SELECT s FROM StudyHistory s " +
" WHERE (s.userAccount.id, s.startTime) " +
" IN (SELECT userAccount.id, max(startTime) " +
" FROM StudyHistory " +
" GROUP BY exercise.id, userAccount.id " +
" HAVING userAccount.id = :userId)"
"""
SELECT s FROM StudyHistory s
WHERE s.userAccount.id = :userId
AND s.startTime = (
SELECT MAX(sh.startTime)
FROM StudyHistory sh
WHERE sh.userAccount.id = s.userAccount.id
AND sh.exercise.id = s.exercise.id
)
"""
)
fun findLastByUserAccountId(userId: Long): List<StudyHistory>

@Query(
"SELECT s FROM StudyHistory s " +
" WHERE (s.userAccount.id, s.startTime) " +
" IN (SELECT userAccount.id, max(startTime) " +
" FROM StudyHistory " +
" WHERE exercise.subGroup.id = :subGroupId " +
" GROUP BY exercise.id, userAccount.id " +
" HAVING userAccount.id = :userId)"
"""
SELECT s FROM StudyHistory s
WHERE s.exercise.subGroup.id = :subGroupId
AND s.userAccount.id = :userId
AND s.startTime = (
SELECT MAX(sh.startTime)
FROM StudyHistory sh
WHERE sh.userAccount.id = s.userAccount.id
AND sh.exercise.id = s.exercise.id
)
"""
)
fun findLastBySubGroupAndUserAccount(subGroupId: Long, userId: Long): List<StudyHistory>

Expand Down Expand Up @@ -93,9 +101,16 @@ interface StudyHistoryRepository : CrudRepository<StudyHistory, Long> {
): List<StudyHistory>

@Query(
"SELECT MIN(s.startTime) AS firstStudy, MAX(s.startTime) AS lastStudy," +
" COALESCE(SUM(s.spentTimeInSeconds), 0) AS spentTime, COUNT (DISTINCT s.exercise.id) as doneExercises" +
" FROM StudyHistory s WHERE user_id = :userId"
"""
SELECT NEW com.epam.brn.model.projection.UserStatisticView(
MIN(s.startTime),
MAX(s.startTime),
COALESCE(SUM(s.spentTimeInSeconds), 0),
COUNT(DISTINCT s.exercise.id)
)
FROM StudyHistory s
WHERE s.userAccount.id = :userId
"""
)
fun getStatisticsByUserAccountId(userId: Long?): UserStatisticView

Expand Down
6 changes: 3 additions & 3 deletions src/main/kotlin/com/epam/brn/repo/SubGroupRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ interface SubGroupRepository : CrudRepository<SubGroup, Long> {

fun findByNameLike(name: String): List<SubGroup>

@Query("select distinct s from SubGroup s where s.code=?1 and s.series.exerciseGroup.locale=?2")
@Query("select distinct s from SubGroup s join fetch s.series ser join fetch ser.exerciseGroup where s.code = ?1 and ser.exerciseGroup.locale = ?2")
fun findByCodeAndLocale(code: String, locale: String): SubGroup?

fun findByNameAndLevelAndSeries(name: String, level: Int, series: Series): SubGroup?

fun findByNameAndLevel(name: String, level: Int): SubGroup?

@Query("select distinct s from SubGroup s where s.name=?1 and s.level=?2 and s.series.exerciseGroup.locale=?3")
@Query("select distinct s from SubGroup s join fetch s.series ser join fetch ser.exerciseGroup where s.name = ?1 and s.level = ?2 and ser.exerciseGroup.locale = ?3")
fun findByNameAndLevelAndLocale(name: String, level: Int, locale: String): SubGroup?

@Query("select distinct s from SubGroup s where s.series.id=?1")
@Query("select distinct s from SubGroup s join fetch s.series where s.series.id = ?1")
fun findBySeriesId(seriesId: Long): List<SubGroup>
}
27 changes: 18 additions & 9 deletions src/main/kotlin/com/epam/brn/repo/TaskRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,27 @@ import java.util.Optional
@Repository
interface TaskRepository : JpaRepository<Task, Long> {

@Query("select DISTINCT t FROM Task t left JOIN FETCH t.answerOptions")
@Query("""
select DISTINCT t FROM Task t
left JOIN FETCH t.answerOptions ao
WHERE t IN (select t2 from Task t2)
""")
fun findAllTasksWithJoinedAnswers(): List<Task>

@Query("select DISTINCT t FROM Task t left JOIN FETCH t.answerOptions where t.exercise.id = ?1")
@Query("""
select DISTINCT t FROM Task t
left JOIN FETCH t.answerOptions ao
where t.exercise.id = :id
AND t IN (select t2 from Task t2 where t2.exercise.id = :id)
""")
fun findTasksByExerciseIdWithJoinedAnswers(id: Long): List<Task>

@Query(
"select DISTINCT t " +
"FROM Task t " +
"left JOIN FETCH t.answerParts " +
"left JOIN FETCH t.answerOptions " +
"where t.id = ?1"
)
@Query("""
select DISTINCT t FROM Task t
left JOIN FETCH t.answerParts ap
left JOIN FETCH t.answerOptions ao
where t.id = :id
AND t IN (select t2 from Task t2 where t2.id = :id)
""")
override fun findById(id: Long): Optional<Task>
}
49 changes: 31 additions & 18 deletions src/main/kotlin/com/epam/brn/repo/UserAccountRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,49 +10,62 @@ import org.springframework.stereotype.Repository
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDateTime
import java.util.Optional
import org.springframework.data.repository.query.Param

@Repository
interface UserAccountRepository : JpaRepository<UserAccount, Long> {

@Query(
"""select DISTINCT u FROM UserAccount u left JOIN FETCH u.roleSet
left JOIN FETCH u.headphones where u.fullName = ?1"""
"""select u FROM UserAccount u
JOIN FETCH u.roleSet
LEFT JOIN FETCH u.headphones
where u.fullName = :fullName"""
)
fun findUserAccountByName(fullName: String): Optional<UserAccount>
fun findUserAccountByName(@Param("fullName") fullName: String): Optional<UserAccount>

@Query(
"""select DISTINCT u FROM UserAccount u left JOIN FETCH u.roleSet
left JOIN FETCH u.headphones where LOWER(u.email) = LOWER( ?1)"""
"""select u FROM UserAccount u
JOIN FETCH u.roleSet
LEFT JOIN FETCH u.headphones
where LOWER(u.email) = LOWER(:email)"""
)
fun findUserAccountByEmail(email: String): Optional<UserAccount>
fun findUserAccountByEmail(@Param("email") email: String): Optional<UserAccount>

@Query(
"""select DISTINCT u FROM UserAccount u left JOIN FETCH u.roleSet
left JOIN FETCH u.headphones where u.id = ?1"""
"""select u FROM UserAccount u
JOIN FETCH u.roleSet
LEFT JOIN FETCH u.headphones
where u.id = :id"""
)
fun findUserAccountById(id: Long): Optional<UserAccount>
fun findUserAccountById(@Param("id") id: Long): Optional<UserAccount>

@Query(
"""select DISTINCT u FROM UserAccount u left JOIN FETCH u.roleSet
left JOIN FETCH u.headphones where u.doctor = ?1"""
"""select u FROM UserAccount u
JOIN FETCH u.roleSet
LEFT JOIN FETCH u.headphones
where u.doctor = :doctor"""
)
fun findUserAccountsByDoctor(doctor: UserAccount): List<UserAccount>
fun findUserAccountsByDoctor(@Param("doctor") doctor: UserAccount): List<UserAccount>

@Query(
"""select DISTINCT u FROM UserAccount u left JOIN FETCH u.roleSet
left JOIN FETCH u.headphones where u.doctor.id = ?1"""
"""select u FROM UserAccount u
JOIN FETCH u.roleSet
LEFT JOIN FETCH u.headphones
where u.doctor.id = :doctorId"""
)
fun findUserAccountsByDoctorId(doctorId: Long): List<UserAccount>
fun findUserAccountsByDoctorId(@Param("doctorId") doctorId: Long): List<UserAccount>

fun findByUserId(uuid: String): UserAccount?

fun findAllByUserIdIsNullAndIsFirebaseErrorIsFalse(pageable: Pageable): Page<UserAccount>

@Query(
"""select DISTINCT u FROM UserAccount u left JOIN FETCH u.roleSet roles
left JOIN FETCH u.headphones where roles.name = :roleName"""
"""select u FROM UserAccount u
JOIN FETCH u.roleSet roles
LEFT JOIN FETCH u.headphones
where roles.name = :roleName"""
)
fun findUsersAccountsByRole(roleName: String): List<UserAccount>
fun findUsersAccountsByRole(@Param("roleName") roleName: String): List<UserAccount>

@Transactional
@Modifying
Expand Down
17 changes: 11 additions & 6 deletions src/main/kotlin/com/epam/brn/service/ExerciseGroupsService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ class ExerciseGroupsService(

fun findAllGroups(): List<ExerciseGroupDto> {
log.debug("Searching all groups")
val groups: List<ExerciseGroup> = exerciseGroupRepository.findAll()
return groups.map { group -> group.toDto() }
return exerciseGroupRepository.findAll()
.asSequence()
.map { it.toDto() }
.toList()
}

fun findGroupDtoById(groupId: Long): ExerciseGroupDto {
Expand All @@ -30,10 +32,13 @@ class ExerciseGroupsService(

fun findByLocale(locale: String): List<ExerciseGroupDto> {
log.debug("Searching groups by locale=$locale")
if (locale.isEmpty())
return exerciseGroupRepository.findAll().map { group -> group.toDto() }
return exerciseGroupRepository.findByLocale(locale)
.map { group -> group.toDto() }
return when {
locale.isBlank() -> findAllGroups()
else -> exerciseGroupRepository.findByLocale(locale)
.asSequence()
.map { it.toDto() }
.toList()
}
}

fun save(exerciseGroup: ExerciseGroup): ExerciseGroup {
Expand Down
33 changes: 12 additions & 21 deletions src/main/kotlin/com/epam/brn/service/StudyHistoryService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -79,30 +79,21 @@ class StudyHistoryService(

private fun calculateUserDailyDetailStatistics(studyHistories: List<StudyHistory>):
MutableList<UserDailyDetailStatisticsDto> {
val result = mutableListOf<UserDailyDetailStatisticsDto>()
studyHistories
return studyHistories
.groupBy { it.exercise.subGroup!!.series.name }
.forEach { (seriesName, histories) ->
val allDoneExercisesCount = histories.size
val studyHistoryByExercise = histories
.groupBy { it.exercise.id }
val uniqueDoneExercisesCount = studyHistoryByExercise
.count()
val doneExercisesSuccessfullyFromFirstTime = studyHistoryByExercise
.count { it.value.size == 1 }
val listenWordsCount = histories.sumOf { it.tasksCount.toInt() }
val seconds = histories.sumOf { it.spentTimeInSeconds ?: 0L }
val userDailyDetailStatisticsDto = UserDailyDetailStatisticsDto(
.map { (seriesName, histories) ->
val exerciseGroups = histories.groupBy { it.exercise.id }
UserDailyDetailStatisticsDto(
seriesName = seriesName,
allDoneExercises = allDoneExercisesCount,
uniqueDoneExercises = uniqueDoneExercisesCount,
doneExercisesSuccessfullyFromFirstTime = doneExercisesSuccessfullyFromFirstTime,
repeatedExercises = allDoneExercisesCount - doneExercisesSuccessfullyFromFirstTime,
listenWordsCount = listenWordsCount,
duration = (seconds.toDouble() / 60).toDuration(DurationUnit.MINUTES)
allDoneExercises = histories.size,
uniqueDoneExercises = exerciseGroups.size,
doneExercisesSuccessfullyFromFirstTime = exerciseGroups.count { it.value.size == 1 },
repeatedExercises = histories.size - exerciseGroups.count { it.value.size == 1 },
listenWordsCount = histories.sumOf { it.tasksCount.toInt() },
duration = (histories.sumOf { it.spentTimeInSeconds ?: 0L }.toDouble() / 60)
.toDuration(DurationUnit.MINUTES)
)
result.add(userDailyDetailStatisticsDto)
}
return result
.toMutableList()
}
}
Loading
Loading