-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
EY-4842: Opprettet service for utsending av brev #6601
Changes from all commits
05c6e4a
95ac964
fe07685
5cc3cb9
b57e0e8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package no.nav.etterlatte.behandling.jobs.brevjobber | ||
|
||
import no.nav.etterlatte.Context | ||
import no.nav.etterlatte.Kontekst | ||
import no.nav.etterlatte.behandling.jobs.brevjobber.ArbeidStatus.FEILET | ||
import no.nav.etterlatte.behandling.jobs.brevjobber.ArbeidStatus.FERDIG | ||
import no.nav.etterlatte.behandling.jobs.brevjobber.ArbeidStatus.PAAGAAENDE | ||
import no.nav.etterlatte.inTransaction | ||
import no.nav.etterlatte.libs.ktor.token.BrukerTokenInfo | ||
import no.nav.etterlatte.libs.ktor.token.HardkodaSystembruker | ||
import org.slf4j.LoggerFactory | ||
|
||
class BrevutsendelseJob( | ||
private val arbeidstabellDao: ArbeidstabellDao, | ||
private val brevutsendelseService: BrevutsendelseService, | ||
) { | ||
private val saksbehandler: BrukerTokenInfo = HardkodaSystembruker.oppgave | ||
|
||
private val logger = LoggerFactory.getLogger(this::class.java) | ||
|
||
fun setupKontekstAndRun(context: Context) { | ||
Kontekst.set(context) | ||
run() | ||
} | ||
|
||
// TODO er jobber egentlig riktig begrep her - blir kanskje litt for generelt i denne sammenheng? Burde tabellen heller hete brevutsendelse? | ||
// TODO mer logging må på plass | ||
private fun run() { | ||
logger.info("Starter jobb for masseutsendelse av brev") | ||
|
||
val brevutsendelser = inTransaction { arbeidstabellDao.hentKlareJobber(ANTALL_SAKER, EKSKLUDERTE_SAKER) } | ||
logger.info("Hentet ${brevutsendelser.size} brevutsendelser som er klare for prosessering") | ||
|
||
brevutsendelser.forEach { brevutsendelse -> | ||
try { | ||
inTransaction { | ||
val paagaaendeBrevutsendelse = oppdaterStatus(brevutsendelse, PAAGAAENDE) | ||
brevutsendelseService.prosesserBrevutsendelse(paagaaendeBrevutsendelse, saksbehandler) | ||
oppdaterStatus(paagaaendeBrevutsendelse, FERDIG) | ||
} | ||
} catch (e: Exception) { | ||
// TODO ønsker nok å lagre ned exception her | ||
oppdaterStatus(brevutsendelse, FEILET) | ||
logger.error("Feilet under brevutsendelse av type ${brevutsendelse.type.name} for sak ${brevutsendelse.sakId}", e) | ||
} | ||
} | ||
} | ||
|
||
// TODO oppdater status eller opprett ny rad for hver status? | ||
private fun oppdaterStatus( | ||
jobb: Arbeidsjobb, | ||
status: ArbeidStatus, | ||
) = arbeidstabellDao.oppdaterJobb(jobb.oppdaterStatus(status)) | ||
|
||
// TODO burde dette heller håndteres fra en tabell slik at det kan oppdateres uten å endre koden? | ||
companion object { | ||
val ANTALL_SAKER: Long = 1 | ||
val EKSKLUDERTE_SAKER: List<Long> = emptyList() | ||
} | ||
Comment on lines
+55
to
+59
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alternativ nais config? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. trenger vi ekskluderte saker egentlig? hvis ikke bare å droppe det vel er bare unødvendig kompleksitet |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package no.nav.etterlatte.behandling.jobs.brevjobber | ||
|
||
import kotlinx.coroutines.runBlocking | ||
import no.nav.etterlatte.behandling.jobs.brevjobber.SjekkGyldigBrevMottakerResultat.GYLDIG_MOTTAKER | ||
import no.nav.etterlatte.behandling.klienter.BrevApiKlient | ||
import no.nav.etterlatte.brev.BrevParametre | ||
import no.nav.etterlatte.brev.SaksbehandlerOgAttestant | ||
import no.nav.etterlatte.brev.model.FerdigstillJournalFoerOgDistribuerOpprettetBrev | ||
import no.nav.etterlatte.brev.model.Spraak | ||
import no.nav.etterlatte.libs.common.feilhaandtering.InternfeilException | ||
import no.nav.etterlatte.libs.common.logging.withLogContext | ||
import no.nav.etterlatte.libs.common.oppgave.OppgaveIntern | ||
import no.nav.etterlatte.libs.common.oppgave.OppgaveType | ||
import no.nav.etterlatte.libs.common.person.maskerFnr | ||
import no.nav.etterlatte.libs.common.sak.Sak | ||
import no.nav.etterlatte.libs.ktor.token.BrukerTokenInfo | ||
import no.nav.etterlatte.oppgave.OppgaveService | ||
import no.nav.etterlatte.sak.SakService | ||
import org.slf4j.LoggerFactory | ||
|
||
class BrevutsendelseService( | ||
private val sakService: SakService, | ||
private val oppgaveService: OppgaveService, | ||
private val sjekkBrevMottakerService: SjekkBrevMottakerService, | ||
private val brevKlient: BrevApiKlient, | ||
) { | ||
private val logger = LoggerFactory.getLogger(this::class.java) | ||
|
||
fun prosesserBrevutsendelse( | ||
brevutsendelse: Arbeidsjobb, | ||
brukerTokenInfo: BrukerTokenInfo, | ||
) { | ||
withLogContext(kv = mdcVerdier(brevutsendelse)) { | ||
logger.info("Starter å prosessering brevutsendelse av type ${brevutsendelse.type.name} for sak ${brevutsendelse.sakId}") | ||
|
||
val sak = hentSak(brevutsendelse) | ||
val gyldigBrevMottakerResultat = sjekkBrevMottakerService.sjekkOmPersonErGyldigBrevmottaker(sak, brukerTokenInfo) | ||
|
||
if (gyldigBrevMottakerResultat == GYLDIG_MOTTAKER) { | ||
sendBrev(sak, brevutsendelse, brukerTokenInfo) | ||
// TODO hvis noe feiler her, må manuell oppgave opprettes | ||
} else { | ||
logger.info("Manuell oppgave opprettes i sak ${sak.id} fordi mottaker ikke var gyldig: ${gyldigBrevMottakerResultat.name}") | ||
opprettManuellOppgave(brevutsendelse) | ||
} | ||
|
||
logger.info("Prosessering av brevutsendelse i sak ${brevutsendelse.sakId} er fullført") | ||
|
||
// TODO burde returnere et objekt her som sier noe om hva som ble resultatet (brev sendt, manuell oppgave opprettet etc) | ||
} | ||
} | ||
|
||
private fun mdcVerdier(brevutsendelse: Arbeidsjobb) = | ||
mapOf( | ||
"sakId" to brevutsendelse.sakId.toString(), | ||
"jobbType" to brevutsendelse.type.name, | ||
) | ||
|
||
private fun hentSak(brevutsendelse: Arbeidsjobb) = | ||
( | ||
sakService.finnSak(brevutsendelse.sakId) | ||
?: throw InternfeilException("Fant ikke sak med id ${brevutsendelse.sakId} for brevutsendelse") | ||
) | ||
|
||
private fun sendBrev( | ||
sak: Sak, | ||
brevutsendelse: Arbeidsjobb, | ||
saksbehandler: BrukerTokenInfo, | ||
): Boolean { | ||
logger.info("Sender brev til ${sak.ident.maskerFnr()} i sak ${sak.id}") | ||
|
||
val tomtBrev = BrevParametre.TomtBrev(Spraak.NB) // TODO placeholder inntil vi har en brevmal | ||
|
||
runBlocking { | ||
val opprettetBrev = brevKlient.opprettSpesifiktBrev(brevutsendelse.sakId, tomtBrev, saksbehandler) | ||
val ferdigstiltBrev = | ||
brevKlient.ferdigstillBrev( | ||
FerdigstillJournalFoerOgDistribuerOpprettetBrev( | ||
opprettetBrev.id, | ||
brevutsendelse.sakId, | ||
sak.enhet, | ||
SaksbehandlerOgAttestant(saksbehandler.ident(), saksbehandler.ident()), | ||
), | ||
saksbehandler, | ||
) | ||
logger.info("Brev med id ${ferdigstiltBrev.brevId} er ferdigstilt") | ||
|
||
val journalfoertBrev = brevKlient.journalfoerBrev(brevutsendelse.sakId, ferdigstiltBrev.brevId, saksbehandler) | ||
logger.info("Brev med id ${ferdigstiltBrev.brevId} er journaltført (journalpostId: ${journalfoertBrev.journalpostId})") | ||
|
||
val distribuertBrev = brevKlient.distribuerBrev(brevutsendelse.sakId, ferdigstiltBrev.brevId, saksbehandler) | ||
logger.info("Brev med id ${ferdigstiltBrev.brevId} er distribuert (bestillingsId: ${distribuertBrev.bestillingsId})") | ||
} | ||
|
||
return true | ||
} | ||
|
||
private fun opprettManuellOppgave(brevutsendelse: Arbeidsjobb): OppgaveIntern = | ||
oppgaveService.opprettOppgave( | ||
referanse = brevutsendelse.id.toString(), | ||
sakId = brevutsendelse.sakId, | ||
kilde = null, // TODO legge inn kilde | ||
type = OppgaveType.GENERELL_OPPGAVE, // TODO er dette riktig | ||
merknad = "Her må det komme tekst om hva saksbehandler må gjøre", // TODO hva skal stå her? | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package no.nav.etterlatte.behandling.jobs.brevjobber | ||
|
||
import kotlinx.coroutines.runBlocking | ||
import no.nav.etterlatte.behandling.GrunnlagService | ||
import no.nav.etterlatte.behandling.jobs.brevjobber.SjekkGyldigBrevMottakerResultat.GYLDIG_MOTTAKER | ||
import no.nav.etterlatte.behandling.jobs.brevjobber.SjekkGyldigBrevMottakerResultat.UGYLDIG_MOTTAKER_UTDATERTE_PERSON_OPPLYSNINGER | ||
import no.nav.etterlatte.behandling.jobs.brevjobber.SjekkGyldigBrevMottakerResultat.UGYLDIG_MOTTAKER_UTDATERT_IDENT | ||
import no.nav.etterlatte.behandling.jobs.brevjobber.SjekkGyldigBrevMottakerResultat.UGYLDIG_MOTTAKER_VERGEMAAL | ||
import no.nav.etterlatte.common.klienter.PdlTjenesterKlient | ||
import no.nav.etterlatte.libs.common.behandling.SakType | ||
import no.nav.etterlatte.libs.common.feilhaandtering.InternfeilException | ||
import no.nav.etterlatte.libs.common.logging.sikkerlogger | ||
import no.nav.etterlatte.libs.common.person.PdlIdentifikator | ||
import no.nav.etterlatte.libs.common.person.Person | ||
import no.nav.etterlatte.libs.common.person.PersonRolle | ||
import no.nav.etterlatte.libs.common.person.VergemaalEllerFremtidsfullmakt | ||
import no.nav.etterlatte.libs.common.person.maskerFnr | ||
import no.nav.etterlatte.libs.common.sak.Sak | ||
import no.nav.etterlatte.libs.ktor.token.BrukerTokenInfo | ||
import org.slf4j.LoggerFactory | ||
import java.util.UUID | ||
|
||
enum class SjekkGyldigBrevMottakerResultat { | ||
UGYLDIG_MOTTAKER_UTDATERT_IDENT, | ||
UGYLDIG_MOTTAKER_UTDATERTE_PERSON_OPPLYSNINGER, | ||
UGYLDIG_MOTTAKER_VERGEMAAL, | ||
GYLDIG_MOTTAKER, | ||
} | ||
|
||
class SjekkBrevMottakerService( | ||
private val grunnlagService: GrunnlagService, | ||
private val pdlTjenesterKlient: PdlTjenesterKlient, | ||
) { | ||
private val logger = LoggerFactory.getLogger(this::class.java) | ||
|
||
fun sjekkOmPersonErGyldigBrevmottaker( | ||
sak: Sak, | ||
brukerTokenInfo: BrukerTokenInfo, | ||
): SjekkGyldigBrevMottakerResultat { | ||
logger.info("Sjekker om person ${sak.ident.maskerFnr()} er en gyldig brev mottaker") | ||
sikkerlogger().info("Sjekker om person ${sak.ident} er en gyldig brev mottaker") | ||
|
||
// TODO Må vel ha en iverksatt sak for at dette skal sendes? | ||
|
||
// Sjekker ident | ||
hentPdlPersonident(sak).let { sisteIdentifikatorPdl -> | ||
val sisteIdent = | ||
when (sisteIdentifikatorPdl) { | ||
is PdlIdentifikator.FolkeregisterIdent -> sisteIdentifikatorPdl.folkeregisterident.value | ||
is PdlIdentifikator.Npid -> sisteIdentifikatorPdl.npid.ident | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Flyten vil vel generelt ikke fungere dersom ident er NPID? 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Skal vi støtte det ? |
||
} | ||
if (sak.ident != sisteIdent) { | ||
return UGYLDIG_MOTTAKER_UTDATERT_IDENT | ||
} | ||
} | ||
|
||
val opplysningerPdl = hentPdlPersonopplysning(sak) | ||
val opplysningerGjenny = hentOpplysningerGjenny(sak, brukerTokenInfo) | ||
|
||
// Sjekker vergemål | ||
if (!opplysningerPdl.vergemaalEllerFremtidsfullmakt.isNullOrEmpty()) { | ||
return UGYLDIG_MOTTAKER_VERGEMAAL | ||
} | ||
|
||
val opplysningerErUendretIPdl = | ||
with(opplysningerGjenny) { | ||
fornavn == opplysningerPdl.fornavn && | ||
mellomnavn == opplysningerPdl.mellomnavn && | ||
etternavn == opplysningerPdl.etternavn && | ||
foedselsdato == opplysningerPdl.foedselsdato && | ||
erLikeVergemaal(vergemaalEllerFremtidsfullmakt, opplysningerPdl.vergemaalEllerFremtidsfullmakt) | ||
} | ||
|
||
// Sjekker for utdaterte personopplysninger | ||
if (!opplysningerErUendretIPdl) { | ||
logger.info( | ||
"Personopplysninger i PDL og Gjenny er forskjellig i sak ${sak.id}. " + | ||
"Det opprettes en oppgave for manuell håndtering. Se sikkerlogg for detaljer om hva som er forskjellig.", | ||
) | ||
sikkerlogger().info( | ||
"Personopplysninger i PDL og Gjenny er forskjellig i sak ${sak.id}. " + | ||
"Personopplysinger i Grunnlag: $opplysningerGjenny, " + | ||
"Personopplysinger i PDL: $opplysningerPdl", | ||
) | ||
return UGYLDIG_MOTTAKER_UTDATERTE_PERSON_OPPLYSNINGER | ||
} | ||
|
||
return GYLDIG_MOTTAKER | ||
} | ||
|
||
private fun hentPdlPersonident(sak: Sak) = | ||
runBlocking { | ||
pdlTjenesterKlient.hentPdlIdentifikator(sak.ident) | ||
?: throw InternfeilException("Fant ikke ident fra PDL for sak ${sak.id}") | ||
} | ||
|
||
private fun hentPdlPersonopplysning(sak: Sak): Person { | ||
// Mottaker av ytelsen | ||
val rolle = | ||
when (sak.sakType) { | ||
SakType.OMSTILLINGSSTOENAD -> PersonRolle.GJENLEVENDE | ||
SakType.BARNEPENSJON -> PersonRolle.BARN | ||
} | ||
|
||
return pdlTjenesterKlient | ||
.hentPdlModellForSaktype(sak.ident, rolle, sak.sakType) | ||
.toPerson() | ||
} | ||
|
||
private fun hentOpplysningerGjenny( | ||
sak: Sak, | ||
brukerTokenInfo: BrukerTokenInfo, | ||
): Person = | ||
runBlocking { | ||
grunnlagService | ||
.hentPersonopplysninger( | ||
// TODO skal vi hente siste iverksatte behandling her, eller nytt endepunkt for siste grunnlag i sak? | ||
UUID.randomUUID(), | ||
sak.sakType, | ||
brukerTokenInfo, | ||
).soeker | ||
?.opplysning ?: throw InternfeilException("Fant ikke opplysninger for sak=${sak.id}") | ||
} | ||
|
||
private fun erLikeVergemaal( | ||
vergerEn: List<VergemaalEllerFremtidsfullmakt>?, | ||
vergerTo: List<VergemaalEllerFremtidsfullmakt>?, | ||
): Boolean { | ||
if (vergerEn.isNullOrEmpty() && vergerTo.isNullOrEmpty()) { | ||
return true | ||
} | ||
return vergerEn == vergerTo | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
todo: mangler limit i spørringen her