diff --git a/.github/workflows/build-and-deploy-preprod.yml b/.github/workflows/build-and-deploy-preprod.yml index 6924e189..f9bc4764 100644 --- a/.github/workflows/build-and-deploy-preprod.yml +++ b/.github/workflows/build-and-deploy-preprod.yml @@ -2,7 +2,7 @@ name: Build-Deploy-Preprod on: push: branches-ignore: - - 'master' + - 'main' workflow_dispatch: env: diff --git a/.github/workflows/build-and-deploy-prod.yml b/.github/workflows/build-and-deploy-prod.yml index 6ee3b6a7..039324cd 100644 --- a/.github/workflows/build-and-deploy-prod.yml +++ b/.github/workflows/build-and-deploy-prod.yml @@ -2,7 +2,7 @@ name: Build-Deploy-Prod on: push: branches: - - 'master' + - 'main' env: IMAGE: ghcr.io/navikt/familie-oppdrag:${{ github.sha }} IMAGE_LATEST: ghcr.io/navikt/familie-oppdrag:latest diff --git a/app-preprod.yaml b/app-preprod.yaml index 1db94d67..4680e208 100644 --- a/app-preprod.yaml +++ b/app-preprod.yaml @@ -69,9 +69,7 @@ spec: external: - host: b27apvl220.preprod.local ports: - - name: mq - port: 1413 - protocol: TCP + - port: 1413 env: - name: SPRING_PROFILES_ACTIVE value: preprod diff --git a/app-prod.yaml b/app-prod.yaml index 28b03d0a..14505ef3 100644 --- a/app-prod.yaml +++ b/app-prod.yaml @@ -64,9 +64,7 @@ spec: external: - host: mpls02.adeo.no ports: - - name: mq - port: 1414 - protocol: TCP + - port: 1414 env: - name: SPRING_PROFILES_ACTIVE value: prod diff --git a/pom.xml b/pom.xml index a401ae56..1eaefe27 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.springframework.boot spring-boot-starter-parent - 3.1.2 + 3.2.2 @@ -22,8 +22,8 @@ 1.9.0 no.nav.familie.oppdrag.LauncherKt 2.20230508082643_6b28bd8 - 3.0_20230808083340_ced4750 - 3.1.2 + 3.0_20240122110213_5591a29 + 3.2.0 ${SONAR_LOGIN} - 2022.0.4 + 2023.0.0 1.18.3 1.0_20230718100517_1e1beb0 - 2.2.0 + 2.3.0 diff --git "a/src/main/kotlin/no/nav/familie/oppdrag/repository/TidligereKj\303\270rtGrensesnittavstemming.kt" "b/src/main/kotlin/no/nav/familie/oppdrag/repository/TidligereKj\303\270rtGrensesnittavstemming.kt" new file mode 100644 index 00000000..4d01c242 --- /dev/null +++ "b/src/main/kotlin/no/nav/familie/oppdrag/repository/TidligereKj\303\270rtGrensesnittavstemming.kt" @@ -0,0 +1,10 @@ +package no.nav.familie.oppdrag.repository + +import java.util.UUID +import org.springframework.data.annotation.Id +import org.springframework.data.relational.core.mapping.Table + +@Table("tidligere_kjoerte_grensesnittavstemminger") +class TidligereKjørtGrensesnittavstemming( + @Id val id: UUID +) \ No newline at end of file diff --git "a/src/main/kotlin/no/nav/familie/oppdrag/repository/TidligereKj\303\270rteGrensesnittavstemmingerRepository.kt" "b/src/main/kotlin/no/nav/familie/oppdrag/repository/TidligereKj\303\270rteGrensesnittavstemmingerRepository.kt" new file mode 100644 index 00000000..d48da993 --- /dev/null +++ "b/src/main/kotlin/no/nav/familie/oppdrag/repository/TidligereKj\303\270rteGrensesnittavstemmingerRepository.kt" @@ -0,0 +1,10 @@ +package no.nav.familie.oppdrag.repository + +import java.util.Optional +import java.util.UUID +import org.springframework.data.repository.CrudRepository +import org.springframework.stereotype.Repository + +@Repository +interface TidligereKjørteGrensesnittavstemmingerRepository : InsertUpdateRepository, + CrudRepository diff --git a/src/main/kotlin/no/nav/familie/oppdrag/rest/OppdragController.kt b/src/main/kotlin/no/nav/familie/oppdrag/rest/OppdragController.kt index 64918ae7..a0dc7482 100644 --- a/src/main/kotlin/no/nav/familie/oppdrag/rest/OppdragController.kt +++ b/src/main/kotlin/no/nav/familie/oppdrag/rest/OppdragController.kt @@ -11,6 +11,7 @@ import no.nav.familie.oppdrag.common.RessursUtils.notFound import no.nav.familie.oppdrag.common.RessursUtils.ok import no.nav.familie.oppdrag.iverksetting.OppdragMapper import no.nav.familie.oppdrag.service.OppdragAlleredeSendtException +import no.nav.familie.oppdrag.service.OppdragHarAlleredeKvitteringException import no.nav.familie.oppdrag.service.OppdragService import no.nav.security.token.support.core.api.ProtectedWithClaims import org.springframework.beans.factory.annotation.Autowired @@ -76,7 +77,7 @@ class OppdragController( } @PostMapping("resend") - fun resentOppdrag( + fun resendOppdrag( @Valid @RequestBody oppdragId: OppdragId, ) { @@ -98,4 +99,24 @@ class OppdragController( }, ) } + + @PostMapping(consumes = [MediaType.APPLICATION_JSON_VALUE], path = ["/oppdrag/manuell-kvittering"]) + fun opprettManuellKvitteringPåOppdrag( + @Valid @RequestBody + oppdragId: OppdragId, + ): ResponseEntity> { + return Result.runCatching { oppdragService.opprettManuellKvitteringPåOppdrag(oppdragId) } + .fold( + onFailure = { + if (it is OppdragHarAlleredeKvitteringException) { + conflict("Oppdrag med id $oppdragId er allerede kvittert ut.") + } else { + illegalState("Klarte ikke opprette manuell kvittering for oppdrag med id $oppdragId", it) + } + }, + onSuccess = { + ok(it.status, it.kvitteringsmelding?.beskrMelding ?: "Savner kvitteringsmelding") + }, + ) + } } diff --git a/src/main/kotlin/no/nav/familie/oppdrag/service/GrensesnittavstemmingService.kt b/src/main/kotlin/no/nav/familie/oppdrag/service/GrensesnittavstemmingService.kt index 43cd6811..18c6e81c 100644 --- a/src/main/kotlin/no/nav/familie/oppdrag/service/GrensesnittavstemmingService.kt +++ b/src/main/kotlin/no/nav/familie/oppdrag/service/GrensesnittavstemmingService.kt @@ -13,11 +13,15 @@ import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Service import java.time.LocalDateTime +import no.nav.familie.oppdrag.repository.TidligereKjørtGrensesnittavstemming +import no.nav.familie.oppdrag.repository.TidligereKjørteGrensesnittavstemmingerRepository +import kotlin.jvm.optionals.getOrNull @Service class GrensesnittavstemmingService( private val avstemmingSender: AvstemmingSender, private val oppdragLagerRepository: OppdragLagerRepository, + private val tidligereKjørteGrensesnittavstemmingerRepository: TidligereKjørteGrensesnittavstemmingerRepository, @Value("\${grensesnitt.antall:7000}") private val antall: Int, ) { @@ -31,7 +35,15 @@ class GrensesnittavstemmingService( } fun utførGrensesnittavstemming(request: GrensesnittavstemmingRequest) { - val (fagsystem: String, fra: LocalDateTime, til: LocalDateTime) = request + val (fagsystem: String, fra: LocalDateTime, til: LocalDateTime, avstemmingId) = request + + val erGrensesnittavstemmingKjørtPåSammeAvstemmingId = + avstemmingId?.let { tidligereKjørteGrensesnittavstemmingerRepository.findById(it).getOrNull() } != null + if (erGrensesnittavstemmingKjørtPåSammeAvstemmingId) { + LOG.info("Grensesnittavstemming er allerede fullført for $avstemmingId og vil ikke bli kjørt på nytt") + return + } + var page = 0 var antallOppdragSomSkalAvstemmes = 0 var oppdragSomSkalAvstemmes = @@ -55,6 +67,10 @@ class GrensesnittavstemmingService( avstemmingSender.sendGrensesnittAvstemming(totalmelding) avstemmingSender.sendGrensesnittAvstemming(avstemmingMapper.lagSluttmelding()) + if (avstemmingId != null) { + tidligereKjørteGrensesnittavstemmingerRepository.insert(TidligereKjørtGrensesnittavstemming(avstemmingId)) + } + LOG.info( "Fullført grensesnittavstemming for id: ${avstemmingMapper.avstemmingId}" + " antallOppdragSomSkalAvstemmes=$antallOppdragSomSkalAvstemmes", diff --git a/src/main/kotlin/no/nav/familie/oppdrag/service/OppdragService.kt b/src/main/kotlin/no/nav/familie/oppdrag/service/OppdragService.kt index 1f0d4a71..5e3e9154 100644 --- a/src/main/kotlin/no/nav/familie/oppdrag/service/OppdragService.kt +++ b/src/main/kotlin/no/nav/familie/oppdrag/service/OppdragService.kt @@ -9,4 +9,5 @@ interface OppdragService { fun opprettOppdrag(utbetalingsoppdrag: Utbetalingsoppdrag, oppdrag: Oppdrag, versjon: Int) fun hentStatusForOppdrag(oppdragId: OppdragId): OppdragLager fun resendOppdrag(oppdragId: OppdragId) + fun opprettManuellKvitteringPåOppdrag(oppdragId: OppdragId): OppdragLager } diff --git a/src/main/kotlin/no/nav/familie/oppdrag/service/OppdragServiceE2E.kt b/src/main/kotlin/no/nav/familie/oppdrag/service/OppdragServiceE2E.kt index fb5bd292..c23204db 100644 --- a/src/main/kotlin/no/nav/familie/oppdrag/service/OppdragServiceE2E.kt +++ b/src/main/kotlin/no/nav/familie/oppdrag/service/OppdragServiceE2E.kt @@ -36,6 +36,10 @@ class OppdragServiceE2E( throw NotImplementedError("Ikke implementert") } + override fun opprettManuellKvitteringPåOppdrag(oppdragId: OppdragId): OppdragLager { + throw NotImplementedError("Ikke implementert") + } + companion object { val LOG = LoggerFactory.getLogger(OppdragServiceE2E::class.java) diff --git a/src/main/kotlin/no/nav/familie/oppdrag/service/OppdragServiceImpl.kt b/src/main/kotlin/no/nav/familie/oppdrag/service/OppdragServiceImpl.kt index f98798ee..cf147cb6 100644 --- a/src/main/kotlin/no/nav/familie/oppdrag/service/OppdragServiceImpl.kt +++ b/src/main/kotlin/no/nav/familie/oppdrag/service/OppdragServiceImpl.kt @@ -8,6 +8,7 @@ import no.nav.familie.oppdrag.iverksetting.Jaxb import no.nav.familie.oppdrag.iverksetting.OppdragSender import no.nav.familie.oppdrag.repository.OppdragLager import no.nav.familie.oppdrag.repository.OppdragLagerRepository +import no.trygdeetaten.skjema.oppdrag.Mmel import no.trygdeetaten.skjema.oppdrag.Oppdrag import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired @@ -52,6 +53,26 @@ class OppdragServiceImpl( oppdragSender.sendOppdrag(oppdragXml) } + @Transactional + override fun opprettManuellKvitteringPåOppdrag(oppdragId: OppdragId): OppdragLager { + val oppdrag = oppdragLagerRepository.hentOppdrag(oppdragId) + + if (oppdrag.status != OppdragStatus.LAGT_PÅ_KØ) { + throw OppdragHarAlleredeKvitteringException("Oppdrag med id $oppdragId er allerede kvittert ut.") + } + + val manuellKvittering = Mmel().apply { beskrMelding = "Manuelt kvittert ut" } + + oppdragLagerRepository.oppdaterKvitteringsmelding( + oppdragId = oppdragId, + oppdragStatus = OppdragStatus.KVITTERT_OK, + kvittering = manuellKvittering, + versjon = oppdrag.versjon + 1, + ) + + return oppdrag + } + companion object { val LOG = LoggerFactory.getLogger(OppdragServiceImpl::class.java) @@ -59,3 +80,4 @@ class OppdragServiceImpl( } class OppdragAlleredeSendtException() : RuntimeException() +class OppdragHarAlleredeKvitteringException(melding: String) : RuntimeException(melding) diff --git a/src/main/resources/application-prod.yaml b/src/main/resources/application-prod.yaml index 789090ff..91ef0cd8 100644 --- a/src/main/resources/application-prod.yaml +++ b/src/main/resources/application-prod.yaml @@ -20,7 +20,7 @@ no.nav.security.jwt: spring: datasource: - url: jdbc:postgresql://A01DBVL011.adeo.no:5432/familie-oppdrag + url: jdbc:postgresql://A01DBVL035.adeo.no:5432/familie-oppdrag-15 OPPDRAG_SERVICE_URL: https://wasapp.adeo.no/cics/services/simulerFpServiceWSBinding SECURITYTOKENSERVICE_URL: https://sts.adeo.no/SecurityTokenServiceProvider/ diff --git a/src/main/resources/bootstrap-prod.yaml b/src/main/resources/bootstrap-prod.yaml index 9e734ea7..b6c52ec4 100644 --- a/src/main/resources/bootstrap-prod.yaml +++ b/src/main/resources/bootstrap-prod.yaml @@ -12,7 +12,7 @@ spring: expiry-threshold: 2m database: enabled: true - role: familie-oppdrag-admin + role: familie-oppdrag-15-admin backend: postgresql/prod-fss authentication: KUBERNETES kubernetes: diff --git a/src/main/resources/db/migration/V013__opprett_tidligere_kjoerte_grensesnittavstemminger.sql b/src/main/resources/db/migration/V013__opprett_tidligere_kjoerte_grensesnittavstemminger.sql new file mode 100644 index 00000000..c6276c4f --- /dev/null +++ b/src/main/resources/db/migration/V013__opprett_tidligere_kjoerte_grensesnittavstemminger.sql @@ -0,0 +1,4 @@ +CREATE TABLE tidligere_kjoerte_grensesnittavstemminger +( + id UUID PRIMARY KEY NOT NULL +); \ No newline at end of file diff --git a/src/test/kotlin/no/nav/familie/oppdrag/grensesnittavstemming/GrensesnittavstemmingIdTest.kt b/src/test/kotlin/no/nav/familie/oppdrag/grensesnittavstemming/GrensesnittavstemmingIdTest.kt new file mode 100644 index 00000000..b51e318d --- /dev/null +++ b/src/test/kotlin/no/nav/familie/oppdrag/grensesnittavstemming/GrensesnittavstemmingIdTest.kt @@ -0,0 +1,216 @@ +package no.nav.familie.oppdrag.grensesnittavstemming + +import ch.qos.logback.classic.Logger +import ch.qos.logback.classic.spi.ILoggingEvent +import ch.qos.logback.core.read.ListAppender +import io.mockk.every +import io.mockk.mockk +import java.time.LocalDateTime +import java.util.* +import no.nav.familie.kontrakter.felles.oppdrag.GrensesnittavstemmingRequest +import no.nav.familie.oppdrag.avstemming.AvstemmingSender +import no.nav.familie.oppdrag.iverksetting.OppdragMapper +import no.nav.familie.oppdrag.repository.OppdragLager +import no.nav.familie.oppdrag.repository.OppdragLagerRepository +import no.nav.familie.oppdrag.repository.TidligereKjørtGrensesnittavstemming +import no.nav.familie.oppdrag.repository.TidligereKjørteGrensesnittavstemmingerRepository +import no.nav.familie.oppdrag.service.GrensesnittavstemmingService +import no.nav.familie.oppdrag.util.TestConfig +import no.nav.familie.oppdrag.util.TestOppdragMedAvstemmingsdato +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.jdbc.core.JdbcTemplate +import org.springframework.test.context.ActiveProfiles +import org.springframework.test.context.DynamicPropertyRegistry +import org.springframework.test.context.DynamicPropertySource +import org.testcontainers.containers.PostgreSQLContainer +import org.testcontainers.junit.jupiter.Container +import org.testcontainers.junit.jupiter.Testcontainers + + +@ActiveProfiles("dev") +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@SpringBootTest(classes = [TestConfig::class], properties = ["spring.cloud.vault.enabled=false"]) +@Testcontainers +class GrensesnittavstemmingIdTest( + @Autowired + val tidligereKjørteGrensesnittavstemmingerRepository: TidligereKjørteGrensesnittavstemmingerRepository, + @Autowired + val jdbcTemplate: JdbcTemplate, + @Autowired + val oppdragLagerRepository: OppdragLagerRepository, + @Autowired val oppdragMapper: OppdragMapper, +) { + + val avstemmingSender: AvstemmingSender = mockk() + + val grensesnittavstemmingService = GrensesnittavstemmingService( + avstemmingSender = avstemmingSender, + oppdragLagerRepository = oppdragLagerRepository, + tidligereKjørteGrensesnittavstemmingerRepository = tidligereKjørteGrensesnittavstemmingerRepository, + antall = 2, + ) + + companion object { + protected fun initLoggingEventListAppender(): ListAppender { + val listAppender = ListAppender() + listAppender.start() + return listAppender + } + + + @Container + private val postgreSQLContainer = PostgreSQLContainer("postgres:latest") + + @DynamicPropertySource + @JvmStatic + fun registerDynamicProperties(registry: DynamicPropertyRegistry) { + registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl) + registry.add("spring.datasource.username", postgreSQLContainer::getUsername) + registry.add("spring.datasource.password", postgreSQLContainer::getPassword) + } + } + + private val listAppender = initLoggingEventListAppender() + + @BeforeEach + fun setUp() { + jdbcTemplate.execute("TRUNCATE TABLE tidligere_kjoerte_grensesnittavstemminger") + } + + @Test + fun `Skal kunne lagre avstemming Id`() { + val uuid = UUID.randomUUID() + tidligereKjørteGrensesnittavstemmingerRepository.insert(TidligereKjørtGrensesnittavstemming(uuid)) + + val lagretKjørtGrensesnittavstemming = tidligereKjørteGrensesnittavstemmingerRepository.findById(uuid) + Assertions.assertNotNull(lagretKjørtGrensesnittavstemming) + } + + @Test + fun `Skal ikke kjøre grensesnittavstemming dersom det allerede er kjørt på samme avstemmingId`() { + val logger: Logger = LoggerFactory.getLogger(GrensesnittavstemmingService::class.java) as Logger + logger.addAppender(listAppender) + + opprettUtbetalingsoppdrag() + every { avstemmingSender.sendGrensesnittAvstemming(any()) } returns Unit + + val avstemmingId = UUID.randomUUID() + grensesnittavstemmingService.utførGrensesnittavstemming( + GrensesnittavstemmingRequest( + fagsystem = "BA", + fra = LocalDateTime.now().minusDays(2), + til = LocalDateTime.now(), + avstemmingId = avstemmingId, + ), + ) + + grensesnittavstemmingService.utførGrensesnittavstemming( + GrensesnittavstemmingRequest( + fagsystem = "BA", + fra = LocalDateTime.now().minusDays(2), + til = LocalDateTime.now(), + avstemmingId = avstemmingId, + ), + ) + + val fullførtMeldinger = listAppender.list.filter { "Fullført grensesnittavstemming" in it.message } + Assertions.assertEquals(1, fullførtMeldinger.size) + } + + @Test + fun `Skal være mulig å kjøre grensesnittavstemming selv om avstemmingId er null`() { + val logger: Logger = LoggerFactory.getLogger(GrensesnittavstemmingService::class.java) as Logger + logger.addAppender(listAppender) + + opprettUtbetalingsoppdrag() + every { avstemmingSender.sendGrensesnittAvstemming(any()) } returns Unit + + grensesnittavstemmingService.utførGrensesnittavstemming( + GrensesnittavstemmingRequest( + fagsystem = "BA", + fra = LocalDateTime.now().minusDays(2), + til = LocalDateTime.now(), + avstemmingId = null, + ), + ) + + val fullførtMeldinger = listAppender.list.filter { "Fullført grensesnittavstemming" in it.message } + Assertions.assertEquals(1, fullførtMeldinger.size) + } + + @Test + fun `Skal være mulig å kjøre grensesnittavstemming flere ganger når ikke avstemmingId er satt`() { + val logger: Logger = LoggerFactory.getLogger(GrensesnittavstemmingService::class.java) as Logger + logger.addAppender(listAppender) + + opprettUtbetalingsoppdrag() + every { avstemmingSender.sendGrensesnittAvstemming(any()) } returns Unit + + grensesnittavstemmingService.utførGrensesnittavstemming( + GrensesnittavstemmingRequest( + fagsystem = "BA", + fra = LocalDateTime.now().minusDays(2), + til = LocalDateTime.now(), + avstemmingId = null, + ), + ) + + grensesnittavstemmingService.utførGrensesnittavstemming( + GrensesnittavstemmingRequest( + fagsystem = "BA", + fra = LocalDateTime.now().minusDays(2), + til = LocalDateTime.now(), + avstemmingId = null, + ), + ) + + val fullførtMeldinger = listAppender.list.filter { "Fullført grensesnittavstemming" in it.message } + Assertions.assertEquals(2, fullførtMeldinger.size) + } + + @Test + fun `Skal være mulig å kjøre grensesnittavstemming flere ganger om man bruker forskjellig avstemmingId`() { + val logger: Logger = LoggerFactory.getLogger(GrensesnittavstemmingService::class.java) as Logger + logger.addAppender(listAppender) + + opprettUtbetalingsoppdrag() + every { avstemmingSender.sendGrensesnittAvstemming(any()) } returns Unit + + grensesnittavstemmingService.utførGrensesnittavstemming( + GrensesnittavstemmingRequest( + fagsystem = "BA", + fra = LocalDateTime.now().minusDays(2), + til = LocalDateTime.now(), + avstemmingId = UUID.randomUUID(), + ), + ) + + grensesnittavstemmingService.utførGrensesnittavstemming( + GrensesnittavstemmingRequest( + fagsystem = "BA", + fra = LocalDateTime.now().minusDays(2), + til = LocalDateTime.now(), + avstemmingId = UUID.randomUUID(), + ), + ) + + val fullførtMeldinger = listAppender.list.filter { "Fullført grensesnittavstemming" in it.message } + Assertions.assertEquals(2, fullførtMeldinger.size) + } + + private fun opprettUtbetalingsoppdrag() { + val utbetalingsoppdrag = TestOppdragMedAvstemmingsdato.lagTestUtbetalingsoppdrag( + LocalDateTime.now().minusDays(1), + "BA", + utbetalingsperiode = arrayOf(TestOppdragMedAvstemmingsdato.lagUtbetalingsperiode()), + ) + val oppdrag = oppdragMapper.tilOppdrag(oppdragMapper.tilOppdrag110(utbetalingsoppdrag)) + oppdragLagerRepository.opprettOppdrag(OppdragLager.lagFraOppdrag(utbetalingsoppdrag, oppdrag), 0) + } +} diff --git a/src/test/kotlin/no/nav/familie/oppdrag/repository/MellomlagringKonsistensavstemmingRepositoryTest.kt b/src/test/kotlin/no/nav/familie/oppdrag/repository/MellomlagringKonsistensavstemmingRepositoryTest.kt index 35dfbab8..1f528179 100644 --- a/src/test/kotlin/no/nav/familie/oppdrag/repository/MellomlagringKonsistensavstemmingRepositoryTest.kt +++ b/src/test/kotlin/no/nav/familie/oppdrag/repository/MellomlagringKonsistensavstemmingRepositoryTest.kt @@ -14,10 +14,14 @@ import org.springframework.test.context.ContextConfiguration import org.testcontainers.junit.jupiter.Container import org.testcontainers.junit.jupiter.Testcontainers import java.util.UUID +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase +import org.springframework.test.context.DynamicPropertyRegistry +import org.springframework.test.context.DynamicPropertySource +import org.testcontainers.containers.PostgreSQLContainer import kotlin.test.assertEquals @ActiveProfiles("dev") -@ContextConfiguration(initializers = arrayOf(Containers.PostgresSQLInitializer::class)) +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @SpringBootTest( classes = [MellomlagringKonsistensavstemmingRepositoryTest.TestConfig::class], properties = ["spring.cloud.vault.enabled=false"], @@ -29,8 +33,16 @@ internal class MellomlagringKonsistensavstemmingRepositoryTest { @Autowired lateinit var repository: MellomlagringKonsistensavstemmingRepository companion object { + @Container + private val postgreSQLContainer = PostgreSQLContainer("postgres:latest") - @Container var postgreSQLContainer = Containers.postgreSQLContainer + @DynamicPropertySource + @JvmStatic + fun registerDynamicProperties(registry: DynamicPropertyRegistry) { + registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl) + registry.add("spring.datasource.username", postgreSQLContainer::getUsername) + registry.add("spring.datasource.password", postgreSQLContainer::getPassword) + } } @Test diff --git a/src/test/kotlin/no/nav/familie/oppdrag/repository/OppdragLagerRepositoryJdbcTest.kt b/src/test/kotlin/no/nav/familie/oppdrag/repository/OppdragLagerRepositoryJdbcTest.kt index 4b687af6..9445206b 100644 --- a/src/test/kotlin/no/nav/familie/oppdrag/repository/OppdragLagerRepositoryJdbcTest.kt +++ b/src/test/kotlin/no/nav/familie/oppdrag/repository/OppdragLagerRepositoryJdbcTest.kt @@ -25,10 +25,14 @@ import java.time.LocalDate import java.time.LocalDateTime import java.time.format.DateTimeFormatter import java.util.UUID +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase +import org.springframework.test.context.DynamicPropertyRegistry +import org.springframework.test.context.DynamicPropertySource +import org.testcontainers.containers.PostgreSQLContainer import kotlin.test.assertFailsWith @ActiveProfiles("dev") -@ContextConfiguration(initializers = arrayOf(Containers.PostgresSQLInitializer::class)) +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @SpringBootTest(classes = [TestConfig::class], properties = ["spring.cloud.vault.enabled=false"]) @DisabledIfEnvironmentVariable(named = "CIRCLECI", matches = "true") @Testcontainers @@ -39,8 +43,16 @@ internal class OppdragLagerRepositoryJdbcTest { @Autowired lateinit var jdbcTemplate: JdbcTemplate companion object { - - @Container var postgreSQLContainer = Containers.postgreSQLContainer + @Container + private val postgreSQLContainer = PostgreSQLContainer("postgres:latest") + + @DynamicPropertySource + @JvmStatic + fun registerDynamicProperties(registry: DynamicPropertyRegistry) { + registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl) + registry.add("spring.datasource.username", postgreSQLContainer::getUsername) + registry.add("spring.datasource.password", postgreSQLContainer::getPassword) + } } @BeforeEach diff --git a/src/test/kotlin/no/nav/familie/oppdrag/rest/OppdragControllerIntegrationTest.kt b/src/test/kotlin/no/nav/familie/oppdrag/rest/OppdragControllerIntegrationTest.kt index f0ed7363..b85ef52d 100644 --- a/src/test/kotlin/no/nav/familie/oppdrag/rest/OppdragControllerIntegrationTest.kt +++ b/src/test/kotlin/no/nav/familie/oppdrag/rest/OppdragControllerIntegrationTest.kt @@ -23,10 +23,15 @@ import org.testcontainers.junit.jupiter.Container import org.testcontainers.junit.jupiter.Testcontainers import org.testcontainers.shaded.org.awaitility.Awaitility.await import java.time.Duration +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase +import org.springframework.test.context.DynamicPropertyRegistry +import org.springframework.test.context.DynamicPropertySource +import org.testcontainers.containers.PostgreSQLContainer import kotlin.test.assertEquals @ActiveProfiles("dev") -@ContextConfiguration(initializers = [Containers.PostgresSQLInitializer::class, Containers.MQInitializer::class]) +@ContextConfiguration(initializers = [ Containers.MQInitializer::class]) +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @SpringBootTest(classes = [TestConfig::class], properties = ["spring.cloud.vault.enabled=false"]) @EnableJms @DisabledIfEnvironmentVariable(named = "CIRCLECI", matches = "true") @@ -38,8 +43,16 @@ internal class OppdragControllerIntegrationTest { @Autowired lateinit var oppdragLagerRepository: OppdragLagerRepository companion object { + @Container + private val postgreSQLContainer = PostgreSQLContainer("postgres:latest") - @Container var postgreSQLContainer = Containers.postgreSQLContainer + @DynamicPropertySource + @JvmStatic + fun registerDynamicProperties(registry: DynamicPropertyRegistry) { + registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl) + registry.add("spring.datasource.username", postgreSQLContainer::getUsername) + registry.add("spring.datasource.password", postgreSQLContainer::getPassword) + } @Container var ibmMQContainer = Containers.ibmMQContainer } @@ -83,7 +96,7 @@ internal class OppdragControllerIntegrationTest { oppdragController.sendOppdrag(utbetalingsoppdrag) oppdragLagerRepository.oppdaterStatus(utbetalingsoppdrag.oppdragId, OppdragStatus.KVITTERT_FUNKSJONELL_FEIL) - oppdragController.resentOppdrag(utbetalingsoppdrag.oppdragId) + oppdragController.resendOppdrag(utbetalingsoppdrag.oppdragId) assertOppdragStatus(utbetalingsoppdrag.oppdragId, OppdragStatus.KVITTERT_OK) } diff --git a/src/test/kotlin/no/nav/familie/oppdrag/rest/OppdragControllerTest.kt b/src/test/kotlin/no/nav/familie/oppdrag/rest/OppdragControllerTest.kt index d78c3704..8ab05f3b 100644 --- a/src/test/kotlin/no/nav/familie/oppdrag/rest/OppdragControllerTest.kt +++ b/src/test/kotlin/no/nav/familie/oppdrag/rest/OppdragControllerTest.kt @@ -4,8 +4,10 @@ import io.mockk.Runs import io.mockk.every import io.mockk.just import io.mockk.mockk +import io.mockk.runs import io.mockk.verify import no.nav.familie.kontrakter.felles.Ressurs +import no.nav.familie.kontrakter.felles.oppdrag.OppdragId import no.nav.familie.kontrakter.felles.oppdrag.OppdragStatus import no.nav.familie.kontrakter.felles.oppdrag.Opphør import no.nav.familie.kontrakter.felles.oppdrag.Utbetalingsoppdrag @@ -15,6 +17,7 @@ import no.nav.familie.oppdrag.iverksetting.OppdragSender import no.nav.familie.oppdrag.repository.OppdragLager import no.nav.familie.oppdrag.repository.OppdragLagerRepository import no.nav.familie.oppdrag.service.OppdragServiceImpl +import no.trygdeetaten.skjema.oppdrag.Mmel import org.junit.jupiter.api.Test import org.springframework.http.HttpStatus import java.math.BigDecimal @@ -81,6 +84,45 @@ internal class OppdragControllerTest { verify(exactly = 1) { oppdragLagerRepository.opprettOppdrag(any()) } } + @Test + fun `Skal kaste 409 feil om oppdrag allerede er kvittert ut`() { + val (oppdragLagerRepository, oppdragController) = mockkOppdragController(false) + val oppdragId = OppdragId(fagsystem = "BA", personIdent = "test", behandlingsId = "0") + val mocketOppdragLager = mockk() + + every { mocketOppdragLager.status } returns OppdragStatus.KVITTERT_OK + every { oppdragLagerRepository.hentOppdrag(oppdragId) } returns mocketOppdragLager + + val response = oppdragController.opprettManuellKvitteringPåOppdrag(oppdragId) + + assertEquals(HttpStatus.CONFLICT, response.statusCode) + assertEquals(Ressurs.Status.FEILET, response.body?.status) + + verify(exactly = 1) { oppdragLagerRepository.hentOppdrag(any()) } + } + + @Test + fun `Skal returnere 200 OK om oppdrag ble manuelt kvittert ut`() { + val (oppdragLagerRepository, oppdragController) = mockkOppdragController(false) + val oppdragId = OppdragId(fagsystem = "BA", personIdent = "test", behandlingsId = "0") + val mocketOppdragLager = mockk() + + every { mocketOppdragLager.status } returns OppdragStatus.LAGT_PÅ_KØ + every { mocketOppdragLager.versjon } returns 0 + every { mocketOppdragLager.kvitteringsmelding } returns Mmel().apply { beskrMelding = "Manuelt kvittert ut" } + + every { oppdragLagerRepository.hentOppdrag(oppdragId) } returns mocketOppdragLager + every { oppdragLagerRepository.oppdaterKvitteringsmelding(oppdragId, OppdragStatus.KVITTERT_OK, any(), 1) } just runs + + val response = oppdragController.opprettManuellKvitteringPåOppdrag(oppdragId) + + assertEquals(HttpStatus.OK, response.statusCode) + assertEquals("Manuelt kvittert ut", response.body?.melding) + + verify(exactly = 1) { oppdragLagerRepository.hentOppdrag(any()) } + verify(exactly = 1) { oppdragLagerRepository.oppdaterKvitteringsmelding(oppdragId, OppdragStatus.KVITTERT_OK, any(), 1) } + } + private fun mockkOppdragController(alleredeOpprettet: Boolean = false): Pair { val mapper = OppdragMapper() val oppdragSender = mockk(relaxed = true) diff --git a/src/test/kotlin/no/nav/familie/oppdrag/service/GrensesnittavstemmingServiceTest.kt b/src/test/kotlin/no/nav/familie/oppdrag/service/GrensesnittavstemmingServiceTest.kt index d06a47f9..eeb36e51 100644 --- a/src/test/kotlin/no/nav/familie/oppdrag/service/GrensesnittavstemmingServiceTest.kt +++ b/src/test/kotlin/no/nav/familie/oppdrag/service/GrensesnittavstemmingServiceTest.kt @@ -15,6 +15,9 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import java.time.LocalDateTime +import java.util.Optional +import no.nav.familie.oppdrag.repository.TidligereKjørtGrensesnittavstemming +import no.nav.familie.oppdrag.repository.TidligereKjørteGrensesnittavstemmingerRepository class GrensesnittavstemmingServiceTest { @@ -23,10 +26,17 @@ class GrensesnittavstemmingServiceTest { val avstemmingSender = mockk() val oppdragLagerRepository = mockk() - val grensesnittavstemmingService = GrensesnittavstemmingService(avstemmingSender, oppdragLagerRepository, antall) + val tidligereKjørteGrensesnittavstemmingerRepository = mockk() + val grensesnittavstemmingService = GrensesnittavstemmingService( + avstemmingSender = avstemmingSender, + oppdragLagerRepository = oppdragLagerRepository, + tidligereKjørteGrensesnittavstemmingerRepository = tidligereKjørteGrensesnittavstemmingerRepository, + antall = antall + ) val slot = mutableListOf() + @BeforeEach fun setUp() { slot.clear() @@ -34,21 +44,55 @@ class GrensesnittavstemmingServiceTest { oppdragLagerRepository.hentIverksettingerForGrensesnittavstemming(any(), any(), any(), antall, any()) } returns emptyList() + every { tidligereKjørteGrensesnittavstemmingerRepository.findById(any()) } returns Optional.empty() + justRun { avstemmingSender.sendGrensesnittAvstemming(capture(slot)) } } @Test fun `skal sende en melding på mq per batch`() { - every { oppdragLagerRepository.hentIverksettingerForGrensesnittavstemming(any(), any(), any(), antall, 0) } returns - listOf( - TestOppdragMedAvstemmingsdato.lagTestUtbetalingsoppdrag(LocalDateTime.now(), fagområde).somAvstemming, - TestOppdragMedAvstemmingsdato.lagTestUtbetalingsoppdrag(LocalDateTime.now(), fagområde).somAvstemming, + every { + oppdragLagerRepository.hentIverksettingerForGrensesnittavstemming( + any(), + any(), + any(), + antall, + 0 + ) + } returns + listOf( + TestOppdragMedAvstemmingsdato.lagTestUtbetalingsoppdrag( + LocalDateTime.now(), + fagområde + ).somAvstemming, + TestOppdragMedAvstemmingsdato.lagTestUtbetalingsoppdrag( + LocalDateTime.now(), + fagområde + ).somAvstemming, + ) + every { + oppdragLagerRepository.hentIverksettingerForGrensesnittavstemming( + any(), + any(), + any(), + antall, + 1 ) - every { oppdragLagerRepository.hentIverksettingerForGrensesnittavstemming(any(), any(), any(), antall, 1) } returns - listOf(TestOppdragMedAvstemmingsdato.lagTestUtbetalingsoppdrag(LocalDateTime.now(), fagområde).somAvstemming) + } returns + listOf( + TestOppdragMedAvstemmingsdato.lagTestUtbetalingsoppdrag( + LocalDateTime.now(), + fagområde + ).somAvstemming + ) grensesnittavstemmingService.utførGrensesnittavstemming( - GrensesnittavstemmingRequest(fagområde, LocalDateTime.now(), LocalDateTime.now()), + GrensesnittavstemmingRequest( + fagsystem = fagområde, + fra = LocalDateTime.now(), + til = LocalDateTime.now(), + avstemmingId = null + ), ) verify(exactly = 3) { diff --git a/src/test/kotlin/no/nav/familie/oppdrag/simulering/SimuleringTjenesteImplTest.kt b/src/test/kotlin/no/nav/familie/oppdrag/simulering/SimuleringTjenesteImplTest.kt index 6dc5bf59..dabb0da5 100644 --- a/src/test/kotlin/no/nav/familie/oppdrag/simulering/SimuleringTjenesteImplTest.kt +++ b/src/test/kotlin/no/nav/familie/oppdrag/simulering/SimuleringTjenesteImplTest.kt @@ -22,11 +22,15 @@ import org.testcontainers.junit.jupiter.Container import org.testcontainers.junit.jupiter.Testcontainers import java.math.BigDecimal import java.time.LocalDate +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase +import org.springframework.test.context.DynamicPropertyRegistry +import org.springframework.test.context.DynamicPropertySource +import org.testcontainers.containers.PostgreSQLContainer import kotlin.test.assertEquals import kotlin.test.assertTrue @ActiveProfiles("dev") -@ContextConfiguration(initializers = [Containers.PostgresSQLInitializer::class]) +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @SpringBootTest(classes = [SimuleringTjenesteImplTest.TestConfig::class], properties = ["spring.cloud.vault.enabled=false"]) @DisabledIfEnvironmentVariable(named = "CIRCLECI", matches = "true") @Testcontainers @@ -40,8 +44,16 @@ internal class SimuleringTjenesteImplTest { private lateinit var jdbcAggregateOperations: JdbcAggregateOperations companion object { - - @Container var postgreSQLContainer = Containers.postgreSQLContainer + @Container + private val postgreSQLContainer = PostgreSQLContainer("postgres:latest") + + @DynamicPropertySource + @JvmStatic + fun registerDynamicProperties(registry: DynamicPropertyRegistry) { + registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl) + registry.add("spring.datasource.username", postgreSQLContainer::getUsername) + registry.add("spring.datasource.password", postgreSQLContainer::getPassword) + } } @BeforeEach diff --git a/src/test/kotlin/no/nav/familie/oppdrag/util/ContainerTest.kt b/src/test/kotlin/no/nav/familie/oppdrag/util/ContainerTest.kt index bffd64e5..91c23909 100644 --- a/src/test/kotlin/no/nav/familie/oppdrag/util/ContainerTest.kt +++ b/src/test/kotlin/no/nav/familie/oppdrag/util/ContainerTest.kt @@ -13,33 +13,14 @@ import org.testcontainers.containers.PostgreSQLContainer class TestConfig object Containers { - - var postgreSQLContainer = MyPostgreSQLContainer("postgres:latest") - .withDatabaseName("familie-oppdrag") - .withUsername("postgres") - .withPassword("test") - .withExposedPorts(5432) - var ibmMQContainer = MyGeneralContainer("ibmcom/mq") .withEnv("LICENSE", "accept") .withEnv("MQ_QMGR_NAME", "QM1") .withEnv("persistance.enabled", "true") .withExposedPorts(1414) - class MyPostgreSQLContainer(imageName: String) : PostgreSQLContainer(imageName) class MyGeneralContainer(imageName: String) : GenericContainer(imageName) - class PostgresSQLInitializer : ApplicationContextInitializer { - - override fun initialize(configurableApplicationContext: ConfigurableApplicationContext) { - TestPropertyValues.of( - "spring.datasource.url=" + postgreSQLContainer.jdbcUrl, - "spring.datasource.username=" + postgreSQLContainer.username, - "spring.datasource.password=" + postgreSQLContainer.password, - ).applyTo(configurableApplicationContext.environment) - } - } - class MQInitializer : ApplicationContextInitializer { override fun initialize(configurableApplicationContext: ConfigurableApplicationContext) {