Implement automatic "mark as fulfilled" for requests

This commit is contained in:
grimsi
2025-09-02 11:22:49 +02:00
parent 9908c401e6
commit 3377f770f6
5 changed files with 64 additions and 4 deletions
@@ -8,12 +8,33 @@ import org.gameyfin.app.games.dto.GameAdminEvent
import org.gameyfin.app.games.dto.GameUserEvent
import org.gameyfin.app.games.extensions.toAdminDto
import org.gameyfin.app.games.extensions.toUserDto
import org.gameyfin.app.requests.GameRequestService
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware
import org.springframework.stereotype.Component
@Component
class GameEntityListener : ApplicationContextAware {
companion object {
private lateinit var applicationContext: ApplicationContext
}
override fun setApplicationContext(context: ApplicationContext) {
applicationContext = context
}
private fun getGameRequestService(): GameRequestService {
return applicationContext.getBean(GameRequestService::class.java)
}
class GameEntityListener {
@PostPersist
fun created(game: Game) {
GameService.emitUser(GameUserEvent.Created(game.toUserDto()))
GameService.emitAdmin(GameAdminEvent.Created(game.toAdminDto()))
// After a game is created, mark any matching game requests as FULFILLED
getGameRequestService().completeMatchingRequests(game)
}
@PostUpdate
@@ -2,5 +2,13 @@ package org.gameyfin.app.requests
import org.gameyfin.app.requests.entities.GameRequest
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param
import java.time.Instant
interface GameRequestRepository : JpaRepository<GameRequest, Long>
interface GameRequestRepository : JpaRepository<GameRequest, Long> {
fun findByTitleAndRelease(title: String, release: Instant): List<GameRequest>
@Query("SELECT g FROM GameRequest g WHERE g.title = :title AND YEAR(g.release) = YEAR(:release)")
fun findByTitleAndReleaseYear(@Param("title") title: String, @Param("release") release: Instant): List<GameRequest>
}
@@ -2,10 +2,12 @@ package org.gameyfin.app.requests
import io.github.oshai.kotlinlogging.KotlinLogging
import org.gameyfin.app.core.security.getCurrentAuth
import org.gameyfin.app.games.entities.Game
import org.gameyfin.app.requests.dto.GameRequestCreationDto
import org.gameyfin.app.requests.dto.GameRequestDto
import org.gameyfin.app.requests.dto.GameRequestEvent
import org.gameyfin.app.requests.entities.GameRequest
import org.gameyfin.app.requests.extensions.toDto
import org.gameyfin.app.requests.extensions.toDtos
import org.gameyfin.app.requests.status.GameRequestStatus
import org.gameyfin.app.users.UserService
@@ -94,4 +96,31 @@ class GameRequestService(
gameRequestRepository.save(gameRequest)
}
fun completeMatchingRequests(game: Game) {
val gameTitle = game.title
val gameRelease = game.release
if (gameTitle == null || gameRelease == null) {
log.debug { "Game '${game.id}' is missing title and/or release date, cannot complete matching requests" }
return
}
// First match by exact title and release date, if not result could be found then by title and release year only
val matchingRequestsByExactRelease = gameRequestRepository.findByTitleAndRelease(gameTitle, gameRelease)
val matchingRequestsByReleaseYear = matchingRequestsByExactRelease.ifEmpty {
gameRequestRepository.findByTitleAndReleaseYear(
gameTitle,
gameRelease
)
}
matchingRequestsByReleaseYear.forEach { request ->
request.status = GameRequestStatus.FULFILLED
request.linkedGameId = game.id
val persistedRequest = gameRequestRepository.save(request)
emit(GameRequestEvent.Updated(persistedRequest.toDto()))
log.info { "Marked game request '${request.title}' (${request.release}) as FULFILLED because game is now available" }
}
}
}
@@ -3,7 +3,7 @@ package org.gameyfin.app.requests.dto
sealed class GameRequestEvent {
abstract val type: String
data class Created(val game: GameRequestDto, override val type: String = "created") : GameRequestEvent()
data class Updated(val game: GameRequestDto, override val type: String = "updated") : GameRequestEvent()
data class Created(val gameRequest: GameRequestDto, override val type: String = "created") : GameRequestEvent()
data class Updated(val gameRequest: GameRequestDto, override val type: String = "updated") : GameRequestEvent()
data class Deleted(val gameRequestId: Long, override val type: String = "deleted") : GameRequestEvent()
}
@@ -35,6 +35,8 @@ class GameRequest(
@OneToMany
var voters: MutableList<User> = mutableListOf(),
var linkedGameId: Long? = null,
@CreationTimestamp
@Column(nullable = false, updatable = false)
var createdAt: Instant? = null,