From b92b816f2464fb9fefff9684a1e74cd0affb1eb5 Mon Sep 17 00:00:00 2001 From: Alexander Hoem Rosbach <82815189+routsi@users.noreply.github.com> Date: Wed, 17 Jul 2024 13:52:16 +0200 Subject: [PATCH] =?UTF-8?q?Legg=20til=20status=20p=C3=A5=20brevredigering?= =?UTF-8?q?=20og=20patch=20endepunkt=20(#819)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/skribenten.adoc | 21 +++ gradle.properties | 8 +- .../pensjon/brev/skribenten/SkribentenApp.kt | 20 +-- .../nav/pensjon/brev/skribenten/model/Api.kt | 19 ++- .../pensjon/brev/skribenten/routes/SakBrev.kt | 39 ++--- .../services/BrevredigeringService.kt | 53 +++++-- .../services/BrevredigeringServiceTest.kt | 136 +++++++++--------- .../frontend/src/api/brev-queries.ts | 2 +- 8 files changed, 176 insertions(+), 122 deletions(-) diff --git a/docs/skribenten.adoc b/docs/skribenten.adoc index ea56442c5..c699a3f83 100644 --- a/docs/skribenten.adoc +++ b/docs/skribenten.adoc @@ -174,4 +174,25 @@ return Web --> Saksbehandler : Slettet brev +.... + +== Brevredigering status diagram + +[plantuml, target=img/brevredigering-state, format=svg] +.... +state "Under redigering" as Redigering +Redigering : redigeresAv : NavIdent + +[*] --> Redigering : Åpne brev (fra brevmeny) +Redigering --> Redigering : Forny lås (1m) +Redigering --> Kladd : Fortsett (knapp) + +Kladd --> Redigering : Åpne +Kladd : PDF +Kladd --> Klar : Lås brev for redigering (toggle) + +Klar --> Kladd : Lås brev for redigering (untoggle) +Klar : PDF + +Klar --> [*] : Ferdigstill .... \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index ab1e806c1..bfa33aa99 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,10 +4,10 @@ kotlin.daemon.jvmargs=-Xmx1G systemProp.javaTarget=17 systemProp.apiModelJavaTarget=17 systemProp.kotlinVersion=2.0.0 -systemProp.ktorVersion=2.3.11 -systemProp.kspVersion=1.0.21 -logbackVersion=1.5.2 -jupiterVersion=5.10.0 +systemProp.ktorVersion=2.3.12 +systemProp.kspVersion=1.0.23 +logbackVersion=1.5.6 +jupiterVersion=5.10.3 hamkrestVersion=1.8.0.1 logstashVersion=7.4 micrometerVersion=1.12.5 diff --git a/skribenten-backend/src/main/kotlin/no/nav/pensjon/brev/skribenten/SkribentenApp.kt b/skribenten-backend/src/main/kotlin/no/nav/pensjon/brev/skribenten/SkribentenApp.kt index 2f39a3cf2..e246ed0f0 100644 --- a/skribenten-backend/src/main/kotlin/no/nav/pensjon/brev/skribenten/SkribentenApp.kt +++ b/skribenten-backend/src/main/kotlin/no/nav/pensjon/brev/skribenten/SkribentenApp.kt @@ -73,14 +73,7 @@ private fun Application.skribentenApp(skribentenConfig: Config) { } } - install(ContentNegotiation) { - jackson { - registerModule(JavaTimeModule()) - registerModule(Edit.JacksonModule) - disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) - disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) - } - } + skribentenContenNegotiation() install(CORS) { allowMethod(HttpMethod.Options) @@ -102,3 +95,14 @@ private fun Application.skribentenApp(skribentenConfig: Config) { configureRouting(azureADConfig, skribentenConfig) configureMetrics() } + +fun Application.skribentenContenNegotiation() { + install(ContentNegotiation) { + jackson { + registerModule(JavaTimeModule()) + registerModule(Edit.JacksonModule) + disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + } + } +} diff --git a/skribenten-backend/src/main/kotlin/no/nav/pensjon/brev/skribenten/model/Api.kt b/skribenten-backend/src/main/kotlin/no/nav/pensjon/brev/skribenten/model/Api.kt index 70c2fd3f4..cd63423a7 100644 --- a/skribenten-backend/src/main/kotlin/no/nav/pensjon/brev/skribenten/model/Api.kt +++ b/skribenten-backend/src/main/kotlin/no/nav/pensjon/brev/skribenten/model/Api.kt @@ -1,5 +1,7 @@ package no.nav.pensjon.brev.skribenten.model +import com.fasterxml.jackson.annotation.JsonSubTypes +import com.fasterxml.jackson.annotation.JsonTypeInfo import no.nav.pensjon.brev.api.model.maler.BrevbakerBrevdata import no.nav.pensjon.brev.api.model.maler.Brevkode import no.nav.pensjon.brev.skribenten.letter.Edit @@ -22,6 +24,8 @@ object Api { val redigertBrev: Edit.Letter, ) + data class DelvisOppdaterBrevRequest(val laastForRedigering: Boolean?) + data class BrevInfo( val id: Long, val opprettetAv: String, @@ -29,8 +33,21 @@ object Api { val sistredigertAv: String, val sistredigert: Instant, val brevkode: Brevkode.Redigerbar, - val redigeresAv: String?, + val status: BrevStatus, + ) + + @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") + @JsonSubTypes( + JsonSubTypes.Type(BrevStatus.Kladd::class, name = "Kladd"), + JsonSubTypes.Type(BrevStatus.UnderRedigering::class, name = "UnderRedigering"), + JsonSubTypes.Type(BrevStatus.Klar::class, name = "Klar"), ) + sealed class BrevStatus { + data object Kladd : BrevStatus() + data class UnderRedigering(val redigeresAv: String) : BrevStatus() + data object Klar : BrevStatus() + } + data class BrevResponse( val info: BrevInfo, val redigertBrev: Edit.Letter, diff --git a/skribenten-backend/src/main/kotlin/no/nav/pensjon/brev/skribenten/routes/SakBrev.kt b/skribenten-backend/src/main/kotlin/no/nav/pensjon/brev/skribenten/routes/SakBrev.kt index 44f1cceb3..54b309a69 100644 --- a/skribenten-backend/src/main/kotlin/no/nav/pensjon/brev/skribenten/routes/SakBrev.kt +++ b/skribenten-backend/src/main/kotlin/no/nav/pensjon/brev/skribenten/routes/SakBrev.kt @@ -7,7 +7,6 @@ import io.ktor.server.response.* import io.ktor.server.routing.* import io.ktor.server.util.* import no.nav.pensjon.brev.skribenten.auth.AuthorizeAnsattSakTilgang -import no.nav.pensjon.brev.skribenten.db.Brevredigering import no.nav.pensjon.brev.skribenten.model.Api import no.nav.pensjon.brev.skribenten.model.Pen import no.nav.pensjon.brev.skribenten.services.BrevredigeringService @@ -21,7 +20,7 @@ fun Route.sakBrev(brevredigeringService: BrevredigeringService) = val spraak = request.spraak.toLanguageCode() val avsenderEnhetsId = request.avsenderEnhetsId?.takeIf { it.isNotBlank() } - brevredigeringService.opprettBrev(call, sak, request.brevkode, spraak, avsenderEnhetsId, request.saksbehandlerValg, ::mapBrev) + brevredigeringService.opprettBrev(call, sak, request.brevkode, spraak, avsenderEnhetsId, request.saksbehandlerValg) .onOk { brev -> call.respond(HttpStatusCode.Created, brev) }.onError { message, statusCode -> @@ -30,11 +29,11 @@ fun Route.sakBrev(brevredigeringService: BrevredigeringService) = } } - post("/{brevId}") { request -> + put("/{brevId}") { request -> val brevId = call.parameters.getOrFail("brevId") val sak: Pen.SakSelection = call.attributes[AuthorizeAnsattSakTilgang.sakKey] - brevredigeringService.oppdaterBrev(call, sak, brevId, request.saksbehandlerValg, request.redigertBrev, ::mapBrev) + brevredigeringService.oppdaterBrev(call, sak, brevId, request.saksbehandlerValg, request.redigertBrev) ?.onOk { brev -> call.respond(HttpStatusCode.OK, brev)} ?.onError { message, statusCode -> call.application.log.error("$statusCode - Feil ved oppdatering av brev ${brevId}: $message") @@ -43,13 +42,19 @@ fun Route.sakBrev(brevredigeringService: BrevredigeringService) = ?: call.respond(HttpStatusCode.NotFound, "Brev med brevid: $brevId ikke funnet") } + patch("/{brevId}") { request -> + val brevId = call.parameters.getOrFail("brevId") + brevredigeringService.delvisOppdaterBrev(brevId, request)?.also { call.respond(HttpStatusCode.OK, it) } + ?: call.respond(HttpStatusCode.NotFound, "Brev med id $brevId: ikke funnet") + } + delete("/{brevId}") { val brevId = call.parameters.getOrFail("brevId") if (brevredigeringService.slettBrev(brevId)) { call.respond(HttpStatusCode.NoContent) } else { - call.respond(HttpStatusCode.NotFound, "Brev med id $brevId ikke funnet") + call.respond(HttpStatusCode.NotFound, "Brev med id $brevId: ikke funnet") } } @@ -57,7 +62,7 @@ fun Route.sakBrev(brevredigeringService: BrevredigeringService) = val brevId = call.parameters.getOrFail("brevId") val sak: Pen.SakSelection = call.attributes[AuthorizeAnsattSakTilgang.sakKey] - brevredigeringService.hentBrev(call, sak, brevId, ::mapBrev) + brevredigeringService.hentBrev(call, sak, brevId) ?.onOk { brev -> call.respond(HttpStatusCode.OK, brev) }?.onError { message, statusCode -> @@ -72,7 +77,7 @@ fun Route.sakBrev(brevredigeringService: BrevredigeringService) = call.respond( HttpStatusCode.OK, - brevredigeringService.hentBrevForSak(sak.saksId, ::mapBrevInfo) + brevredigeringService.hentBrevForSak(sak.saksId) ) } @@ -104,26 +109,6 @@ fun Route.sakBrev(brevredigeringService: BrevredigeringService) = } } -internal fun mapBrev(brev: Brevredigering): Api.BrevResponse = with(brev) { - Api.BrevResponse( - info = mapBrevInfo(this), - redigertBrev = redigertBrev, - saksbehandlerValg = saksbehandlerValg, - ) -} - -private fun mapBrevInfo(brev: Brevredigering): Api.BrevInfo = with(brev) { - Api.BrevInfo( - id = id.value, - opprettetAv = opprettetAvNavIdent, - opprettet = opprettet, - sistredigertAv = sistRedigertAvNavIdent, - sistredigert = sistredigert, - brevkode = brevkode, - redigeresAv = redigeresAvNavIdent, - ) -} - private fun SpraakKode.toLanguageCode(): LanguageCode = when (this) { SpraakKode.NB -> LanguageCode.BOKMAL diff --git a/skribenten-backend/src/main/kotlin/no/nav/pensjon/brev/skribenten/services/BrevredigeringService.kt b/skribenten-backend/src/main/kotlin/no/nav/pensjon/brev/skribenten/services/BrevredigeringService.kt index 0eeb449ad..9c7870f5f 100644 --- a/skribenten-backend/src/main/kotlin/no/nav/pensjon/brev/skribenten/services/BrevredigeringService.kt +++ b/skribenten-backend/src/main/kotlin/no/nav/pensjon/brev/skribenten/services/BrevredigeringService.kt @@ -13,6 +13,7 @@ import no.nav.pensjon.brev.skribenten.letter.Edit import no.nav.pensjon.brev.skribenten.letter.toEdit import no.nav.pensjon.brev.skribenten.letter.toMarkup import no.nav.pensjon.brev.skribenten.letter.updateEditedLetter +import no.nav.pensjon.brev.skribenten.model.Api import no.nav.pensjon.brev.skribenten.model.Pen import no.nav.pensjon.brev.skribenten.model.Pen.SendRedigerbartBrevRequest import no.nav.pensjon.brev.skribenten.principal @@ -41,15 +42,14 @@ class BrevredigeringService( val logger: Logger = LoggerFactory.getLogger(BrevredigeringService::class.java) - suspend fun opprettBrev( + suspend fun opprettBrev( call: ApplicationCall, sak: Pen.SakSelection, brevkode: Brevkode.Redigerbar, spraak: LanguageCode, avsenderEnhetsId: String?, saksbehandlerValg: BrevbakerBrevdata, - mapper: Brevredigering.() -> T, - ): ServiceResult = + ): ServiceResult = harTilgangTilEnhet(call, avsenderEnhetsId) { rendreBrev(call, brevkode, spraak, sak, saksbehandlerValg, avsenderEnhetsId).map { letter -> transaction { @@ -66,19 +66,18 @@ class BrevredigeringService( sistredigert = Instant.now().truncatedTo(ChronoUnit.MILLIS) redigertBrev = letter.toEdit() sistRedigertAvNavIdent = call.principal().navIdent - }.mapper() + }.mapBrev() } } } - suspend fun oppdaterBrev( + suspend fun oppdaterBrev( call: ApplicationCall, sak: Pen.SakSelection, brevId: Long, nyeSaksbehandlerValg: BrevbakerBrevdata, nyttRedigertbrev: Edit.Letter, - mapper: Brevredigering.() -> T, - ): ServiceResult? = + ): ServiceResult? = newSuspendedTransaction { val brevredigering = Brevredigering.findById(brevId) @@ -91,11 +90,18 @@ class BrevredigeringService( sistredigert = Instant.now().truncatedTo(ChronoUnit.MILLIS) saksbehandlerValg = nyeSaksbehandlerValg sistRedigertAvNavIdent = call.principal().navIdent - }.mapper() + }.mapBrev() } } else null } + fun delvisOppdaterBrev(brevId: Long, patch: Api.DelvisOppdaterBrevRequest): Api.BrevResponse? = + transaction { + Brevredigering.findByIdAndUpdate(brevId) { brev -> + patch.laastForRedigering?.also { brev.laastForRedigering = it } + } + }?.mapBrev() + /** * Slett brev med id. * @return `true` om brevet ble slettet, false om brevet ikke eksisterer, @@ -112,20 +118,20 @@ class BrevredigeringService( } } - suspend fun hentBrev(call: ApplicationCall, sak: Pen.SakSelection, brevId: Long, mapper: Brevredigering.() -> T): ServiceResult? = + suspend fun hentBrev(call: ApplicationCall, sak: Pen.SakSelection, brevId: Long): ServiceResult? = newSuspendedTransaction { val brev = Brevredigering.findById(brevId) if (brev != null) { rendreBrev(call, brev.brevkode, brev.spraak, sak, brev.saksbehandlerValg, brev.avsenderEnhetId) .map { brev.redigertBrev.updateEditedLetter(it) } - .map { brev.apply { redigertBrev = it }.mapper() } + .map { brev.apply { redigertBrev = it }.mapBrev() } } else null } - fun hentBrevForSak(saksId: Long, mapper: Brevredigering.() -> T): List { + fun hentBrevForSak(saksId: Long): List { return transaction { - Brevredigering.find { BrevredigeringTable.saksId eq saksId }.map(mapper) + Brevredigering.find { BrevredigeringTable.saksId eq saksId }.map(::mapBrevInfo) } } @@ -229,4 +235,27 @@ class BrevredigeringService( } else null } + private fun Brevredigering.mapBrev(): Api.BrevResponse = + Api.BrevResponse( + info = mapBrevInfo(this), + redigertBrev = redigertBrev, + saksbehandlerValg = saksbehandlerValg, + ) + + private fun mapBrevInfo(brev: Brevredigering): Api.BrevInfo = with(brev) { + val redigeresAv = redigeresAvNavIdent + Api.BrevInfo( + id = id.value, + opprettetAv = opprettetAvNavIdent, + opprettet = opprettet, + sistredigertAv = sistRedigertAvNavIdent, + sistredigert = sistredigert, + brevkode = brevkode, + status = when { + laastForRedigering -> Api.BrevStatus.Klar + redigeresAv != null -> Api.BrevStatus.UnderRedigering(redigeresAv) + else -> Api.BrevStatus.Kladd + }, + ) + } } diff --git a/skribenten-backend/src/test/kotlin/no/nav/pensjon/brev/skribenten/services/BrevredigeringServiceTest.kt b/skribenten-backend/src/test/kotlin/no/nav/pensjon/brev/skribenten/services/BrevredigeringServiceTest.kt index 12fb385ab..d650a09d7 100644 --- a/skribenten-backend/src/test/kotlin/no/nav/pensjon/brev/skribenten/services/BrevredigeringServiceTest.kt +++ b/skribenten-backend/src/test/kotlin/no/nav/pensjon/brev/skribenten/services/BrevredigeringServiceTest.kt @@ -3,7 +3,6 @@ package no.nav.pensjon.brev.skribenten.services import io.ktor.http.* import io.ktor.server.application.* import io.mockk.* -import io.mockk.InternalPlatformDsl.toArray import kotlinx.coroutines.* import no.nav.pensjon.brev.api.model.LetterResponse import no.nav.pensjon.brev.api.model.maler.BrevbakerBrevdata @@ -20,7 +19,6 @@ import no.nav.pensjon.brev.skribenten.letter.updateEditedLetter import no.nav.pensjon.brev.skribenten.model.Api import no.nav.pensjon.brev.skribenten.model.Pen import no.nav.pensjon.brev.skribenten.principal -import no.nav.pensjon.brev.skribenten.routes.mapBrev import no.nav.pensjon.brevbaker.api.model.* import no.nav.pensjon.brevbaker.api.model.LetterMarkup.Block.Paragraph import no.nav.pensjon.brevbaker.api.model.LetterMarkup.ParagraphContent.Text.Literal @@ -28,7 +26,6 @@ import no.nav.pensjon.brevbaker.api.model.LetterMarkup.ParagraphContent.Text.Var import no.nav.pensjon.brevbaker.api.model.LetterMetadata import no.nav.pensjon.brevbaker.api.model.NAVEnhet import org.assertj.core.api.Assertions.assertThat -import org.jetbrains.exposed.sql.statements.api.ExposedBlob import org.jetbrains.exposed.sql.transactions.transaction import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.Assertions.assertEquals @@ -109,7 +106,7 @@ class BrevredigeringServiceTest { coEvery { harTilgangTilEnhet(any(), any(), any()) } returns ServiceResult.Ok(false) coEvery { harTilgangTilEnhet(any(), eq(principalNavIdent), eq(principalNavEnhetId)) } returns ServiceResult.Ok(true) } - private val service: BrevredigeringService = BrevredigeringService( + private val brevredigeringService: BrevredigeringService = BrevredigeringService( brevbakerService = brevbakerMock, penService = penService, navansattService = navAnsattService, @@ -125,21 +122,20 @@ class BrevredigeringServiceTest { @Test fun `non existing brevredingering returns null`(): Unit = runBlocking { - assertThat(service.hentBrev(callMock, sak, 99, ::mapBrev)).isNull() + assertThat(brevredigeringService.hentBrev(callMock, sak, 99)).isNull() } @Test fun `can create and fetch brevredigering`() = runBlocking { val saksbehandlerValg = GeneriskBrevData().apply { put("valg1", true) } val result = - service.opprettBrev( + brevredigeringService.opprettBrev( callMock, sak, Brevkode.Redigerbar.INFORMASJON_OM_SAKSBEHANDLINGSTID, LanguageCode.ENGLISH, principalNavEnhetId, - saksbehandlerValg, - ::mapBrev + saksbehandlerValg ) coVerify { @@ -153,7 +149,7 @@ class BrevredigeringServiceTest { } clearMocks() - assertEquals(result, service.hentBrev(callMock, sak, result.resultOrNull()!!.info.id, ::mapBrev)) + assertEquals(result, brevredigeringService.hentBrev(callMock, sak, result.resultOrNull()!!.info.id)) assertEquals(result.resultOrNull()?.info?.brevkode, Brevkode.Redigerbar.INFORMASJON_OM_SAKSBEHANDLINGSTID) assertEquals(result.resultOrNull()?.redigertBrev, letter.toEdit()) coVerify { @@ -170,14 +166,13 @@ class BrevredigeringServiceTest { @Test fun `cannot create brevredigering for a NavEnhet without access to it`(): Unit = runBlocking { val saksbehandlerValg = GeneriskBrevData().apply { put("valg1", true) } - val result = service.opprettBrev( + val result = brevredigeringService.opprettBrev( callMock, sak, Brevkode.Redigerbar.INFORMASJON_OM_SAKSBEHANDLINGSTID, LanguageCode.ENGLISH, "The Matrix", - saksbehandlerValg, - ::mapBrev + saksbehandlerValg ) assertThat(result).isInstanceOfSatisfying(ServiceResult.Error::class.java) { assertThat(it.statusCode).isEqualTo(HttpStatusCode.Forbidden) @@ -188,26 +183,24 @@ class BrevredigeringServiceTest { fun `can update brevredigering`() = runBlocking { val saksbehandlerValg = GeneriskBrevData().apply { put("valg1", true) } val original = - service.opprettBrev( + brevredigeringService.opprettBrev( callMock, sak, Brevkode.Redigerbar.INFORMASJON_OM_SAKSBEHANDLINGSTID, LanguageCode.ENGLISH, principalNavEnhetId, - saksbehandlerValg, - ::mapBrev + saksbehandlerValg ).resultOrNull()!! clearMocks() val nyeValg = GeneriskBrevData().apply { put("valg2", true) } - val oppdatert = service.oppdaterBrev( + val oppdatert = brevredigeringService.oppdaterBrev( callMock, sak, original.info.id, nyeValg, letter.toEdit(), - ::mapBrev, )?.resultOrNull()!! coVerify(exactly = 1) { @@ -220,7 +213,7 @@ class BrevredigeringServiceTest { ) } - assertThat(service.hentBrev(callMock, sak, original.info.id, ::mapBrev)) + assertThat(brevredigeringService.hentBrev(callMock, sak, original.info.id)) .isInstanceOfSatisfying(ServiceResult.Ok::class.java) { assertThat(it.result).isEqualTo(oppdatert) } @@ -232,14 +225,13 @@ class BrevredigeringServiceTest { fun `updates redigertBrev with fresh rendering from brevbaker`() = runBlocking { val saksbehandlerValg = GeneriskBrevData().apply { put("valg1", true) } val original = - service.opprettBrev( + brevredigeringService.opprettBrev( callMock, sak, Brevkode.Redigerbar.INFORMASJON_OM_SAKSBEHANDLINGSTID, LanguageCode.ENGLISH, principalNavEnhetId, - saksbehandlerValg, - ::mapBrev + saksbehandlerValg ).resultOrNull()!! val nyeValg = GeneriskBrevData().apply { put("valg2", true) } @@ -255,13 +247,12 @@ class BrevredigeringServiceTest { } returns ServiceResult.Ok(freshRender) val oppdatert = - service.oppdaterBrev( + brevredigeringService.oppdaterBrev( callMock, sak, original.info.id, nyeValg, letter.toEdit(), - ::mapBrev, )?.resultOrNull()!! assertNotEquals(original.redigertBrev, oppdatert.redigertBrev) @@ -272,7 +263,7 @@ class BrevredigeringServiceTest { fun `cannot update non-existing brevredigering`() = runBlocking { val saksbehandlerValg = GeneriskBrevData().apply { put("valg1", true) } val oppdatert = - service.oppdaterBrev(callMock, sak, 1099, saksbehandlerValg, letter.toEdit(), ::mapBrev) + brevredigeringService.oppdaterBrev(callMock, sak, 1099, saksbehandlerValg, letter.toEdit()) ?.resultOrNull() assertNull(oppdatert) @@ -300,7 +291,7 @@ class BrevredigeringServiceTest { val result = withTimeout(10.seconds) { - service.oppdaterBrev(callMock, sak, 2098, saksbehandlerValg, letter.toEdit(), ::mapBrev) + brevredigeringService.oppdaterBrev(callMock, sak, 2098, saksbehandlerValg, letter.toEdit()) } assertThat(result).isNull() @@ -310,25 +301,24 @@ class BrevredigeringServiceTest { fun `can delete brevredigering`(): Unit = runBlocking { val saksbehandlerValg = GeneriskBrevData().apply { put("valg1", true) } val result = - service.opprettBrev( + brevredigeringService.opprettBrev( callMock, sak, Brevkode.Redigerbar.INFORMASJON_OM_SAKSBEHANDLINGSTID, LanguageCode.ENGLISH, principalNavEnhetId, - saksbehandlerValg, - ::mapBrev + saksbehandlerValg ) - assertEquals(result, service.hentBrev(callMock, sak, result.resultOrNull()!!.info.id, ::mapBrev)) - assertTrue(service.slettBrev(result.resultOrNull()!!.info.id)) - assertThat(service.hentBrev(callMock, sak, result.resultOrNull()!!.info.id, ::mapBrev)).isNull() + assertEquals(result, brevredigeringService.hentBrev(callMock, sak, result.resultOrNull()!!.info.id)) + assertTrue(brevredigeringService.slettBrev(result.resultOrNull()!!.info.id)) + assertThat(brevredigeringService.hentBrev(callMock, sak, result.resultOrNull()!!.info.id)).isNull() } @Test fun `delete brevredigering returns false for non-existing brev`(): Unit = runBlocking { - assertThat(service.hentBrev(callMock, sak, 1337, ::mapBrev)).isNull() - assertFalse(service.slettBrev(1337)) + assertThat(brevredigeringService.hentBrev(callMock, sak, 1337)).isNull() + assertFalse(brevredigeringService.slettBrev(1337)) } @Test @@ -338,14 +328,13 @@ class BrevredigeringServiceTest { // val saksbehandlersValg = GeneriskBrevData().apply { put("valg", true) } - val serviceResult = service.opprettBrev( + val serviceResult = brevredigeringService.opprettBrev( call = callMock, sak = sak, brevkode = Brevkode.Redigerbar.INFORMASJON_OM_SAKSBEHANDLINGSTID, spraak = LanguageCode.ENGLISH, avsenderEnhetsId = principalNavEnhetId, - saksbehandlerValg = saksbehandlersValg, - mapper = ::mapBrev + saksbehandlerValg = saksbehandlersValg ) assertThat(serviceResult).isInstanceOf(ServiceResult.Ok::class.java) val result = serviceResult.resultOrNull()!! @@ -365,7 +354,7 @@ class BrevredigeringServiceTest { val pdf = "nesten en pdf".encodeToByteArray() stagePdf(pdf) - service.opprettPdf(callMock, result.info.id) + brevredigeringService.opprettPdf(callMock, result.info.id) coVerify { brevbakerMock.renderPdf(any(), eq(Brevkode.Redigerbar.INFORMASJON_OM_SAKSBEHANDLINGSTID), eq(LanguageCode.ENGLISH), any(), any(), any()) @@ -384,24 +373,16 @@ class BrevredigeringServiceTest { @Test fun `sletter relaterte documents ved sletting av brevredigering`(): Unit = runBlocking { - val brev = service.opprettBrev( - call = callMock, - sak = sak, - brevkode = Brevkode.Redigerbar.INFORMASJON_OM_SAKSBEHANDLINGSTID, - spraak = LanguageCode.ENGLISH, - avsenderEnhetsId = principalNavEnhetId, - saksbehandlerValg = GeneriskBrevData().apply { put("valg", true) }, - mapper = ::mapBrev - ).resultOrNull()!! + val brev = opprettBrev().resultOrNull()!! stagePdf("a real life pdf".encodeToByteArray()) - service.opprettPdf(callMock, brev.info.id) + brevredigeringService.opprettPdf(callMock, brev.info.id) transaction { assertThat(Document.find { DocumentTable.brevredigering eq brev.info.id }).hasSize(1) } - service.slettBrev(brev.info.id) + brevredigeringService.slettBrev(brev.info.id) transaction { assertThat(Brevredigering.findById(brev.info.id)).isNull() @@ -411,20 +392,12 @@ class BrevredigeringServiceTest { @Test fun `andre opprettPdf erstatter den forrige`(): Unit = runBlocking { - val brev = service.opprettBrev( - call = callMock, - sak = sak, - brevkode = Brevkode.Redigerbar.INFORMASJON_OM_SAKSBEHANDLINGSTID, - spraak = LanguageCode.ENGLISH, - avsenderEnhetsId = principalNavEnhetId, - saksbehandlerValg = GeneriskBrevData().apply { put("valg", true) }, - mapper = ::mapBrev - ).resultOrNull()!! + val brev = opprettBrev().resultOrNull()!! stagePdf("a real life pdf".encodeToByteArray()) - service.opprettPdf(callMock, brev.info.id) + brevredigeringService.opprettPdf(callMock, brev.info.id) stagePdf("the newest pdf".encodeToByteArray()) - service.opprettPdf(callMock, brev.info.id) + brevredigeringService.opprettPdf(callMock, brev.info.id) transaction { assertThat(Document.find { DocumentTable.brevredigering eq brev.info.id }).hasSize(1) @@ -434,19 +407,11 @@ class BrevredigeringServiceTest { @Test fun `dobbel oppretting av pdf er ikke mulig`(): Unit = runBlocking { - val brev = service.opprettBrev( - call = callMock, - sak = sak, - brevkode = Brevkode.Redigerbar.INFORMASJON_OM_SAKSBEHANDLINGSTID, - spraak = LanguageCode.ENGLISH, - avsenderEnhetsId = principalNavEnhetId, - saksbehandlerValg = GeneriskBrevData().apply { put("valg", true) }, - mapper = ::mapBrev - ).resultOrNull()!! + val brev = opprettBrev().resultOrNull()!! stagePdf("a real life pdf".encodeToByteArray()) - val jobs = awaitAll(*(0..<10).map { async(Dispatchers.IO) { service.opprettPdf(callMock, brev.info.id) } }.toTypedArray()) + val jobs = awaitAll(*(0..<10).map { async(Dispatchers.IO) { brevredigeringService.opprettPdf(callMock, brev.info.id) } }.toTypedArray()) jobs.forEach { println(String(it?.resultOrNull()!!)) } @@ -455,6 +420,39 @@ class BrevredigeringServiceTest { } } + @Test + fun `status er kladd om brev ikke er laast og ikke redigeres`(): Unit = runBlocking { + val brev = opprettBrev().resultOrNull()!! + assertThat(brev.info.status).isEqualTo(Api.BrevStatus.Kladd) + } + + @Test + fun `status er Klar om brev er laast`(): Unit = runBlocking { + val brev = opprettBrev().resultOrNull()!! + val oppdatert = brevredigeringService.delvisOppdaterBrev(brev.info.id, Api.DelvisOppdaterBrevRequest(laastForRedigering = true)) + assertThat(oppdatert?.info?.status).isEqualTo(Api.BrevStatus.Klar) + } + + @Test + fun `status er UnderRedigering om brev ikke er laast og redigeres`(): Unit = runBlocking { + val brev = opprettBrev().resultOrNull()!! + transaction { + Brevredigering[brev.info.id].redigeresAvNavIdent = "Morpheus" + } + assertThat( + brevredigeringService.hentBrev(callMock, sak, brev.info.id)?.resultOrNull()?.info?.status + ).isEqualTo(Api.BrevStatus.UnderRedigering("Morpheus")) + } + + private suspend fun opprettBrev() = brevredigeringService.opprettBrev( + call = callMock, + sak = sak, + brevkode = Brevkode.Redigerbar.INFORMASJON_OM_SAKSBEHANDLINGSTID, + spraak = LanguageCode.ENGLISH, + avsenderEnhetsId = principalNavEnhetId, + saksbehandlerValg = GeneriskBrevData().apply { put("valg", true) } + ) + private fun stagePdf(pdf: ByteArray) { coEvery { brevbakerMock.renderPdf(any(), any(), any(), any(), any(), any()) } returns ServiceResult.Ok( LetterResponse( diff --git a/skribenten-web/frontend/src/api/brev-queries.ts b/skribenten-web/frontend/src/api/brev-queries.ts index 0b2c9a11d..42cc72b5f 100644 --- a/skribenten-web/frontend/src/api/brev-queries.ts +++ b/skribenten-web/frontend/src/api/brev-queries.ts @@ -38,7 +38,7 @@ export async function createBrev(saksId: string, request: OpprettBrevRequest) { } export async function updateBrev(saksId: string, brevId: number, request: OppdaterBrevRequest) { - return (await axios.post(`${SKRIBENTEN_API_BASE_PATH}/sak/${saksId}/brev/${brevId}`, request)).data; + return (await axios.put(`${SKRIBENTEN_API_BASE_PATH}/sak/${saksId}/brev/${brevId}`, request)).data; } export function useModelSpecification(brevkode: string, select: (data: LetterModelSpecification) => T) {