Skip to content

Commit

Permalink
Legg til status på brevredigering og patch endepunkt (#819)
Browse files Browse the repository at this point in the history
  • Loading branch information
routsi authored Jul 17, 2024
1 parent d1537fe commit b92b816
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 122 deletions.
21 changes: 21 additions & 0 deletions docs/skribenten.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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
....
8 changes: 4 additions & 4 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
}
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -22,15 +24,30 @@ object Api {
val redigertBrev: Edit.Letter,
)

data class DelvisOppdaterBrevRequest(val laastForRedigering: Boolean?)

data class BrevInfo(
val id: Long,
val opprettetAv: String,
val opprettet: Instant,
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 ->
Expand All @@ -30,11 +29,11 @@ fun Route.sakBrev(brevredigeringService: BrevredigeringService) =
}
}

post<Api.OppdaterBrevRequest>("/{brevId}") { request ->
put<Api.OppdaterBrevRequest>("/{brevId}") { request ->
val brevId = call.parameters.getOrFail<Long>("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")
Expand All @@ -43,21 +42,27 @@ fun Route.sakBrev(brevredigeringService: BrevredigeringService) =
?: call.respond(HttpStatusCode.NotFound, "Brev med brevid: $brevId ikke funnet")
}

patch<Api.DelvisOppdaterBrevRequest>("/{brevId}") { request ->
val brevId = call.parameters.getOrFail<Long>("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<Long>("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")
}
}

get("/{brevId}") {
val brevId = call.parameters.getOrFail<Long>("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 ->
Expand All @@ -72,7 +77,7 @@ fun Route.sakBrev(brevredigeringService: BrevredigeringService) =

call.respond(
HttpStatusCode.OK,
brevredigeringService.hentBrevForSak(sak.saksId, ::mapBrevInfo)
brevredigeringService.hentBrevForSak(sak.saksId)
)
}

Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -41,15 +42,14 @@ class BrevredigeringService(

val logger: Logger = LoggerFactory.getLogger(BrevredigeringService::class.java)

suspend fun <T : Any> opprettBrev(
suspend fun opprettBrev(
call: ApplicationCall,
sak: Pen.SakSelection,
brevkode: Brevkode.Redigerbar,
spraak: LanguageCode,
avsenderEnhetsId: String?,
saksbehandlerValg: BrevbakerBrevdata,
mapper: Brevredigering.() -> T,
): ServiceResult<T> =
): ServiceResult<Api.BrevResponse> =
harTilgangTilEnhet(call, avsenderEnhetsId) {
rendreBrev(call, brevkode, spraak, sak, saksbehandlerValg, avsenderEnhetsId).map { letter ->
transaction {
Expand All @@ -66,19 +66,18 @@ class BrevredigeringService(
sistredigert = Instant.now().truncatedTo(ChronoUnit.MILLIS)
redigertBrev = letter.toEdit()
sistRedigertAvNavIdent = call.principal().navIdent
}.mapper()
}.mapBrev()
}
}
}

suspend fun <T : Any> oppdaterBrev(
suspend fun oppdaterBrev(
call: ApplicationCall,
sak: Pen.SakSelection,
brevId: Long,
nyeSaksbehandlerValg: BrevbakerBrevdata,
nyttRedigertbrev: Edit.Letter,
mapper: Brevredigering.() -> T,
): ServiceResult<T>? =
): ServiceResult<Api.BrevResponse>? =
newSuspendedTransaction {
val brevredigering = Brevredigering.findById(brevId)

Expand All @@ -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,
Expand All @@ -112,20 +118,20 @@ class BrevredigeringService(
}
}

suspend fun <T : Any> hentBrev(call: ApplicationCall, sak: Pen.SakSelection, brevId: Long, mapper: Brevredigering.() -> T): ServiceResult<T>? =
suspend fun hentBrev(call: ApplicationCall, sak: Pen.SakSelection, brevId: Long): ServiceResult<Api.BrevResponse>? =
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 <T : Any> hentBrevForSak(saksId: Long, mapper: Brevredigering.() -> T): List<T> {
fun hentBrevForSak(saksId: Long): List<Api.BrevInfo> {
return transaction {
Brevredigering.find { BrevredigeringTable.saksId eq saksId }.map(mapper)
Brevredigering.find { BrevredigeringTable.saksId eq saksId }.map(::mapBrevInfo)
}
}

Expand Down Expand Up @@ -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
},
)
}
}
Loading

0 comments on commit b92b816

Please sign in to comment.