Skip to content

Commit

Permalink
IS-2577: Add dokarkivclient for journalforing
Browse files Browse the repository at this point in the history
  • Loading branch information
eirikdahlen committed Aug 8, 2024
1 parent 06f0098 commit 5149c35
Show file tree
Hide file tree
Showing 21 changed files with 472 additions and 5 deletions.
4 changes: 4 additions & 0 deletions .nais/naiserator-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,7 @@ spec:
value: "dev-fss.pdl.pdl-api"
- name: PDL_URL
value: "https://pdl-api.dev-fss-pub.nais.io/graphql"
- name: DOKARKIV_CLIENT_ID
value: "dev-fss.teamdokumenthandtering.dokarkiv-q1"
- name: DOKARKIV_URL
value: "https://dokarkiv.dev-fss-pub.nais.io"
4 changes: 4 additions & 0 deletions .nais/naiserator-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,7 @@ spec:
value: "prod-fss.pdl.pdl-api"
- name: PDL_URL
value: "https://pdl-api.prod-fss-pub.nais.io/graphql"
- name: DOKARKIV_CLIENT_ID
value: "prod-fss.teamdokumenthandtering.dokarkiv"
- name: DOKARKIV_URL
value: "https://dokarkiv.prod-fss-pub.nais.io"
4 changes: 4 additions & 0 deletions src/main/kotlin/no/nav/syfo/ApplicationEnvironment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ data class Environment(
baseUrl = getEnvVar("PDL_URL"),
clientId = getEnvVar("PDL_CLIENT_ID")
),
dokarkiv = ClientEnvironment(
baseUrl = getEnvVar("DOKARKIV_URL"),
clientId = getEnvVar("DOKARKIV_CLIENT_ID")
),
),
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package no.nav.syfo.domain

import no.nav.syfo.aktivitetskrav.api.DocumentComponentDTO
import no.nav.syfo.infrastructure.clients.dokarkiv.dto.BrevkodeType
import no.nav.syfo.infrastructure.clients.dokarkiv.dto.JournalpostType
import java.time.LocalDate
import java.time.OffsetDateTime
import java.util.UUID
Expand All @@ -24,7 +25,7 @@ sealed class ManglendeMedvirkningVurdering(val status: Status) : IManglendeMedvi
override val createdAt: OffsetDateTime,
override val begrunnelse: String,
override val document: List<DocumentComponentDTO>,
override val journalpostId: JournalpostId?,
override val journalpostId: JournalpostId? = null,
val varsel: Varsel,
) : ManglendeMedvirkningVurdering(Status.FORHANDSVARSEL)

Expand All @@ -35,7 +36,7 @@ sealed class ManglendeMedvirkningVurdering(val status: Status) : IManglendeMedvi
override val createdAt: OffsetDateTime,
override val begrunnelse: String,
override val document: List<DocumentComponentDTO>,
override val journalpostId: JournalpostId?,
override val journalpostId: JournalpostId? = null,
) : ManglendeMedvirkningVurdering(Status.OPPFYLT)

data class Stans(
Expand All @@ -45,7 +46,7 @@ sealed class ManglendeMedvirkningVurdering(val status: Status) : IManglendeMedvi
override val createdAt: OffsetDateTime,
override val begrunnelse: String,
override val document: List<DocumentComponentDTO>,
override val journalpostId: JournalpostId?,
override val journalpostId: JournalpostId? = null,
) : ManglendeMedvirkningVurdering(Status.STANS)

data class IkkeAktuell(
Expand All @@ -55,7 +56,7 @@ sealed class ManglendeMedvirkningVurdering(val status: Status) : IManglendeMedvi
override val createdAt: OffsetDateTime,
override val begrunnelse: String,
override val document: List<DocumentComponentDTO>,
override val journalpostId: JournalpostId?,
override val journalpostId: JournalpostId? = null,
) : ManglendeMedvirkningVurdering(Status.IKKE_AKTUELL)
}

Expand All @@ -71,3 +72,20 @@ data class Varsel(
val createdAt: OffsetDateTime,
val svarfrist: LocalDate,
)

fun Status.getDokumentTittel(): String = when (this) {
Status.FORHANDSVARSEL -> "Forhåndsvarsel om stans av sykepenger"
Status.OPPFYLT, Status.IKKE_AKTUELL -> "Vurdering av § 8-8 manglende medvirkning"
Status.STANS -> "Innstilling om stans"
}

fun Status.getBrevkode(): BrevkodeType = when (this) {
Status.FORHANDSVARSEL -> BrevkodeType.MANGLENDE_MEDVIRKNING_FORHANDSVARSEL
Status.OPPFYLT, Status.IKKE_AKTUELL -> BrevkodeType.MANGLENDE_MEDVIRKNING_VURDERING
Status.STANS -> BrevkodeType.MANGLENDE_MEDVIRKNING_STANS
}

fun Status.getJournalpostType(): JournalpostType = when (this) {
Status.FORHANDSVARSEL, Status.OPPFYLT, Status.IKKE_AKTUELL -> JournalpostType.UTGAAENDE
Status.STANS -> JournalpostType.NOTAT
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package no.nav.syfo.infrastructure.clients
data class ClientsEnvironment(
val istilgangskontroll: ClientEnvironment,
val pdl: ClientEnvironment,
val dokarkiv: ClientEnvironment,
)

data class ClientEnvironment(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package no.nav.syfo.infrastructure.clients.dokarkiv

import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.plugins.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.micrometer.core.instrument.Counter
import net.logstash.logback.argument.StructuredArguments
import no.nav.syfo.infrastructure.clients.ClientEnvironment
import no.nav.syfo.infrastructure.clients.azuread.AzureAdClient
import no.nav.syfo.infrastructure.bearerHeader
import no.nav.syfo.infrastructure.clients.dokarkiv.dto.JournalpostRequest
import no.nav.syfo.infrastructure.clients.dokarkiv.dto.JournalpostResponse
import no.nav.syfo.infrastructure.clients.httpClientDefault
import no.nav.syfo.infrastructure.metric.METRICS_NS
import no.nav.syfo.infrastructure.metric.METRICS_REGISTRY
import org.slf4j.LoggerFactory

class DokarkivClient(
private val azureAdClient: AzureAdClient,
private val dokarkivEnvironment: ClientEnvironment,
private val httpClient: HttpClient = httpClientDefault(),
) {
private val journalpostUrl: String = "${dokarkivEnvironment.baseUrl}$JOURNALPOST_PATH"

suspend fun journalfor(
journalpostRequest: JournalpostRequest,
): JournalpostResponse {
val token = azureAdClient.getSystemToken(dokarkivEnvironment.clientId)?.accessToken
?: throw RuntimeException("Failed to Journalfor Journalpost: No token was found")
return try {
val response: HttpResponse = httpClient.post(journalpostUrl) {
parameter(JOURNALPOST_PARAM_STRING, JOURNALPOST_PARAM_VALUE)
header(HttpHeaders.Authorization, bearerHeader(token))
accept(ContentType.Application.Json)
contentType(ContentType.Application.Json)
setBody(journalpostRequest)
}
val journalpostResponse = response.body<JournalpostResponse>()
Metrics.COUNT_CALL_DOKARKIV_JOURNALPOST_SUCCESS.increment()
journalpostResponse
} catch (e: ClientRequestException) {
if (e.response.status == HttpStatusCode.Conflict) {
val journalpostResponse = e.response.body<JournalpostResponse>()
log.warn("Journalpost med id ${journalpostResponse.journalpostId} lagret fra før (409 Conflict)")
Metrics.COUNT_CALL_DOKARKIV_JOURNALPOST_CONFLICT.increment()
journalpostResponse
} else {
handleUnexpectedResponseException(e.response, e.message)
throw e
}
} catch (e: ServerResponseException) {
handleUnexpectedResponseException(e.response, e.message)
throw e
}
}

private fun handleUnexpectedResponseException(
response: HttpResponse,
message: String?,
) {
log.error(
"Error while requesting Dokarkiv to Journalpost PDF with {}, {}",
StructuredArguments.keyValue("statusCode", response.status.value.toString()),
StructuredArguments.keyValue("message", message),
)
Metrics.COUNT_CALL_DOKARKIV_JOURNALPOST_FAIL.increment()
}

companion object {
private const val JOURNALPOST_PATH = "/rest/journalpostapi/v1/journalpost"
private const val JOURNALPOST_PARAM_STRING = "forsoekFerdigstill"
private const val JOURNALPOST_PARAM_VALUE = true
private val log = LoggerFactory.getLogger(DokarkivClient::class.java)
}
}

private class Metrics {
companion object {
const val CALL_DOKARKIV_BASE = "${METRICS_NS}_call_dokarkiv"

const val CALL_DOKARKIV_JOURNALPOST_BASE = "${CALL_DOKARKIV_BASE}_journalpost"
const val CALL_DOKARKIV_JOURNALPOST_SUCCESS = "${CALL_DOKARKIV_JOURNALPOST_BASE}_success_count"
const val CALL_DOKARKIV_JOURNALPOST_FAIL = "${CALL_DOKARKIV_JOURNALPOST_BASE}_fail_count"

val COUNT_CALL_DOKARKIV_JOURNALPOST_SUCCESS: Counter = Counter
.builder(CALL_DOKARKIV_JOURNALPOST_SUCCESS)
.description("Counts the number of successful calls to Dokarkiv - Journalpost")
.register(METRICS_REGISTRY)
val COUNT_CALL_DOKARKIV_JOURNALPOST_FAIL: Counter = Counter
.builder(CALL_DOKARKIV_JOURNALPOST_FAIL)
.description("Counts the number of failed calls to Dokarkiv - Journalpost")
.register(METRICS_REGISTRY)

const val CALL_DOKARKIV_JOURNALPOST_CONFLICT = "${CALL_DOKARKIV_JOURNALPOST_BASE}_conflict_count"
val COUNT_CALL_DOKARKIV_JOURNALPOST_CONFLICT: Counter = Counter
.builder(CALL_DOKARKIV_JOURNALPOST_CONFLICT)
.description("Counts the number of calls to Dokarkiv - Journalpost resulting in 409 Conflict")
.register(METRICS_REGISTRY)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package no.nav.syfo.infrastructure.clients.dokarkiv.dto

data class AvsenderMottaker private constructor(
val id: String?,
val idType: String?,
val navn: String? = null,
) {
companion object {
fun create(
id: String?,
idType: BrukerIdType?,
navn: String? = null,
) = AvsenderMottaker(
id = id,
idType = idType?.value,
navn = navn
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package no.nav.syfo.infrastructure.clients.dokarkiv.dto

enum class BrukerIdType(
val value: String,
) {
PERSON_IDENT("FNR"),
}

data class Bruker private constructor(
val id: String,
val idType: String,
) {
companion object {
fun create(
id: String,
idType: BrukerIdType,
) = Bruker(
id = id,
idType = idType.value
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package no.nav.syfo.infrastructure.clients.dokarkiv.dto

enum class BrevkodeType(
val value: String,
) {
MANGLENDE_MEDVIRKNING_FORHANDSVARSEL("OPPF_MANGLENDE_MEDVIRKNING_FORHANDSVARSEL"),
MANGLENDE_MEDVIRKNING_VURDERING("OPPF_MANGLENDE_MEDVIRKNING_VURDERING"),
MANGLENDE_MEDVIRKNING_STANS("OPPF_MANGLENDE_MEDVIRKNING_STANS"),
}

data class Dokument private constructor(
val brevkode: String,
val dokumentKategori: String? = null,
val dokumentvarianter: List<Dokumentvariant>,
val tittel: String? = null,
) {
companion object {
fun create(
brevkode: BrevkodeType,
dokumentvarianter: List<Dokumentvariant>,
tittel: String? = null,
) = Dokument(
brevkode = brevkode.value,
dokumentvarianter = dokumentvarianter,
tittel = tittel,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package no.nav.syfo.infrastructure.clients.dokarkiv.dto

data class DokumentInfo(
val brevkode: String? = null,
val dokumentInfoId: Int? = null,
val tittel: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package no.nav.syfo.infrastructure.clients.dokarkiv.dto

enum class FiltypeType(
val value: String,
) {
PDFA("PDFA"),
}

enum class VariantformatType(
val value: String,
) {
ARKIV("ARKIV"),
}

const val DOKUMENTVARIANT_FILNAVN_MAX_LENGTH = 200

data class Dokumentvariant private constructor(
val filnavn: String,
val filtype: String,
val fysiskDokument: ByteArray,
val variantformat: String,
) {
companion object {
fun create(
filnavn: String,
filtype: FiltypeType,
fysiskDokument: ByteArray,
variantformat: VariantformatType,
): Dokumentvariant {
if ((filnavn.length + filtype.value.length) >= DOKUMENTVARIANT_FILNAVN_MAX_LENGTH) {
throw IllegalArgumentException("Filnavn of Dokumentvariant is too long, max size is $DOKUMENTVARIANT_FILNAVN_MAX_LENGTH")
}
return Dokumentvariant(
filnavn = filnavn,
filtype = filtype.value,
fysiskDokument = fysiskDokument,
variantformat = variantformat.value,
)
}
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as Dokumentvariant

if (filnavn != other.filnavn) return false
if (filtype != other.filtype) return false
if (!fysiskDokument.contentEquals(other.fysiskDokument)) return false
if (variantformat != other.variantformat) return false

return true
}

override fun hashCode(): Int {
var result = filnavn.hashCode()
result = 31 * result + filtype.hashCode()
result = 31 * result + fysiskDokument.contentHashCode()
result = 31 * result + variantformat.hashCode()
return result
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package no.nav.syfo.infrastructure.clients.dokarkiv.dto

const val JOURNALFORENDE_ENHET = 9999

enum class JournalpostType {
UTGAAENDE,
NOTAT,
}

enum class JournalpostTema(val value: String) {
OPPFOLGING("OPP"),
}

data class JournalpostRequest(
val avsenderMottaker: AvsenderMottaker,
val tittel: String,
val bruker: Bruker? = null,
val dokumenter: List<Dokument>,
val journalfoerendeEnhet: Int? = JOURNALFORENDE_ENHET,
val journalpostType: String,
val tema: String = JournalpostTema.OPPFOLGING.value,
val sak: Sak = Sak(),
val eksternReferanseId: String,
val overstyrInnsynsregler: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package no.nav.syfo.infrastructure.clients.dokarkiv.dto

data class JournalpostResponse(
val dokumenter: List<DokumentInfo>? = null,
val journalpostId: Int,
val journalpostferdigstilt: Boolean? = null,
val journalstatus: String,
val melding: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package no.nav.syfo.infrastructure.clients.dokarkiv.dto

enum class SaksType(val value: String) {
GENERELL("GENERELL_SAK"),
}

data class Sak(
val sakstype: String = SaksType.GENERELL.value,
)
Loading

0 comments on commit 5149c35

Please sign in to comment.