diff --git a/app/src/main/kotlin/org/gameyfin/app/games/entities/GameEntityListener.kt b/app/src/main/kotlin/org/gameyfin/app/games/entities/GameEntityListener.kt index 9a04b3e..f1f8e53 100644 --- a/app/src/main/kotlin/org/gameyfin/app/games/entities/GameEntityListener.kt +++ b/app/src/main/kotlin/org/gameyfin/app/games/entities/GameEntityListener.kt @@ -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 diff --git a/app/src/main/kotlin/org/gameyfin/app/requests/GameRequestRepository.kt b/app/src/main/kotlin/org/gameyfin/app/requests/GameRequestRepository.kt index c045b4d..a8d2a95 100644 --- a/app/src/main/kotlin/org/gameyfin/app/requests/GameRequestRepository.kt +++ b/app/src/main/kotlin/org/gameyfin/app/requests/GameRequestRepository.kt @@ -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 \ No newline at end of file +interface GameRequestRepository : JpaRepository { + fun findByTitleAndRelease(title: String, release: Instant): List + + @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 +} \ No newline at end of file diff --git a/app/src/main/kotlin/org/gameyfin/app/requests/GameRequestService.kt b/app/src/main/kotlin/org/gameyfin/app/requests/GameRequestService.kt index dfef3f4..9860d84 100644 --- a/app/src/main/kotlin/org/gameyfin/app/requests/GameRequestService.kt +++ b/app/src/main/kotlin/org/gameyfin/app/requests/GameRequestService.kt @@ -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" } + } + } } \ No newline at end of file diff --git a/app/src/main/kotlin/org/gameyfin/app/requests/dto/GameRequestEvent.kt b/app/src/main/kotlin/org/gameyfin/app/requests/dto/GameRequestEvent.kt index f006d3a..d59bd9a 100644 --- a/app/src/main/kotlin/org/gameyfin/app/requests/dto/GameRequestEvent.kt +++ b/app/src/main/kotlin/org/gameyfin/app/requests/dto/GameRequestEvent.kt @@ -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() } \ No newline at end of file diff --git a/app/src/main/kotlin/org/gameyfin/app/requests/entities/GameRequest.kt b/app/src/main/kotlin/org/gameyfin/app/requests/entities/GameRequest.kt index 20947f4..832322c 100644 --- a/app/src/main/kotlin/org/gameyfin/app/requests/entities/GameRequest.kt +++ b/app/src/main/kotlin/org/gameyfin/app/requests/entities/GameRequest.kt @@ -35,6 +35,8 @@ class GameRequest( @OneToMany var voters: MutableList = mutableListOf(), + var linkedGameId: Long? = null, + @CreationTimestamp @Column(nullable = false, updatable = false) var createdAt: Instant? = null,