From e9b3b247971c3e2efd80f0d334c71d4ee91c93d1 Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Fri, 2 Aug 2024 15:36:02 +0200 Subject: [PATCH 01/20] Skatt-panel --- .../steg/steg1/paneler/ArbeidInntekt.tsx | 56 +++++++++++++++++++ .../main/js/src/components/ui/icon/Icon.tsx | 1 + 2 files changed, 57 insertions(+) diff --git a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg1/paneler/ArbeidInntekt.tsx b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg1/paneler/ArbeidInntekt.tsx index 1b6ea61843a..5e7b683e060 100644 --- a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg1/paneler/ArbeidInntekt.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg1/paneler/ArbeidInntekt.tsx @@ -17,6 +17,7 @@ export const ArbeidInntektPanel = ({ stateModifier, formValues }) => { const infoTekst = 'Arbeidsforhold: \nDataene her blir lagt til AAREG. \n\nInntekt: \nSkatte- og inntektsgrunnlag. Inntektene blir lagt i Sigrun-stub.' + '\n\nPensjonsgivende inntekt: \nInntektene blir lagt til i POPP-register. \n\nInntektstub: \nInformasjonen blir lagt i Inntekt-stub.' + //TODO: Info om skattekort? return ( { inntektstubAttributt, inntektsmeldingAttributt, sigrunstubPensjonsgivendeAttributt, + // skattekortAttributt, ])} > @@ -46,6 +48,9 @@ export const ArbeidInntektPanel = ({ stateModifier, formValues }) => { + + + ) } @@ -150,4 +155,55 @@ ArbeidInntektPanel.initialValues = ({ set, del, has }) => ({ del('inntektstub') }, }, + skattekort: { + label: 'Har skattekort', + checked: has('skattekort'), + add: () => + set('skattekort', { + arbeidsgiver: [ + { + arbeidsgiveridentifikator: { + organisasjonsnummer: '', + personidentifikator: '', + }, + arbeidstaker: [ + { + arbeidstakeridentifikator: '', + resultatPaaForespoersel: '', + skattekort: { + utstedtDato: '', + skattekortidentifikator: null, + trekktype: [ + { + forskuddstrekk: { + trekkode: '', + }, + frikort: { + trekkode: '', + frikortbeloep: null, + }, + trekktabell: { + trekkode: '', + tabelltype: '', + tabellnummer: '', + prosentsats: null, + antallMaanederForTrekk: null, + }, + trekkprosent: { + trekkode: '', + prosentsats: null, + antallMaanederForTrekk: null, + }, + }, + ], + }, + tilleggsopplysning: '', + inntektsaar: null, + }, + ], + }, + ], + }), + remove: () => del('skattekort'), + }, }) diff --git a/apps/dolly-frontend/src/main/js/src/components/ui/icon/Icon.tsx b/apps/dolly-frontend/src/main/js/src/components/ui/icon/Icon.tsx index 2b717912348..830afd0d6b2 100644 --- a/apps/dolly-frontend/src/main/js/src/components/ui/icon/Icon.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/ui/icon/Icon.tsx @@ -145,6 +145,7 @@ export const icons = { sigrun: BankNoteIcon, bankkonto: BankNoteIcon, pengesekk: SackKronerIcon, + inntektstub: BankNoteIcon, inntektsmelding: BankNoteIcon, udi: EarthIcon, kommentar: ChatElipsisIcon, From 204f3be71da2aa10dfed5a72a0ee465e6fd1476b Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Fri, 2 Aug 2024 16:40:00 +0200 Subject: [PATCH 02/20] Div skattekort-service-oppsett --- apps/dolly-frontend/config.test.yml | 1 + apps/dolly-frontend/config.unstable.yml | 1 + .../no/nav/dolly/web/DollyFrontendApplicationStarter.java | 1 + .../src/main/java/no/nav/dolly/web/config/Consumers.java | 1 + apps/dolly-frontend/src/main/js/proxy-routes.json | 5 +++++ apps/dolly-frontend/src/main/resources/application-local.yml | 4 +++- apps/dolly-frontend/src/main/resources/application.yml | 5 +++++ 7 files changed, 17 insertions(+), 1 deletion(-) diff --git a/apps/dolly-frontend/config.test.yml b/apps/dolly-frontend/config.test.yml index 04c162a3877..ddbf6b16f9a 100644 --- a/apps/dolly-frontend/config.test.yml +++ b/apps/dolly-frontend/config.test.yml @@ -59,6 +59,7 @@ spec: - application: testnav-varslinger-service-dev - application: testnorge-profil-api-dev - application: testnorge-tilbakemelding-api + - application: testnav-skattekort-service external: - host: testnav-pensjon-testdata-facade-proxy.dev-fss-pub.nais.io - host: testnav-sigrunstub-proxy.dev-fss-pub.nais.io diff --git a/apps/dolly-frontend/config.unstable.yml b/apps/dolly-frontend/config.unstable.yml index 59a1ad3f7ee..d03aebb3db3 100644 --- a/apps/dolly-frontend/config.unstable.yml +++ b/apps/dolly-frontend/config.unstable.yml @@ -54,6 +54,7 @@ spec: - application: testnav-varslinger-service-dev - application: testnorge-profil-api-dev - application: testnorge-tilbakemelding-api + - application: testnav-skattekort-service external: - host: testnav-pensjon-testdata-facade-proxy.dev-fss-pub.nais.io - host: testnav-sigrunstub-proxy.dev-fss-pub.nais.io diff --git a/apps/dolly-frontend/src/main/java/no/nav/dolly/web/DollyFrontendApplicationStarter.java b/apps/dolly-frontend/src/main/java/no/nav/dolly/web/DollyFrontendApplicationStarter.java index 06c00ec7121..f924989b6d5 100644 --- a/apps/dolly-frontend/src/main/java/no/nav/dolly/web/DollyFrontendApplicationStarter.java +++ b/apps/dolly-frontend/src/main/java/no/nav/dolly/web/DollyFrontendApplicationStarter.java @@ -83,6 +83,7 @@ public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { .route(createRoute(consumers.getGenererNavnService())) .route(createRoute(consumers.getTestnavKodeverkService())) .route(createRoute(consumers.getTestnavTenorSearchService())) + .route(createRoute(consumers.getTestnavSkattekortService())) .build(); } diff --git a/apps/dolly-frontend/src/main/java/no/nav/dolly/web/config/Consumers.java b/apps/dolly-frontend/src/main/java/no/nav/dolly/web/config/Consumers.java index e6a490b6be1..a3460d9fc68 100644 --- a/apps/dolly-frontend/src/main/java/no/nav/dolly/web/config/Consumers.java +++ b/apps/dolly-frontend/src/main/java/no/nav/dolly/web/config/Consumers.java @@ -62,5 +62,6 @@ public class Consumers { private ServerProperties testnorgeProfilApi; private ServerProperties testnorgeTilbakemeldingApi; private ServerProperties testnavTenorSearchService; + private ServerProperties testnavSkattekortService; } diff --git a/apps/dolly-frontend/src/main/js/proxy-routes.json b/apps/dolly-frontend/src/main/js/proxy-routes.json index 0b650890bcf..aa9e9f3c24c 100644 --- a/apps/dolly-frontend/src/main/js/proxy-routes.json +++ b/apps/dolly-frontend/src/main/js/proxy-routes.json @@ -228,5 +228,10 @@ "target": "http://localhost:8020", "changeOrigin": true, "secure": false + }, + "/testnav-skattekort-service/api": { + "target": "http://localhost:8020", + "changeOrigin": true, + "secure": false } } \ No newline at end of file diff --git a/apps/dolly-frontend/src/main/resources/application-local.yml b/apps/dolly-frontend/src/main/resources/application-local.yml index d25e52393fe..9d3b3378a17 100644 --- a/apps/dolly-frontend/src/main/resources/application-local.yml +++ b/apps/dolly-frontend/src/main/resources/application-local.yml @@ -75,4 +75,6 @@ consumers: testnav-kodeverk-service: url: https://testnav-kodeverk-service.intern.dev.nav.no/ testnav-tenor-search-service: - url: https://testnav-tenor-search-service.intern.dev.nav.no \ No newline at end of file + url: https://testnav-tenor-search-service.intern.dev.nav.no + testnav-skattekort-service: + url: https://testnav-skattekort-service.intern.dev.nav.no \ No newline at end of file diff --git a/apps/dolly-frontend/src/main/resources/application.yml b/apps/dolly-frontend/src/main/resources/application.yml index e92d3318b18..ac334193d45 100644 --- a/apps/dolly-frontend/src/main/resources/application.yml +++ b/apps/dolly-frontend/src/main/resources/application.yml @@ -218,6 +218,11 @@ consumers: namespace: dolly name: testnav-tenor-search-service url: http://testnav-tenor-search-service.dolly.svc.cluster.local + testnav-skattekort-service: + cluster: dev-gcp + namespace: dolly + name: testnav-skattekort-service + url: http://testnav-skattekort-service.dolly.svc.cluster.local management: endpoints: From 555bc16ddc315167e51e3bd1eec789404f29adb1 Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Mon, 5 Aug 2024 14:39:00 +0200 Subject: [PATCH 03/20] Hent kodeverk med useSkattekort, paabegynt form --- .../steg/steg1/paneler/ArbeidInntekt.tsx | 50 ++-------- .../stegVelger/steg/steg2/Steg2.tsx | 4 +- .../components/bestillingsveileder/utils.tsx | 1 + .../fagsystem/skattekort/form/Form.tsx | 91 +++++++++++++++++++ .../js/src/components/ui/form/formUtils.tsx | 1 + .../main/js/src/components/ui/icon/Icon.tsx | 1 + .../main/js/src/utils/hooks/useSkattekort.tsx | 23 +++++ 7 files changed, 126 insertions(+), 45 deletions(-) create mode 100644 apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx create mode 100644 apps/dolly-frontend/src/main/js/src/utils/hooks/useSkattekort.tsx diff --git a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg1/paneler/ArbeidInntekt.tsx b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg1/paneler/ArbeidInntekt.tsx index 5e7b683e060..230bdb986ac 100644 --- a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg1/paneler/ArbeidInntekt.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg1/paneler/ArbeidInntekt.tsx @@ -10,6 +10,10 @@ import { getInitialSigrunstubPensjonsgivende, sigrunstubPensjonsgivendeAttributt, } from '@/components/fagsystem/sigrunstubPensjonsgivende/form/Form' +import { + initialArbeidsgiverSkatt, + skattekortAttributt, +} from '@/components/fagsystem/skattekort/form/Form' export const ArbeidInntektPanel = ({ stateModifier, formValues }) => { const sm = stateModifier(ArbeidInntektPanel.initialValues) @@ -32,7 +36,7 @@ export const ArbeidInntektPanel = ({ stateModifier, formValues }) => { inntektstubAttributt, inntektsmeldingAttributt, sigrunstubPensjonsgivendeAttributt, - // skattekortAttributt, + skattekortAttributt, ])} > @@ -160,49 +164,7 @@ ArbeidInntektPanel.initialValues = ({ set, del, has }) => ({ checked: has('skattekort'), add: () => set('skattekort', { - arbeidsgiver: [ - { - arbeidsgiveridentifikator: { - organisasjonsnummer: '', - personidentifikator: '', - }, - arbeidstaker: [ - { - arbeidstakeridentifikator: '', - resultatPaaForespoersel: '', - skattekort: { - utstedtDato: '', - skattekortidentifikator: null, - trekktype: [ - { - forskuddstrekk: { - trekkode: '', - }, - frikort: { - trekkode: '', - frikortbeloep: null, - }, - trekktabell: { - trekkode: '', - tabelltype: '', - tabellnummer: '', - prosentsats: null, - antallMaanederForTrekk: null, - }, - trekkprosent: { - trekkode: '', - prosentsats: null, - antallMaanederForTrekk: null, - }, - }, - ], - }, - tilleggsopplysning: '', - inntektsaar: null, - }, - ], - }, - ], + arbeidsgiverSkatt: [initialArbeidsgiverSkatt], }), remove: () => del('skattekort'), }, diff --git a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg2/Steg2.tsx b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg2/Steg2.tsx index 1b8684a167e..1323e0d0b50 100644 --- a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg2/Steg2.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg2/Steg2.tsx @@ -24,6 +24,7 @@ import { UforetrygdForm } from '@/components/fagsystem/uforetrygd/form/Form' import { SigrunstubPensjonsgivendeForm } from '@/components/fagsystem/sigrunstubPensjonsgivende/form/Form' import { KrrstubForm } from '@/components/fagsystem/krrstub/form/KrrForm' import { useFormContext } from 'react-hook-form' +import { SkattekortForm } from '@/components/fagsystem/skattekort/form/Form' import { PensjonsavtaleForm } from '@/components/fagsystem/pensjonsavtale/form/Form' const gruppeNavn = (gruppe) => {gruppe.navn} @@ -65,11 +66,12 @@ export const Steg2 = () => {
- + + diff --git a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/utils.tsx b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/utils.tsx index da5f500ee46..7cab3240fab 100644 --- a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/utils.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/utils.tsx @@ -74,6 +74,7 @@ export const rootPaths = [ 'medl', 'sykemelding', 'organisasjon', + 'skattekort', ] export const harAvhukedeAttributter = (values) => { diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx new file mode 100644 index 00000000000..1663269abe2 --- /dev/null +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx @@ -0,0 +1,91 @@ +import { Vis } from '@/components/bestillingsveileder/VisAttributt' +import { erForsteEllerTest, panelError } from '@/components/ui/form/formUtils' +import { useFormContext } from 'react-hook-form' +import { ErrorBoundary } from '@/components/ui/appError/ErrorBoundary' +import React from 'react' +import Panel from '@/components/ui/panel/Panel' +import { FormDollyFieldArray } from '@/components/ui/form/fieldArray/DollyFieldArray' +import { FormSelect } from '@/components/ui/form/inputs/select/Select' +import { useSkattekortKodeverk } from '@/utils/hooks/useSkattekort' + +export const initialArbeidsgiverSkatt = { + arbeidsgiveridentifikator: { + organisasjonsnummer: '', + personidentifikator: '', + }, + arbeidstaker: [ + { + arbeidstakeridentifikator: '', + resultatPaaForespoersel: '', + skattekort: { + utstedtDato: '', + skattekortidentifikator: null, + trekktype: [ + { + forskuddstrekk: { + trekkode: '', + }, + frikort: { + trekkode: '', + frikortbeloep: null, + }, + trekktabell: { + trekkode: '', + tabelltype: '', + tabellnummer: '', + prosentsats: null, + antallMaanederForTrekk: null, + }, + trekkprosent: { + trekkode: '', + prosentsats: null, + antallMaanederForTrekk: null, + }, + }, + ], + }, + tilleggsopplysning: '', + inntektsaar: null, + }, + ], +} + +export const skattekortAttributt = 'skattekort' + +export const SkattekortForm = () => { + const formMethods = useFormContext() + + const { kodeverk: resultatstatus } = useSkattekortKodeverk('RESULTATSTATUS') + + return ( + + + + + {(path: string) => ( +
+ +
+ )} +
+
+
+
+ ) +} diff --git a/apps/dolly-frontend/src/main/js/src/components/ui/form/formUtils.tsx b/apps/dolly-frontend/src/main/js/src/components/ui/form/formUtils.tsx index d344c0a6d27..92c47177943 100644 --- a/apps/dolly-frontend/src/main/js/src/components/ui/form/formUtils.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/ui/form/formUtils.tsx @@ -68,6 +68,7 @@ const getValgteAttributter = (values) => { 'sigrunstubPensjonsgivende', 'inntektstub', 'inntektsmelding', + 'skattekort', 'arbeidsplassenCV', 'pensjonforvalter.inntekt', 'pensjonforvalter.pensjonsavtale', diff --git a/apps/dolly-frontend/src/main/js/src/components/ui/icon/Icon.tsx b/apps/dolly-frontend/src/main/js/src/components/ui/icon/Icon.tsx index 830afd0d6b2..bb641c02e7e 100644 --- a/apps/dolly-frontend/src/main/js/src/components/ui/icon/Icon.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/ui/icon/Icon.tsx @@ -147,6 +147,7 @@ export const icons = { pengesekk: SackKronerIcon, inntektstub: BankNoteIcon, inntektsmelding: BankNoteIcon, + skattekort: BankNoteIcon, udi: EarthIcon, kommentar: ChatElipsisIcon, partner: HeartIcon, diff --git a/apps/dolly-frontend/src/main/js/src/utils/hooks/useSkattekort.tsx b/apps/dolly-frontend/src/main/js/src/utils/hooks/useSkattekort.tsx new file mode 100644 index 00000000000..d9a0bed5e67 --- /dev/null +++ b/apps/dolly-frontend/src/main/js/src/utils/hooks/useSkattekort.tsx @@ -0,0 +1,23 @@ +import useSWR from 'swr' +import { fetcher } from '@/api' + +const getKodeverkUrl = (kodeverkstype: string) => { + return `/testnav-skattekort-service/api/v1/kodeverk?kodeverkstype=${kodeverkstype}` +} + +export const useSkattekortKodeverk = (kodeverkstype: string) => { + const { data, isLoading, error } = useSWR(getKodeverkUrl(kodeverkstype), fetcher) + + const koder = + data && + Object.keys(data)?.map((key) => ({ + label: key, + value: data[key], + })) + + return { + kodeverk: koder, + loading: isLoading, + error: error, + } +} From a5e9c839b29060e85b7b807eef2b8a050c64914a Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Tue, 6 Aug 2024 15:15:12 +0200 Subject: [PATCH 04/20] Trekktype-form --- .../fagsystem/skattekort/form/Form.tsx | 83 ++++---- .../fagsystem/skattekort/form/Trekktype.tsx | 177 ++++++++++++++++++ 2 files changed, 224 insertions(+), 36 deletions(-) create mode 100644 apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Trekktype.tsx diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx index 1663269abe2..c9ea224e8f5 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx @@ -7,6 +7,11 @@ import Panel from '@/components/ui/panel/Panel' import { FormDollyFieldArray } from '@/components/ui/form/fieldArray/DollyFieldArray' import { FormSelect } from '@/components/ui/form/inputs/select/Select' import { useSkattekortKodeverk } from '@/utils/hooks/useSkattekort' +import { getYearRangeOptions } from '@/utils/DataFormatter' +import { subYears } from 'date-fns' +import { FormDatepicker } from '@/components/ui/form/inputs/datepicker/Datepicker' +import { FormTextInput } from '@/components/ui/form/inputs/textInput/TextInput' +import { initialTrekktabell, TrekktypeForm } from '@/components/fagsystem/skattekort/form/Trekktype' export const initialArbeidsgiverSkatt = { arbeidsgiveridentifikator: { @@ -15,37 +20,15 @@ export const initialArbeidsgiverSkatt = { }, arbeidstaker: [ { - arbeidstakeridentifikator: '', - resultatPaaForespoersel: '', + // arbeidstakeridentifikator: '', + resultatPaaForespoersel: 'SKATTEKORTOPPLYSNINGER_OK', skattekort: { utstedtDato: '', - skattekortidentifikator: null, - trekktype: [ - { - forskuddstrekk: { - trekkode: '', - }, - frikort: { - trekkode: '', - frikortbeloep: null, - }, - trekktabell: { - trekkode: '', - tabelltype: '', - tabellnummer: '', - prosentsats: null, - antallMaanederForTrekk: null, - }, - trekkprosent: { - trekkode: '', - prosentsats: null, - antallMaanederForTrekk: null, - }, - }, - ], + skattekortidentifikator: Math.floor(100000 + Math.random() * 900000), + trekktype: [initialTrekktabell], }, - tilleggsopplysning: '', - inntektsaar: null, + tilleggsopplysning: [''], + inntektsaar: new Date().getFullYear(), }, ], } @@ -56,6 +39,7 @@ export const SkattekortForm = () => { const formMethods = useFormContext() const { kodeverk: resultatstatus } = useSkattekortKodeverk('RESULTATSTATUS') + const { kodeverk: tilleggsopplysning } = useSkattekortKodeverk('TILLEGGSOPPLYSNING') return ( @@ -73,15 +57,42 @@ export const SkattekortForm = () => { canBeEmpty={false} > {(path: string) => ( -
- +
+ {/*Arbeidsgiveridentifikator (toggles)*/} + + + + + +
+ -
+ )} diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Trekktype.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Trekktype.tsx new file mode 100644 index 00000000000..24b746fdad6 --- /dev/null +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Trekktype.tsx @@ -0,0 +1,177 @@ +import { ErrorBoundary } from '@/components/ui/appError/ErrorBoundary' +import { + DollyFaBlokk, + DollyFieldArrayWrapper, + FieldArrayAddButton, +} from '@/components/ui/form/fieldArray/DollyFieldArray' +import React from 'react' +import { FormSelect } from '@/components/ui/form/inputs/select/Select' +import { useSkattekortKodeverk } from '@/utils/hooks/useSkattekort' +import { toTitleCase } from '@/utils/DataFormatter' +import { Kategori } from '@/components/ui/form/kategori/Kategori' +import { FormTextInput } from '@/components/ui/form/inputs/textInput/TextInput' +import { useFieldArray } from 'react-hook-form' + +const initialForskuddstrekk = { + forskuddstrekk: { + trekkode: '', + }, +} + +const initialFrikort = { + frikort: { + trekkode: '', + frikortbeloep: null, + }, +} + +export const initialTrekktabell = { + trekktabell: { + trekkode: '', + tabelltype: '', + tabellnummer: '', + prosentsats: null, + antallMaanederForTrekk: null, + }, +} + +const initialTrekkprosent = { + trekkprosent: { + trekkode: '', + prosentsats: null, + antallMaanederForTrekk: null, + }, +} + +const ForskuddstrekkForm = ({ path, trekkode }) => { + return ( + <> + + + ) +} + +const FrikortForm = ({ path, trekkode }) => { + return ( + <> + + + + ) +} + +const TrekktabellForm = ({ path, trekkode }) => { + const { kodeverk: tabelltype } = useSkattekortKodeverk('TABELLTYPE') + + return ( + <> + + + + + + + ) +} + +const TrekkprosentForm = ({ path, trekkode }) => { + return ( + <> + + + + + ) +} + +export const TrekktypeForm = ({ formMethods, path }) => { + const trekktypePath = `${path}.trekktype` + const trekktype = formMethods.watch(trekktypePath) + const fieldMethods = useFieldArray({ control: formMethods.control, name: trekktypePath }) + + const addNewForskuddstrekk = () => fieldMethods.append(initialForskuddstrekk) + const addNewFrikort = () => fieldMethods.append(initialFrikort) + const addNewTrekktabell = () => fieldMethods.append(initialTrekktabell) + const addNewTrekkprosent = () => fieldMethods.append(initialTrekkprosent) + + const { kodeverk: trekkode } = useSkattekortKodeverk('TREKKODE') + + return ( + + + + {trekktype.map((trekk, idx) => { + const header = Object.keys(trekk)?.[0] + const clickRemove = () => fieldMethods.remove(idx) + + return ( + 1} + > + {header === 'forskuddstrekk' && ( + + )} + {header === 'frikort' && ( + + )} + {header === 'trekktabell' && ( + + )} + {header === 'trekkprosent' && ( + + )} + + ) + })} +
+ + + + +
+
+
+
+ ) +} From 86b065a770b4f10c61517e02e0802dd542146458 Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Wed, 7 Aug 2024 11:20:50 +0200 Subject: [PATCH 05/20] Arbeidsgiver-form --- .../skattekort/form/ArbeidsgiverToggle.tsx | 61 +++++++++++++++++++ .../fagsystem/skattekort/form/Form.tsx | 6 ++ .../fagsystem/skattekort/form/Trekktype.tsx | 2 +- .../gruppeOversikt/FinnPersonBestilling.tsx | 2 +- 4 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/ArbeidsgiverToggle.tsx diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/ArbeidsgiverToggle.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/ArbeidsgiverToggle.tsx new file mode 100644 index 00000000000..5756daefef8 --- /dev/null +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/ArbeidsgiverToggle.tsx @@ -0,0 +1,61 @@ +import React, { useState } from 'react' +import { ToggleGroup } from '@navikt/ds-react' +import { OrgnummerToggle } from '@/components/fagsystem/inntektstub/form/partials/orgnummerToggle' +import { FormTextInput } from '@/components/ui/form/inputs/textInput/TextInput' +import { Kategori } from '@/components/ui/form/kategori/Kategori' + +enum ToggleValg { + ORGANISASJON = 'ORGANISASJON', + PRIVAT = 'PRIVAT', +} + +export const ArbeidsgiverToggle = ({ formMethods, path }) => { + const organisasjonPath = `${path}.organisasjonsnummer` + const personPath = `${path}.personidentifikator` + const orgnummerLength = 9 + + const [inputType, setInputType] = useState( + !formMethods.watch(organisasjonPath) || + formMethods.watch(organisasjonPath).length === orgnummerLength + ? ToggleValg.ORGANISASJON + : ToggleValg.PRIVAT, + ) + + const handleToggleChange = (value: ToggleValg) => { + setInputType(value) + formMethods.setValue(organisasjonPath, '') + formMethods.setValue(personPath, '') + } + + return ( + +
+ + + Organisasjon + + + Privat + + + + {inputType === ToggleValg.ORGANISASJON ? ( + + ) : ( +
+ +
+ )} +
+
+ ) +} diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx index c9ea224e8f5..1c7e4eec9db 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx @@ -12,6 +12,7 @@ import { subYears } from 'date-fns' import { FormDatepicker } from '@/components/ui/form/inputs/datepicker/Datepicker' import { FormTextInput } from '@/components/ui/form/inputs/textInput/TextInput' import { initialTrekktabell, TrekktypeForm } from '@/components/fagsystem/skattekort/form/Trekktype' +import { ArbeidsgiverToggle } from '@/components/fagsystem/skattekort/form/ArbeidsgiverToggle' export const initialArbeidsgiverSkatt = { arbeidsgiveridentifikator: { @@ -80,6 +81,7 @@ export const SkattekortForm = () => { label="Tilleggsopplysning" options={tilleggsopplysning} size="large" + isMulti={true} /> { isClearable={false} />
+ { options={tabelltype} size="large" /> - +
From 5f97730ee7ee8c8e635eb1d061bc622def8c919c Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Wed, 7 Aug 2024 14:22:26 +0200 Subject: [PATCH 06/20] Div fix form --- .../fagsystem/skattekort/form/ArbeidsgiverToggle.tsx | 9 +++++++-- .../js/src/components/fagsystem/skattekort/form/Form.tsx | 5 ++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/ArbeidsgiverToggle.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/ArbeidsgiverToggle.tsx index 5756daefef8..1f993365a37 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/ArbeidsgiverToggle.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/ArbeidsgiverToggle.tsx @@ -23,8 +23,13 @@ export const ArbeidsgiverToggle = ({ formMethods, path }) => { const handleToggleChange = (value: ToggleValg) => { setInputType(value) - formMethods.setValue(organisasjonPath, '') - formMethods.setValue(personPath, '') + if (value === ToggleValg.ORGANISASJON) { + formMethods.setValue(organisasjonPath, '') + formMethods.setValue(personPath, undefined) + } else if (value === ToggleValg.PRIVAT) { + formMethods.setValue(personPath, '') + formMethods.setValue(organisasjonPath, undefined) + } } return ( diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx index 1c7e4eec9db..8d0268d93e0 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx @@ -17,7 +17,7 @@ import { ArbeidsgiverToggle } from '@/components/fagsystem/skattekort/form/Arbei export const initialArbeidsgiverSkatt = { arbeidsgiveridentifikator: { organisasjonsnummer: '', - personidentifikator: '', + // personidentifikator: '', }, arbeidstaker: [ { @@ -28,7 +28,7 @@ export const initialArbeidsgiverSkatt = { skattekortidentifikator: Math.floor(100000 + Math.random() * 900000), trekktype: [initialTrekktabell], }, - tilleggsopplysning: [''], + tilleggsopplysning: [], inntektsaar: new Date().getFullYear(), }, ], @@ -60,7 +60,6 @@ export const SkattekortForm = () => { {(path: string) => ( <>
- {/*Arbeidsgiveridentifikator (toggles)*/} Date: Wed, 7 Aug 2024 15:14:43 +0200 Subject: [PATCH 07/20] Hent skattekort fra skattekort-service --- .../src/pages/gruppe/PersonVisning/PersonVisning.tsx | 7 +++++++ .../src/main/js/src/utils/SjekkBestillingFagsystem.tsx | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/apps/dolly-frontend/src/main/js/src/pages/gruppe/PersonVisning/PersonVisning.tsx b/apps/dolly-frontend/src/main/js/src/pages/gruppe/PersonVisning/PersonVisning.tsx index 346f553afde..230b86fd9af 100644 --- a/apps/dolly-frontend/src/main/js/src/pages/gruppe/PersonVisning/PersonVisning.tsx +++ b/apps/dolly-frontend/src/main/js/src/pages/gruppe/PersonVisning/PersonVisning.tsx @@ -61,6 +61,7 @@ import { harMedlBestilling, harPensjonavtaleBestilling, harPoppBestilling, + harSkattekortBestilling, harSykemeldingBestilling, harTpBestilling, harUdistubBestilling, @@ -92,6 +93,7 @@ import { useTenorIdent } from '@/utils/hooks/useTenorSoek' import { SkatteetatenVisning } from '@/components/fagsystem/skatteetaten/visning/SkatteetatenVisning' import PdlVisningConnector from '@/components/fagsystem/pdl/visning/PdlVisningConnector' import { useOrganisasjonMiljoe } from '@/utils/hooks/useOrganisasjonTilgang' +import { useSkattekort } from '@/utils/hooks/useSkattekort' import { PensjonsavtaleVisning } from '@/components/fagsystem/pensjonsavtale/visning/PensjonsavtaleVisning' const getIdenttype = (ident) => { @@ -152,6 +154,11 @@ export default ({ harAaregBestilling(bestillingerFagsystemer) || ident?.master === 'PDL', ) + const { loading: loadingSkattekort, skattekort } = useSkattekort( + ident.ident, + harSkattekortBestilling(bestillingerFagsystemer), + ) + const { loading: loadingMedl, medl } = useMedlPerson( ident.ident, harMedlBestilling(bestillingerFagsystemer) || ident?.master === 'PDL', diff --git a/apps/dolly-frontend/src/main/js/src/utils/SjekkBestillingFagsystem.tsx b/apps/dolly-frontend/src/main/js/src/utils/SjekkBestillingFagsystem.tsx index 0e02fd81ede..0e6d3895eab 100644 --- a/apps/dolly-frontend/src/main/js/src/utils/SjekkBestillingFagsystem.tsx +++ b/apps/dolly-frontend/src/main/js/src/utils/SjekkBestillingFagsystem.tsx @@ -8,6 +8,16 @@ export const harAaregBestilling = (bestillingerFagsystemer) => { return aareg } +export const harSkattekortBestilling = (bestillingerFagsystemer) => { + let skattekort = false + bestillingerFagsystemer?.forEach((i) => { + if (i?.skattekort) { + skattekort = true + } + }) + return skattekort +} + export const harMedlBestilling = (bestillingerFagsystemer) => { let medl = false bestillingerFagsystemer?.forEach((i) => { From 3a02b6111bebb3000b39581115dd1473a1b2cb96 Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Wed, 14 Aug 2024 10:25:44 +0200 Subject: [PATCH 08/20] Hent skattekort fra skattekort-service --- .../main/js/src/utils/hooks/useSkattekort.tsx | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/apps/dolly-frontend/src/main/js/src/utils/hooks/useSkattekort.tsx b/apps/dolly-frontend/src/main/js/src/utils/hooks/useSkattekort.tsx index d9a0bed5e67..9a6d349c565 100644 --- a/apps/dolly-frontend/src/main/js/src/utils/hooks/useSkattekort.tsx +++ b/apps/dolly-frontend/src/main/js/src/utils/hooks/useSkattekort.tsx @@ -1,8 +1,37 @@ import useSWR from 'swr' import { fetcher } from '@/api' +const baseUrl = '/testnav-skattekort-service/api/v1' + +const getSkattekortUrl = (ident: string) => { + return `${baseUrl}/skattekort?ident=${ident}` +} + const getKodeverkUrl = (kodeverkstype: string) => { - return `/testnav-skattekort-service/api/v1/kodeverk?kodeverkstype=${kodeverkstype}` + return `${baseUrl}/kodeverk?kodeverkstype=${kodeverkstype}` +} + +export const useSkattekort = (ident: string, harSkattekortBestilling: boolean) => { + if (!ident) { + return { + loading: false, + error: 'Ident mangler!', + } + } + + if (!harSkattekortBestilling) { + return { + loading: false, + } + } + + const { data, isLoading, error } = useSWR(getSkattekortUrl(ident), fetcher) + + return { + skattekort: data, + loading: isLoading, + error: error, + } } export const useSkattekortKodeverk = (kodeverkstype: string) => { From 9726bff79eb122043847ba8b9d3ae558a63d87a4 Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Thu, 8 Aug 2024 15:11:34 +0200 Subject: [PATCH 09/20] =?UTF-8?q?Visning=20av=20skattekortdata=20p=C3=A5?= =?UTF-8?q?=20person?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fagsystem/skattekort/form/Form.tsx | 12 +-- .../skattekort/visning/TrekktypeVisning.tsx | 34 +++++++ .../fagsystem/skattekort/visning/Visning.tsx | 97 +++++++++++++++++++ .../gruppe/PersonVisning/PersonVisning.tsx | 4 +- .../main/js/src/utils/hooks/useSkattekort.tsx | 2 +- 5 files changed, 141 insertions(+), 8 deletions(-) create mode 100644 apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/TrekktypeVisning.tsx create mode 100644 apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/Visning.tsx diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx index 8d0268d93e0..f78f4ea7522 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx @@ -67,6 +67,12 @@ export const SkattekortForm = () => { size="large" isClearable={false} /> + { size="large" isMulti={true} /> -
{ + return ( + + {(trekk, idx) => { + const forskuddstrekk = trekk?.forskuddstrekk + + return ( +
+ + + + + + + +
+ ) + }} +
+ ) +} diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/Visning.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/Visning.tsx new file mode 100644 index 00000000000..b9b1d00d5df --- /dev/null +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/Visning.tsx @@ -0,0 +1,97 @@ +import Loading from '@/components/ui/loading/Loading' +import React from 'react' +import SubOverskrift from '@/components/ui/subOverskrift/SubOverskrift' +import { Alert } from '@navikt/ds-react' +import { ErrorBoundary } from '@/components/ui/appError/ErrorBoundary' +import { TitleValue } from '@/components/ui/titleValue/TitleValue' +import { arrayToString, formatDate } from '@/utils/DataFormatter' +import { DollyFieldArray } from '@/components/ui/form/fieldArray/DollyFieldArray' +import { useSkattekortKodeverk } from '@/utils/hooks/useSkattekort' +import { TrekktypeVisning } from '@/components/fagsystem/skattekort/visning/TrekktypeVisning' + +type SkattekortVisning = { + liste?: Array + loading?: boolean +} + +type SkattekortData = any + +export const showKodeverkLabel = (kodeverkstype: any, value: any) => { + const { kodeverk, loading, error } = useSkattekortKodeverk(kodeverkstype) + if (loading || error) { + return value + } + return kodeverk?.find((kode) => kode?.value === value)?.label || value +} + +export const SkattekortVisning = ({ liste, loading }: SkattekortVisning) => { + if (loading) { + return + } + if (!liste) { + return null + } + + const manglerFagsystemdata = liste?.length < 1 + + return ( + <> + + {manglerFagsystemdata ? ( + + Fant ikke skattekort-data på person + + ) : ( + + 5} nested> + {(skattekort: SkattekortData) => { + const arbeidsgiver = skattekort?.arbeidsgiver?.[0] + const arbeidstaker = arbeidsgiver?.arbeidstaker?.[0] + const trekkListe = arbeidstaker?.skattekort?.trekktype + + const tilleggsopplysningFormatted = arbeidstaker?.tilleggsopplysning?.map( + (tilleggsopplysning) => { + return showKodeverkLabel('TILLEGGSOPPLYSNING', tilleggsopplysning) + }, + ) + + return ( +
+ + + + + + + + +
+ ) + }} +
+
+ )} + + ) +} diff --git a/apps/dolly-frontend/src/main/js/src/pages/gruppe/PersonVisning/PersonVisning.tsx b/apps/dolly-frontend/src/main/js/src/pages/gruppe/PersonVisning/PersonVisning.tsx index 230b86fd9af..69645abc3ec 100644 --- a/apps/dolly-frontend/src/main/js/src/pages/gruppe/PersonVisning/PersonVisning.tsx +++ b/apps/dolly-frontend/src/main/js/src/pages/gruppe/PersonVisning/PersonVisning.tsx @@ -94,6 +94,7 @@ import { SkatteetatenVisning } from '@/components/fagsystem/skatteetaten/visning import PdlVisningConnector from '@/components/fagsystem/pdl/visning/PdlVisningConnector' import { useOrganisasjonMiljoe } from '@/utils/hooks/useOrganisasjonTilgang' import { useSkattekort } from '@/utils/hooks/useSkattekort' +import { SkattekortVisning } from '@/components/fagsystem/skattekort/visning/Visning' import { PensjonsavtaleVisning } from '@/components/fagsystem/pensjonsavtale/visning/PensjonsavtaleVisning' const getIdenttype = (ident) => { @@ -154,7 +155,7 @@ export default ({ harAaregBestilling(bestillingerFagsystemer) || ident?.master === 'PDL', ) - const { loading: loadingSkattekort, skattekort } = useSkattekort( + const { loading: loadingSkattekort, skattekortData } = useSkattekort( ident.ident, harSkattekortBestilling(bestillingerFagsystemer), ) @@ -469,6 +470,7 @@ export default ({ harInntektsmeldingBestilling(bestillingerFagsystemer) ? inntektsmeldingBestilling : null } /> + (getSkattekortUrl(ident), fetcher) return { - skattekort: data, + skattekortData: data, loading: isLoading, error: error, } From 19772f8841530c09c2f645154ae955eaaa70cf31 Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Thu, 8 Aug 2024 15:33:54 +0200 Subject: [PATCH 10/20] Fjernet forskuddstrekk som trekktype --- .../fagsystem/skattekort/form/Trekktype.tsx | 31 ++----------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Trekktype.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Trekktype.tsx index e3aca8d7a83..939ae096dd3 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Trekktype.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Trekktype.tsx @@ -12,12 +12,6 @@ import { Kategori } from '@/components/ui/form/kategori/Kategori' import { FormTextInput } from '@/components/ui/form/inputs/textInput/TextInput' import { useFieldArray } from 'react-hook-form' -const initialForskuddstrekk = { - forskuddstrekk: { - trekkode: '', - }, -} - const initialFrikort = { frikort: { trekkode: '', @@ -43,19 +37,6 @@ const initialTrekkprosent = { }, } -const ForskuddstrekkForm = ({ path, trekkode }) => { - return ( - <> - - - ) -} - const FrikortForm = ({ path, trekkode }) => { return ( <> @@ -122,7 +103,6 @@ export const TrekktypeForm = ({ formMethods, path }) => { const trekktype = formMethods.watch(trekktypePath) const fieldMethods = useFieldArray({ control: formMethods.control, name: trekktypePath }) - const addNewForskuddstrekk = () => fieldMethods.append(initialForskuddstrekk) const addNewFrikort = () => fieldMethods.append(initialFrikort) const addNewTrekktabell = () => fieldMethods.append(initialTrekktabell) const addNewTrekkprosent = () => fieldMethods.append(initialTrekkprosent) @@ -131,7 +111,7 @@ export const TrekktypeForm = ({ formMethods, path }) => { return ( - + {trekktype.map((trekk, idx) => { const header = Object.keys(trekk)?.[0] @@ -144,11 +124,8 @@ export const TrekktypeForm = ({ formMethods, path }) => { header={toTitleCase(header)} handleRemove={clickRemove} whiteBackground - showDeleteButton={trekktype.length > 1} + showDeleteButton > - {header === 'forskuddstrekk' && ( - - )} {header === 'frikort' && ( )} @@ -165,10 +142,6 @@ export const TrekktypeForm = ({ formMethods, path }) => { -
From d9978a4a631ba47a6b61e59f5bfd20f32d5017d7 Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Fri, 9 Aug 2024 15:57:29 +0200 Subject: [PATCH 11/20] Vis bestillingsdata + omskrivning av forskuddstrekk + div fix --- .../kriterier/BestillingKriterieMapper.tsx | 60 +++++++++++++++++-- .../steg/steg1/paneler/ArbeidInntekt.tsx | 6 +- .../fagsystem/skattekort/form/Form.tsx | 14 +++-- .../{Trekktype.tsx => Forskuddstrekk.tsx} | 16 ++--- ...eVisning.tsx => ForskuddstrekkVisning.tsx} | 8 ++- .../fagsystem/skattekort/visning/Visning.tsx | 12 ++-- .../src/main/js/src/pages/tenorSoek/utils.tsx | 2 +- 7 files changed, 89 insertions(+), 29 deletions(-) rename apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/{Trekktype.tsx => Forskuddstrekk.tsx} (88%) rename apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/{TrekktypeVisning.tsx => ForskuddstrekkVisning.tsx} (76%) diff --git a/apps/dolly-frontend/src/main/js/src/components/bestilling/sammendrag/kriterier/BestillingKriterieMapper.tsx b/apps/dolly-frontend/src/main/js/src/components/bestilling/sammendrag/kriterier/BestillingKriterieMapper.tsx index 432c2203aee..2d41e9aa933 100644 --- a/apps/dolly-frontend/src/main/js/src/components/bestilling/sammendrag/kriterier/BestillingKriterieMapper.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/bestilling/sammendrag/kriterier/BestillingKriterieMapper.tsx @@ -9,6 +9,7 @@ import { omraaderArrayToString, oversettBoolean, showLabel, + toTitleCase, uppercaseAndUnderscoreToCapitalized, } from '@/utils/DataFormatter' import { @@ -27,6 +28,7 @@ import { useNavEnheter } from '@/utils/hooks/useNorg2' import { kodeverkKeyToLabel } from '@/components/fagsystem/sigrunstubPensjonsgivende/utils' import { useContext } from 'react' import { BestillingsveilederContext } from '@/components/bestillingsveileder/BestillingsveilederContext' +import { showKodeverkLabel } from '@/components/fagsystem/skattekort/visning/Visning' // TODO: Flytte til selector? // - Denne kan forminskes ved bruk av hjelpefunksjoner @@ -2126,6 +2128,55 @@ const mapInntektsmelding = (bestillingData, data) => { } } +const mapSkattekort = (bestillingData, data) => { + const skattekortKriterier = bestillingData.skattekort + + const arbeidsgiver = skattekortKriterier?.arbeidsgiverSkatt?.[0] + const arbeidstaker = arbeidsgiver?.arbeidstaker?.[0] + const trekkListe = arbeidstaker?.skattekort?.forskuddstrekk + + const tilleggsopplysningFormatted = arbeidstaker?.tilleggsopplysning?.map( + (tilleggsopplysning) => { + return showKodeverkLabel('TILLEGGSOPPLYSNING', tilleggsopplysning) + }, + ) + + if (skattekortKriterier) { + const skattekort = { + header: 'Skattekort (SOKOS)', + items: [ + obj( + 'Resultat på forespørsel', + showKodeverkLabel('RESULTATSTATUS', arbeidstaker?.resultatPaaForespoersel), + ), + obj('Inntektsår', arbeidstaker?.inntektsaar), + obj('Utstedt dato', formatDate(arbeidstaker?.skattekort?.utstedtDato)), + obj('Skattekortidentifikator', arbeidstaker?.skattekort?.skattekortidentifikator), + obj('Tilleggsopplysning', arrayToString(tilleggsopplysningFormatted)), + obj('Arbeidsgiver (org.nr.)', arbeidsgiver?.arbeidsgiveridentifikator?.organisasjonsnummer), + obj('Arbeidsgiver (ident)', arbeidsgiver?.arbeidsgiveridentifikator?.personidentifikator), + ], + itemRows: [], + } + + trekkListe?.forEach((item, idx) => { + const forskuddstrekkType = Object.keys(item)?.filter((key) => item[key])?.[0] + const forskuddstrekk = item[forskuddstrekkType] + skattekort.itemRows.push([ + { numberHeader: `Forskuddstrekk ${idx + 1}: ${toTitleCase(forskuddstrekkType)}` }, + obj('Trekkode', showKodeverkLabel('TREKKODE', forskuddstrekk?.trekkode)), + obj('Frikortbeløp', forskuddstrekk?.frikortbeloep), + obj('Tabelltype', showKodeverkLabel('TABELLTYPE', forskuddstrekk?.tabelltype)), + obj('Tabellnummer', forskuddstrekk?.tabellnummer), + obj('Prosentsats', forskuddstrekk?.prosentsats), + obj('Antall måneder for trekk', forskuddstrekk?.antallMaanederForTrekk), + ]) + }) + + data.push(skattekort) + } +} + const mapDokarkiv = (bestillingData, data) => { const dokarkivKriterier = bestillingData.dokarkiv @@ -2326,16 +2377,17 @@ export function mapBestillingData(bestillingData, bestillingsinformasjon, firstI mapSigrunStub(bestillingData, data) mapSigrunstubPensjonsgivende(bestillingData, data) mapInntektStub(bestillingData, data) + mapInntektsmelding(bestillingData, data) + mapSkattekort(bestillingData, data) mapArbeidsplassenCV(bestillingData, data) + mapPensjon(bestillingData, data, navEnheter) + mapArena(bestillingData, data) mapSykemelding(bestillingData, data) mapBrregstub(bestillingData, data) + mapInst(bestillingData, data) mapKrr(bestillingData, data) mapMedlemskapsperiode(bestillingData, data) - mapArena(bestillingData, data) - mapInst(bestillingData, data) mapUdiStub(bestillingData, data) - mapPensjon(bestillingData, data, navEnheter) - mapInntektsmelding(bestillingData, data) mapDokarkiv(bestillingData, data) mapHistark(bestillingData, data) mapOrganisasjon(bestillingData, data) diff --git a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg1/paneler/ArbeidInntekt.tsx b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg1/paneler/ArbeidInntekt.tsx index 230bdb986ac..76cd6aaf162 100644 --- a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg1/paneler/ArbeidInntekt.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg1/paneler/ArbeidInntekt.tsx @@ -20,8 +20,8 @@ export const ArbeidInntektPanel = ({ stateModifier, formValues }) => { const infoTekst = 'Arbeidsforhold: \nDataene her blir lagt til AAREG. \n\nInntekt: \nSkatte- og inntektsgrunnlag. Inntektene blir lagt i Sigrun-stub.' + - '\n\nPensjonsgivende inntekt: \nInntektene blir lagt til i POPP-register. \n\nInntektstub: \nInformasjonen blir lagt i Inntekt-stub.' - //TODO: Info om skattekort? + '\n\nPensjonsgivende inntekt: \nInntektene blir lagt til i POPP-register. \n\nInntektstub: \nInformasjonen blir lagt i Inntekt-stub.' + + '\n\nSkattekort: Dataene blir lagt til i SOKOS.' return ( { - + diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx index f78f4ea7522..c53735b3a77 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx @@ -11,22 +11,23 @@ import { getYearRangeOptions } from '@/utils/DataFormatter' import { subYears } from 'date-fns' import { FormDatepicker } from '@/components/ui/form/inputs/datepicker/Datepicker' import { FormTextInput } from '@/components/ui/form/inputs/textInput/TextInput' -import { initialTrekktabell, TrekktypeForm } from '@/components/fagsystem/skattekort/form/Trekktype' +import { + ForskuddstrekkForm, + initialTrekktabell, +} from '@/components/fagsystem/skattekort/form/Forskuddstrekk' import { ArbeidsgiverToggle } from '@/components/fagsystem/skattekort/form/ArbeidsgiverToggle' export const initialArbeidsgiverSkatt = { arbeidsgiveridentifikator: { organisasjonsnummer: '', - // personidentifikator: '', }, arbeidstaker: [ { - // arbeidstakeridentifikator: '', resultatPaaForespoersel: 'SKATTEKORTOPPLYSNINGER_OK', skattekort: { utstedtDato: '', skattekortidentifikator: Math.floor(100000 + Math.random() * 900000), - trekktype: [initialTrekktabell], + forskuddstrekk: [initialTrekktabell], }, tilleggsopplysning: [], inntektsaar: new Date().getFullYear(), @@ -45,7 +46,7 @@ export const SkattekortForm = () => { return ( { name={`${path}.arbeidstaker[0].skattekort.utstedtDato`} label="Utstedt dato" /> + {/*//TODO: Boer vaere random for hvert skattekort vi legger til*/} { formMethods={formMethods} path={`${path}.arbeidsgiveridentifikator`} /> - diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Trekktype.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Forskuddstrekk.tsx similarity index 88% rename from apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Trekktype.tsx rename to apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Forskuddstrekk.tsx index 939ae096dd3..55b127c7e0e 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Trekktype.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Forskuddstrekk.tsx @@ -98,10 +98,10 @@ const TrekkprosentForm = ({ path, trekkode }) => { ) } -export const TrekktypeForm = ({ formMethods, path }) => { - const trekktypePath = `${path}.trekktype` - const trekktype = formMethods.watch(trekktypePath) - const fieldMethods = useFieldArray({ control: formMethods.control, name: trekktypePath }) +export const ForskuddstrekkForm = ({ formMethods, path }) => { + const forskuddstrekkPath = `${path}.forskuddstrekk` + const forskuddstrekk = formMethods.watch(forskuddstrekkPath) + const fieldMethods = useFieldArray({ control: formMethods.control, name: forskuddstrekkPath }) const addNewFrikort = () => fieldMethods.append(initialFrikort) const addNewTrekktabell = () => fieldMethods.append(initialTrekktabell) @@ -113,7 +113,7 @@ export const TrekktypeForm = ({ formMethods, path }) => { - {trekktype.map((trekk, idx) => { + {forskuddstrekk.map((trekk, idx) => { const header = Object.keys(trekk)?.[0] const clickRemove = () => fieldMethods.remove(idx) @@ -127,13 +127,13 @@ export const TrekktypeForm = ({ formMethods, path }) => { showDeleteButton > {header === 'frikort' && ( - + )} {header === 'trekktabell' && ( - + )} {header === 'trekkprosent' && ( - + )} ) diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/TrekktypeVisning.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/ForskuddstrekkVisning.tsx similarity index 76% rename from apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/TrekktypeVisning.tsx rename to apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/ForskuddstrekkVisning.tsx index 764e8f343b6..473562345f7 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/TrekktypeVisning.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/ForskuddstrekkVisning.tsx @@ -1,16 +1,18 @@ import { DollyFieldArray } from '@/components/ui/form/fieldArray/DollyFieldArray' import { TitleValue } from '@/components/ui/titleValue/TitleValue' import { showKodeverkLabel } from '@/components/fagsystem/skattekort/visning/Visning' +import { toTitleCase } from '@/utils/DataFormatter' -export const TrekktypeVisning = ({ trekkliste }) => { +export const ForskuddstrekkVisning = ({ trekkliste }) => { return ( {(trekk, idx) => { - const forskuddstrekk = trekk?.forskuddstrekk + const forskuddstrekkType = Object.keys(trekk)?.filter((key) => trekk[key])?.[0] + const forskuddstrekk = trekk[forskuddstrekkType] return (
- + @@ -36,7 +36,11 @@ export const SkattekortVisning = ({ liste, loading }: SkattekortVisning) => { return ( <> - + {manglerFagsystemdata ? ( Fant ikke skattekort-data på person @@ -47,7 +51,7 @@ export const SkattekortVisning = ({ liste, loading }: SkattekortVisning) => { {(skattekort: SkattekortData) => { const arbeidsgiver = skattekort?.arbeidsgiver?.[0] const arbeidstaker = arbeidsgiver?.arbeidstaker?.[0] - const trekkListe = arbeidstaker?.skattekort?.trekktype + const trekkListe = arbeidstaker?.skattekort?.forskuddstrekk const tilleggsopplysningFormatted = arbeidstaker?.tilleggsopplysning?.map( (tilleggsopplysning) => { @@ -85,7 +89,7 @@ export const SkattekortVisning = ({ liste, loading }: SkattekortVisning) => { title="Arbeidsgiver (ident)" value={arbeidsgiver?.arbeidsgiveridentifikator?.personidentifikator} /> - +
) }} diff --git a/apps/dolly-frontend/src/main/js/src/pages/tenorSoek/utils.tsx b/apps/dolly-frontend/src/main/js/src/pages/tenorSoek/utils.tsx index a4366f10a80..399af38de97 100644 --- a/apps/dolly-frontend/src/main/js/src/pages/tenorSoek/utils.tsx +++ b/apps/dolly-frontend/src/main/js/src/pages/tenorSoek/utils.tsx @@ -20,7 +20,7 @@ export const createOptions = ( if (Array.isArray(options)) { return options.map((option) => ({ value: option, - label: hasManualOptions ? manualOptions[option] || codeToNorskLabel(option) : option, + label: hasManualOptions ? manualOptions[option] : codeToNorskLabel(option), })) } else { return Object.entries(options).map(([key, value]) => ({ From 3e293e6dada82d427e011068dd9fc6a0569af8dd Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Mon, 12 Aug 2024 12:09:53 +0200 Subject: [PATCH 12/20] Vis xml av skattekort --- .../js/src/components/codeView/CodeView.tsx | 9 +- .../fagsystem/skattekort/visning/Visning.tsx | 90 ++++++++++++------- .../tenorSoek/resultatVisning/TabsVisning.tsx | 5 +- .../src/main/js/src/utils/DataFormatter.tsx | 11 +++ 4 files changed, 77 insertions(+), 38 deletions(-) diff --git a/apps/dolly-frontend/src/main/js/src/components/codeView/CodeView.tsx b/apps/dolly-frontend/src/main/js/src/components/codeView/CodeView.tsx index 4807f7b99a4..b17440fa6cd 100644 --- a/apps/dolly-frontend/src/main/js/src/components/codeView/CodeView.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/codeView/CodeView.tsx @@ -3,14 +3,17 @@ import styled from 'styled-components' const StyledSyntaxHighlighter = styled(SyntaxHighlighter)` font-size: 0.9em; - max-width: 820px; + width: 100%; ` type Props = { code: string language: string + wrapLongLines?: boolean } -export default ({ code, language }: Props) => ( - {code} +export default ({ code, language, wrapLongLines = false }: Props) => ( + + {code} + ) diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/Visning.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/Visning.tsx index 94727b9a4ee..0055a833ec8 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/Visning.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/Visning.tsx @@ -4,10 +4,13 @@ import SubOverskrift from '@/components/ui/subOverskrift/SubOverskrift' import { Alert } from '@navikt/ds-react' import { ErrorBoundary } from '@/components/ui/appError/ErrorBoundary' import { TitleValue } from '@/components/ui/titleValue/TitleValue' -import { arrayToString, formatDate } from '@/utils/DataFormatter' +import { arrayToString, formatDate, formatXml } from '@/utils/DataFormatter' import { DollyFieldArray } from '@/components/ui/form/fieldArray/DollyFieldArray' import { useSkattekortKodeverk } from '@/utils/hooks/useSkattekort' import { ForskuddstrekkVisning } from '@/components/fagsystem/skattekort/visning/ForskuddstrekkVisning' +import Button from '@/components/ui/button/Button' +import useBoolean from '@/utils/hooks/useBoolean' +import { CodeView } from '@/components/codeView' type SkattekortVisning = { liste?: Array @@ -48,7 +51,9 @@ export const SkattekortVisning = ({ liste, loading }: SkattekortVisning) => { ) : ( 5} nested> - {(skattekort: SkattekortData) => { + {(skattekort: SkattekortData, idx: number) => { + const [viserXml, vis, skjul] = useBoolean(false) + const arbeidsgiver = skattekort?.arbeidsgiver?.[0] const arbeidstaker = arbeidsgiver?.arbeidstaker?.[0] const trekkListe = arbeidstaker?.skattekort?.forskuddstrekk @@ -59,38 +64,57 @@ export const SkattekortVisning = ({ liste, loading }: SkattekortVisning) => { }, ) + const xmlFormatted = formatXml(skattekort?.skattekortXml, ' ') + return ( -
- - - - - - - - -
+ +
+ + + + + + + + +
+ + {viserXml && + (skattekort?.skattekortXml ? ( + + ) : ( + + Kunne ikke vise skattekort-xml + + ))} +
) }}
diff --git a/apps/dolly-frontend/src/main/js/src/pages/tenorSoek/resultatVisning/TabsVisning.tsx b/apps/dolly-frontend/src/main/js/src/pages/tenorSoek/resultatVisning/TabsVisning.tsx index 1cc8014c5fc..f68031380ed 100644 --- a/apps/dolly-frontend/src/main/js/src/pages/tenorSoek/resultatVisning/TabsVisning.tsx +++ b/apps/dolly-frontend/src/main/js/src/pages/tenorSoek/resultatVisning/TabsVisning.tsx @@ -22,7 +22,6 @@ const TabsVisningFormatter = styled.div` const StyledCodeView = styled(SyntaxHighlighter)` font-size: 0.9em; - max-width: 820px; margin: 0; ` @@ -61,7 +60,9 @@ export const TabsVisning = ({ children, kildedata }: any) => { marginBottom: '15px', }} > - {kildedataPretty} + + {kildedataPretty} + diff --git a/apps/dolly-frontend/src/main/js/src/utils/DataFormatter.tsx b/apps/dolly-frontend/src/main/js/src/utils/DataFormatter.tsx index 3b14c69d688..d55a7c8c117 100644 --- a/apps/dolly-frontend/src/main/js/src/utils/DataFormatter.tsx +++ b/apps/dolly-frontend/src/main/js/src/utils/DataFormatter.tsx @@ -243,3 +243,14 @@ export const getYearRangeOptions = (start, stop) => { } return years.reverse() } + +export const formatXml = (xml: string, tab = '\t') => { + let formatted = '' + let indent = '' + xml.split(/>\s*\r\n' + if (node.match(/^]*[^\/]$/)) indent += tab + }) + return formatted.substring(1, formatted.length - 3) +} From e6d24d37a6e30c2bcc86e3a77e0339f5a64a20b9 Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Mon, 12 Aug 2024 16:50:11 +0200 Subject: [PATCH 13/20] Tilpass bestillingsvisning --- .../kriterier/BestillingKriterieMapper.tsx | 56 ++++++++++--------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/apps/dolly-frontend/src/main/js/src/components/bestilling/sammendrag/kriterier/BestillingKriterieMapper.tsx b/apps/dolly-frontend/src/main/js/src/components/bestilling/sammendrag/kriterier/BestillingKriterieMapper.tsx index 2d41e9aa933..22c2250f7ed 100644 --- a/apps/dolly-frontend/src/main/js/src/components/bestilling/sammendrag/kriterier/BestillingKriterieMapper.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/bestilling/sammendrag/kriterier/BestillingKriterieMapper.tsx @@ -2131,20 +2131,24 @@ const mapInntektsmelding = (bestillingData, data) => { const mapSkattekort = (bestillingData, data) => { const skattekortKriterier = bestillingData.skattekort - const arbeidsgiver = skattekortKriterier?.arbeidsgiverSkatt?.[0] - const arbeidstaker = arbeidsgiver?.arbeidstaker?.[0] - const trekkListe = arbeidstaker?.skattekort?.forskuddstrekk - - const tilleggsopplysningFormatted = arbeidstaker?.tilleggsopplysning?.map( - (tilleggsopplysning) => { - return showKodeverkLabel('TILLEGGSOPPLYSNING', tilleggsopplysning) - }, - ) - if (skattekortKriterier) { const skattekort = { header: 'Skattekort (SOKOS)', - items: [ + itemRows: [], + } + + skattekortKriterier?.arbeidsgiverSkatt?.forEach((arbeidsgiver, idx) => { + const arbeidstaker = arbeidsgiver?.arbeidstaker?.[0] + const trekkListe = arbeidstaker?.skattekort?.forskuddstrekk + + const tilleggsopplysningFormatted = arbeidstaker?.tilleggsopplysning?.map( + (tilleggsopplysning) => { + return showKodeverkLabel('TILLEGGSOPPLYSNING', tilleggsopplysning) + }, + ) + + skattekort.itemRows.push([ + { numberHeader: `Skattekort ${idx + 1}` }, obj( 'Resultat på forespørsel', showKodeverkLabel('RESULTATSTATUS', arbeidstaker?.resultatPaaForespoersel), @@ -2155,22 +2159,22 @@ const mapSkattekort = (bestillingData, data) => { obj('Tilleggsopplysning', arrayToString(tilleggsopplysningFormatted)), obj('Arbeidsgiver (org.nr.)', arbeidsgiver?.arbeidsgiveridentifikator?.organisasjonsnummer), obj('Arbeidsgiver (ident)', arbeidsgiver?.arbeidsgiveridentifikator?.personidentifikator), - ], - itemRows: [], - } - - trekkListe?.forEach((item, idx) => { - const forskuddstrekkType = Object.keys(item)?.filter((key) => item[key])?.[0] - const forskuddstrekk = item[forskuddstrekkType] - skattekort.itemRows.push([ - { numberHeader: `Forskuddstrekk ${idx + 1}: ${toTitleCase(forskuddstrekkType)}` }, - obj('Trekkode', showKodeverkLabel('TREKKODE', forskuddstrekk?.trekkode)), - obj('Frikortbeløp', forskuddstrekk?.frikortbeloep), - obj('Tabelltype', showKodeverkLabel('TABELLTYPE', forskuddstrekk?.tabelltype)), - obj('Tabellnummer', forskuddstrekk?.tabellnummer), - obj('Prosentsats', forskuddstrekk?.prosentsats), - obj('Antall måneder for trekk', forskuddstrekk?.antallMaanederForTrekk), ]) + + trekkListe?.forEach((item, idx) => { + const forskuddstrekkType = Object.keys(item)?.filter((key) => item[key])?.[0] + const forskuddstrekk = item[forskuddstrekkType] + + skattekort.itemRows.push([ + { numberHeader: `Forskuddstrekk ${idx + 1}: ${toTitleCase(forskuddstrekkType)}` }, + obj('Trekkode', showKodeverkLabel('TREKKODE', forskuddstrekk?.trekkode)), + obj('Frikortbeløp', forskuddstrekk?.frikortbeloep), + obj('Tabelltype', showKodeverkLabel('TABELLTYPE', forskuddstrekk?.tabelltype)), + obj('Tabellnummer', forskuddstrekk?.tabellnummer), + obj('Prosentsats', forskuddstrekk?.prosentsats), + obj('Antall måneder for trekk', forskuddstrekk?.antallMaanederForTrekk), + ]) + }) }) data.push(skattekort) From 7e0b533877b05c92cb87a25538159d6eab1da2a9 Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Tue, 13 Aug 2024 12:27:22 +0200 Subject: [PATCH 14/20] Fix initial values og tilpass form layout --- .../steg/steg1/paneler/ArbeidInntekt.tsx | 2 +- .../fagsystem/skattekort/form/Form.tsx | 40 +++++++++++-------- .../skattekort/form/Forskuddstrekk.tsx | 6 +-- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg1/paneler/ArbeidInntekt.tsx b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg1/paneler/ArbeidInntekt.tsx index 76cd6aaf162..2a88832ddab 100644 --- a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg1/paneler/ArbeidInntekt.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg1/paneler/ArbeidInntekt.tsx @@ -164,7 +164,7 @@ ArbeidInntektPanel.initialValues = ({ set, del, has }) => ({ checked: has('skattekort'), add: () => set('skattekort', { - arbeidsgiverSkatt: [initialArbeidsgiverSkatt], + arbeidsgiverSkatt: [initialArbeidsgiverSkatt()], }), remove: () => del('skattekort'), }, diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx index c53735b3a77..1ca33ee7477 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx @@ -17,22 +17,26 @@ import { } from '@/components/fagsystem/skattekort/form/Forskuddstrekk' import { ArbeidsgiverToggle } from '@/components/fagsystem/skattekort/form/ArbeidsgiverToggle' -export const initialArbeidsgiverSkatt = { - arbeidsgiveridentifikator: { - organisasjonsnummer: '', - }, - arbeidstaker: [ - { - resultatPaaForespoersel: 'SKATTEKORTOPPLYSNINGER_OK', - skattekort: { - utstedtDato: '', - skattekortidentifikator: Math.floor(100000 + Math.random() * 900000), - forskuddstrekk: [initialTrekktabell], - }, - tilleggsopplysning: [], - inntektsaar: new Date().getFullYear(), +export const initialArbeidsgiverSkatt = ( + skattekortidentifikator = Math.floor(100000 + Math.random() * 900000), +) => { + return { + arbeidsgiveridentifikator: { + organisasjonsnummer: '', }, - ], + arbeidstaker: [ + { + resultatPaaForespoersel: 'SKATTEKORTOPPLYSNINGER_OK', + skattekort: { + utstedtDato: '', + skattekortidentifikator: skattekortidentifikator, + forskuddstrekk: [initialTrekktabell], + }, + tilleggsopplysning: [], + inntektsaar: new Date().getFullYear(), + }, + ], + } } export const skattekortAttributt = 'skattekort' @@ -55,7 +59,7 @@ export const SkattekortForm = () => { {(path: string) => ( @@ -72,6 +76,7 @@ export const SkattekortForm = () => { name={`${path}.arbeidstaker[0].inntektsaar`} label="Inntektsår" options={getYearRangeOptions(1968, subYears(new Date(), -5).getFullYear())} + size="xsmall" isClearable={false} /> {
diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Forskuddstrekk.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Forskuddstrekk.tsx index 55b127c7e0e..350c7233775 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Forskuddstrekk.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Forskuddstrekk.tsx @@ -44,7 +44,7 @@ const FrikortForm = ({ path, trekkode }) => { name={`${path}.frikort.trekkode`} label="Trekkode" options={trekkode} - size="large" + size="xlarge" /> @@ -60,7 +60,7 @@ const TrekktabellForm = ({ path, trekkode }) => { name={`${path}.trekktabell.trekkode`} label="Trekkode" options={trekkode} - size="large" + size="xlarge" /> { name={`${path}.trekkprosent.trekkode`} label="Trekkode" options={trekkode} - size="large" + size="xlarge" /> Date: Tue, 13 Aug 2024 16:52:25 +0200 Subject: [PATCH 15/20] Validering og div fix --- .../stegVelger/steg/steg2/DollyValidation.tsx | 2 + .../skattekort/form/ArbeidsgiverToggle.tsx | 12 ++- .../fagsystem/skattekort/form/Form.tsx | 3 + .../skattekort/form/Forskuddstrekk.tsx | 4 + .../fagsystem/skattekort/form/validation.tsx | 76 +++++++++++++++++++ .../visning/ForskuddstrekkVisning.tsx | 4 + 6 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/validation.tsx diff --git a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg2/DollyValidation.tsx b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg2/DollyValidation.tsx index d673b271a03..9fad3f3d878 100644 --- a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg2/DollyValidation.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/stegVelger/steg/steg2/DollyValidation.tsx @@ -21,6 +21,7 @@ import { KrrstubForm } from '@/components/fagsystem/krrstub/form/KrrForm' import { MiljoVelger } from '@/components/miljoVelger/MiljoVelger' import { MalForm } from '@/components/bestillingsveileder/stegVelger/steg/steg3/MalForm' import { VelgGruppe } from '@/components/bestillingsveileder/stegVelger/steg/steg3/VelgGruppe' +import { SkattekortForm } from '@/components/fagsystem/skattekort/form/Form' export const DollyValidation = Yup.object({ ...PdlfForm.validation, @@ -30,6 +31,7 @@ export const DollyValidation = Yup.object({ ...SigrunstubPensjonsgivendeForm.validation, ...InntektstubForm.validation, ...InntektsmeldingForm.validation, + ...SkattekortForm.validation, ...SykdomForm.validation, ...BrregstubForm.validation, ...InstForm.validation, diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/ArbeidsgiverToggle.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/ArbeidsgiverToggle.tsx index 1f993365a37..f2fac8f5795 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/ArbeidsgiverToggle.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/ArbeidsgiverToggle.tsx @@ -12,13 +12,11 @@ enum ToggleValg { export const ArbeidsgiverToggle = ({ formMethods, path }) => { const organisasjonPath = `${path}.organisasjonsnummer` const personPath = `${path}.personidentifikator` - const orgnummerLength = 9 const [inputType, setInputType] = useState( - !formMethods.watch(organisasjonPath) || - formMethods.watch(organisasjonPath).length === orgnummerLength - ? ToggleValg.ORGANISASJON - : ToggleValg.PRIVAT, + formMethods.watch(`${path}.personidentifikator`)?.length === 11 + ? ToggleValg.PRIVAT + : ToggleValg.ORGANISASJON, ) const handleToggleChange = (value: ToggleValg) => { @@ -38,7 +36,7 @@ export const ArbeidsgiverToggle = ({ formMethods, path }) => { @@ -57,7 +55,7 @@ export const ArbeidsgiverToggle = ({ formMethods, path }) => { /> ) : (
- +
)} diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx index 1ca33ee7477..f2b583110a5 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx @@ -16,6 +16,7 @@ import { initialTrekktabell, } from '@/components/fagsystem/skattekort/form/Forskuddstrekk' import { ArbeidsgiverToggle } from '@/components/fagsystem/skattekort/form/ArbeidsgiverToggle' +import { validation } from '@/components/fagsystem/skattekort/form/validation' export const initialArbeidsgiverSkatt = ( skattekortidentifikator = Math.floor(100000 + Math.random() * 900000), @@ -113,3 +114,5 @@ export const SkattekortForm = () => { ) } + +SkattekortForm.validation = validation diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Forskuddstrekk.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Forskuddstrekk.tsx index 350c7233775..bde8bfd2ebe 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Forskuddstrekk.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Forskuddstrekk.tsx @@ -45,6 +45,7 @@ const FrikortForm = ({ path, trekkode }) => { label="Trekkode" options={trekkode} size="xlarge" + isClearable={false} /> @@ -61,12 +62,14 @@ const TrekktabellForm = ({ path, trekkode }) => { label="Trekkode" options={trekkode} size="xlarge" + isClearable={false} /> @@ -87,6 +90,7 @@ const TrekkprosentForm = ({ path, trekkode }) => { label="Trekkode" options={trekkode} size="xlarge" + isClearable={false} /> val?.length === 9), + ), + personidentifikator: ifPresent( + '$personidentifikator', + requiredString + .matches(/^\d*$/, 'Ident må være et tall med 11 sifre') + .test('len', 'Ident må være et tall med 11 sifre', (val) => val?.length === 11), + ), + }), + arbeidstaker: Yup.array().of( + Yup.object({ + resultatPaaForespoersel: requiredString, + skattekort: Yup.object({ + utstedtDato: Yup.string().nullable(), + skattekortidentifikator: Yup.string().nullable(), + forskuddstrekk: Yup.array().of( + Yup.object({ + frikort: ifPresent( + '$frikort', + Yup.object({ + trekkode: requiredString, + frikortbeloep: Yup.string().nullable(), + }), + ), + trekktabell: ifPresent( + '$trekktabell', + Yup.object({ + trekkode: requiredString, + tabelltype: requiredString, + tabellnummer: Yup.string().nullable(), + prosentsats: Yup.number() + .transform((i, j) => (j === '' ? null : i)) + .min(0, 'Kan ikke være mindre enn ${min}') + .max(100, 'Kan ikke være større enn ${max}') + .nullable(), + antallMaanederForTrekk: Yup.string().nullable(), + }), + ), + trekkprosent: ifPresent( + '$trekkprosent', + Yup.object({ + trekkode: requiredString, + prosentsats: Yup.number() + .transform((i, j) => (j === '' ? null : i)) + .min(0, 'Kan ikke være mindre enn ${min}') + .max(100, 'Kan ikke være større enn ${max}') + .nullable(), + antallMaanederForTrekk: Yup.string().nullable(), + }), + ), + }), + ), + }), + tilleggsopplysning: Yup.array().of(Yup.string().nullable()), + inntektsaar: requiredString, + }), + ), + }), + ), + }), + ), +} diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/ForskuddstrekkVisning.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/ForskuddstrekkVisning.tsx index 473562345f7..cf63776d241 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/ForskuddstrekkVisning.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/ForskuddstrekkVisning.tsx @@ -4,6 +4,10 @@ import { showKodeverkLabel } from '@/components/fagsystem/skattekort/visning/Vis import { toTitleCase } from '@/utils/DataFormatter' export const ForskuddstrekkVisning = ({ trekkliste }) => { + if (!trekkliste || trekkliste?.length < 1) { + return null + } + return ( {(trekk, idx) => { From f226c1709a38f30d5c8f268c661e5c0937350309 Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Tue, 13 Aug 2024 18:05:38 +0200 Subject: [PATCH 16/20] Opprydning --- .../skattekort/form/ArbeidsgiverToggle.tsx | 8 ++++++- .../fagsystem/skattekort/form/Form.tsx | 3 +-- .../skattekort/form/Forskuddstrekk.tsx | 21 ++++++++++++++----- .../visning/ForskuddstrekkVisning.tsx | 4 ++-- .../fagsystem/skattekort/visning/Visning.tsx | 6 +++--- 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/ArbeidsgiverToggle.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/ArbeidsgiverToggle.tsx index f2fac8f5795..4a85097d233 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/ArbeidsgiverToggle.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/ArbeidsgiverToggle.tsx @@ -3,13 +3,19 @@ import { ToggleGroup } from '@navikt/ds-react' import { OrgnummerToggle } from '@/components/fagsystem/inntektstub/form/partials/orgnummerToggle' import { FormTextInput } from '@/components/ui/form/inputs/textInput/TextInput' import { Kategori } from '@/components/ui/form/kategori/Kategori' +import { UseFormReturn } from 'react-hook-form/dist/types' enum ToggleValg { ORGANISASJON = 'ORGANISASJON', PRIVAT = 'PRIVAT', } -export const ArbeidsgiverToggle = ({ formMethods, path }) => { +type ArbeidsgiverToggleProps = { + formMethods: UseFormReturn + path: string +} + +export const ArbeidsgiverToggle = ({ formMethods, path }: ArbeidsgiverToggleProps) => { const organisasjonPath = `${path}.organisasjonsnummer` const personPath = `${path}.personidentifikator` diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx index f2b583110a5..cd29d72aa83 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/form/Form.tsx @@ -19,7 +19,7 @@ import { ArbeidsgiverToggle } from '@/components/fagsystem/skattekort/form/Arbei import { validation } from '@/components/fagsystem/skattekort/form/validation' export const initialArbeidsgiverSkatt = ( - skattekortidentifikator = Math.floor(100000 + Math.random() * 900000), + skattekortidentifikator = Math.floor(100000 + Math.random() * 900000), //NOSONAR not used in secure contexts ) => { return { arbeidsgiveridentifikator: { @@ -84,7 +84,6 @@ export const SkattekortForm = () => { name={`${path}.arbeidstaker[0].skattekort.utstedtDato`} label="Utstedt dato" /> - {/*//TODO: Boer vaere random for hvert skattekort vi legger til*/} { +const FrikortForm = ({ path, trekkode }: ForskuddstrekkProps) => { return ( <> { ) } -const TrekktabellForm = ({ path, trekkode }) => { +const TrekktabellForm = ({ path, trekkode }: ForskuddstrekkProps) => { const { kodeverk: tabelltype } = useSkattekortKodeverk('TABELLTYPE') return ( @@ -82,7 +93,7 @@ const TrekktabellForm = ({ path, trekkode }) => { ) } -const TrekkprosentForm = ({ path, trekkode }) => { +const TrekkprosentForm = ({ path, trekkode }: ForskuddstrekkProps) => { return ( <> { ) } -export const ForskuddstrekkForm = ({ formMethods, path }) => { +export const ForskuddstrekkForm = ({ formMethods, path }: ForskuddstrekkFormProps) => { const forskuddstrekkPath = `${path}.forskuddstrekk` const forskuddstrekk = formMethods.watch(forskuddstrekkPath) const fieldMethods = useFieldArray({ control: formMethods.control, name: forskuddstrekkPath }) @@ -117,7 +128,7 @@ export const ForskuddstrekkForm = ({ formMethods, path }) => { - {forskuddstrekk.map((trekk, idx) => { + {forskuddstrekk.map((trekk: any, idx: number) => { const header = Object.keys(trekk)?.[0] const clickRemove = () => fieldMethods.remove(idx) diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/ForskuddstrekkVisning.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/ForskuddstrekkVisning.tsx index cf63776d241..a4656010814 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/ForskuddstrekkVisning.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/ForskuddstrekkVisning.tsx @@ -3,14 +3,14 @@ import { TitleValue } from '@/components/ui/titleValue/TitleValue' import { showKodeverkLabel } from '@/components/fagsystem/skattekort/visning/Visning' import { toTitleCase } from '@/utils/DataFormatter' -export const ForskuddstrekkVisning = ({ trekkliste }) => { +export const ForskuddstrekkVisning = ({ trekkliste }: any) => { if (!trekkliste || trekkliste?.length < 1) { return null } return ( - {(trekk, idx) => { + {(trekk: any, idx: number) => { const forskuddstrekkType = Object.keys(trekk)?.filter((key) => trekk[key])?.[0] const forskuddstrekk = trekk[forskuddstrekkType] diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/Visning.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/Visning.tsx index 0055a833ec8..1e4b6788731 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/Visning.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/Visning.tsx @@ -19,12 +19,12 @@ type SkattekortVisning = { type SkattekortData = any -export const showKodeverkLabel = (kodeverkstype: any, value: any) => { +export const showKodeverkLabel = (kodeverkstype: string, value: string) => { const { kodeverk, loading, error } = useSkattekortKodeverk(kodeverkstype) if (loading || error) { return value } - return kodeverk?.find((kode) => kode?.value === value)?.label || value + return kodeverk?.find((kode: any) => kode?.value === value)?.label || value } export const SkattekortVisning = ({ liste, loading }: SkattekortVisning) => { @@ -59,7 +59,7 @@ export const SkattekortVisning = ({ liste, loading }: SkattekortVisning) => { const trekkListe = arbeidstaker?.skattekort?.forskuddstrekk const tilleggsopplysningFormatted = arbeidstaker?.tilleggsopplysning?.map( - (tilleggsopplysning) => { + (tilleggsopplysning: string) => { return showKodeverkLabel('TILLEGGSOPPLYSNING', tilleggsopplysning) }, ) From af2da0ab9263076d5b84b5dcc9862bfd57558e85 Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Wed, 14 Aug 2024 18:06:33 +0200 Subject: [PATCH 17/20] Tilpasning av mal-data --- .../options/malOptions.tsx | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/options/malOptions.tsx b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/options/malOptions.tsx index b5140d137c0..5dc9e6d72cd 100644 --- a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/options/malOptions.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/options/malOptions.tsx @@ -30,6 +30,9 @@ export const initialValuesBasedOnMal = (mal: any, environments: any) => { if (initialValuesMal.inntektstub) { initialValuesMal.inntektstub = getUpdatedInntektstubData(initialValuesMal.inntektstub) } + if (initialValuesMal.skattekort) { + initialValuesMal.skattekort = getUpdatedSkattekortData(initialValuesMal.skattekort) + } if (initialValuesMal.instdata) { initialValuesMal.instdata = getUpdatedInstData(initialValuesMal.instdata) } @@ -156,6 +159,27 @@ const getUpdatedAaregData = (aaregData: any) => { const getUpdatedInntektsmeldingData = (inntektsmeldingData: any) => inntektsmeldingData.map((inntekt: any) => updateData(inntekt, initialValues.inntektsmelding)) +const getUpdatedSkattekortData = (skattekortData) => { + const newSkattekortData = Object.assign({}, skattekortData) + + newSkattekortData.arbeidsgiverSkatt = newSkattekortData.arbeidsgiverSkatt.map((arbeidsgiver) => { + const identifikator = Object.fromEntries( + Object.entries(arbeidsgiver?.arbeidsgiveridentifikator)?.filter(([key, value]) => value), + ) + _.set(arbeidsgiver, 'arbeidsgiveridentifikator', identifikator) + + const forskuddstrekk = arbeidsgiver?.arbeidstaker?.[0]?.skattekort?.forskuddstrekk?.map( + (forskuddstrekk) => + Object.fromEntries(Object.entries(forskuddstrekk)?.filter(([key, value]) => value)), + ) + _.set(arbeidsgiver, 'arbeidstaker[0].skattekort.forskuddstrekk', forskuddstrekk) + + return arbeidsgiver + }) + + return newSkattekortData +} + const getUpdatedInstData = (instData: any) => instData.map((data: any) => updateData(data, initialValues.instdata)) From d6e4aafd4b7700caa7a7ff751a8c62bb0b0badc0 Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Wed, 14 Aug 2024 18:18:27 +0200 Subject: [PATCH 18/20] Sonar-fix --- .../options/malOptions.tsx | 28 ++++++++++--------- .../fagsystem/skattekort/visning/Visning.tsx | 6 ++-- .../src/main/js/src/utils/DataFormatter.tsx | 8 ++++-- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/options/malOptions.tsx b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/options/malOptions.tsx index 5dc9e6d72cd..d35ad820aef 100644 --- a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/options/malOptions.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/options/malOptions.tsx @@ -159,23 +159,25 @@ const getUpdatedAaregData = (aaregData: any) => { const getUpdatedInntektsmeldingData = (inntektsmeldingData: any) => inntektsmeldingData.map((inntekt: any) => updateData(inntekt, initialValues.inntektsmelding)) -const getUpdatedSkattekortData = (skattekortData) => { +const getUpdatedSkattekortData = (skattekortData: any) => { const newSkattekortData = Object.assign({}, skattekortData) - newSkattekortData.arbeidsgiverSkatt = newSkattekortData.arbeidsgiverSkatt.map((arbeidsgiver) => { - const identifikator = Object.fromEntries( - Object.entries(arbeidsgiver?.arbeidsgiveridentifikator)?.filter(([key, value]) => value), - ) - _.set(arbeidsgiver, 'arbeidsgiveridentifikator', identifikator) + newSkattekortData.arbeidsgiverSkatt = newSkattekortData.arbeidsgiverSkatt.map( + (arbeidsgiver: any) => { + const identifikator = Object.fromEntries( + Object.entries(arbeidsgiver?.arbeidsgiveridentifikator)?.filter(([key, value]) => value), + ) + _.set(arbeidsgiver, 'arbeidsgiveridentifikator', identifikator) - const forskuddstrekk = arbeidsgiver?.arbeidstaker?.[0]?.skattekort?.forskuddstrekk?.map( - (forskuddstrekk) => - Object.fromEntries(Object.entries(forskuddstrekk)?.filter(([key, value]) => value)), - ) - _.set(arbeidsgiver, 'arbeidstaker[0].skattekort.forskuddstrekk', forskuddstrekk) + const forskuddstrekk = arbeidsgiver?.arbeidstaker?.[0]?.skattekort?.forskuddstrekk?.map( + (forskuddstrekk: any) => + Object.fromEntries(Object.entries(forskuddstrekk)?.filter(([key, value]) => value)), + ) + _.set(arbeidsgiver, 'arbeidstaker[0].skattekort.forskuddstrekk', forskuddstrekk) - return arbeidsgiver - }) + return arbeidsgiver + }, + ) return newSkattekortData } diff --git a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/Visning.tsx b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/Visning.tsx index 1e4b6788731..51db4c625f2 100644 --- a/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/Visning.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/fagsystem/skattekort/visning/Visning.tsx @@ -13,12 +13,10 @@ import useBoolean from '@/utils/hooks/useBoolean' import { CodeView } from '@/components/codeView' type SkattekortVisning = { - liste?: Array + liste?: Array loading?: boolean } -type SkattekortData = any - export const showKodeverkLabel = (kodeverkstype: string, value: string) => { const { kodeverk, loading, error } = useSkattekortKodeverk(kodeverkstype) if (loading || error) { @@ -51,7 +49,7 @@ export const SkattekortVisning = ({ liste, loading }: SkattekortVisning) => { ) : ( 5} nested> - {(skattekort: SkattekortData, idx: number) => { + {(skattekort: any, idx: number) => { const [viserXml, vis, skjul] = useBoolean(false) const arbeidsgiver = skattekort?.arbeidsgiver?.[0] diff --git a/apps/dolly-frontend/src/main/js/src/utils/DataFormatter.tsx b/apps/dolly-frontend/src/main/js/src/utils/DataFormatter.tsx index d55a7c8c117..9947f25f61c 100644 --- a/apps/dolly-frontend/src/main/js/src/utils/DataFormatter.tsx +++ b/apps/dolly-frontend/src/main/js/src/utils/DataFormatter.tsx @@ -248,9 +248,13 @@ export const formatXml = (xml: string, tab = '\t') => { let formatted = '' let indent = '' xml.split(/>\s*\r\n' - if (node.match(/^]*[^\/]$/)) indent += tab + if (/^]*[^/]$/.exec(node)) { + indent += tab + } }) return formatted.substring(1, formatted.length - 3) } From b9e1372325baddd595db1b8aace319721ad4685c Mon Sep 17 00:00:00 2001 From: Betsy Carina Traran Date: Wed, 14 Aug 2024 18:25:56 +0200 Subject: [PATCH 19/20] Deploy #deploy-test-frontend --- .../src/components/bestillingsveileder/options/malOptions.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/options/malOptions.tsx b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/options/malOptions.tsx index d35ad820aef..574c1eaf7a2 100644 --- a/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/options/malOptions.tsx +++ b/apps/dolly-frontend/src/main/js/src/components/bestillingsveileder/options/malOptions.tsx @@ -161,24 +161,20 @@ const getUpdatedInntektsmeldingData = (inntektsmeldingData: any) => const getUpdatedSkattekortData = (skattekortData: any) => { const newSkattekortData = Object.assign({}, skattekortData) - newSkattekortData.arbeidsgiverSkatt = newSkattekortData.arbeidsgiverSkatt.map( (arbeidsgiver: any) => { const identifikator = Object.fromEntries( Object.entries(arbeidsgiver?.arbeidsgiveridentifikator)?.filter(([key, value]) => value), ) _.set(arbeidsgiver, 'arbeidsgiveridentifikator', identifikator) - const forskuddstrekk = arbeidsgiver?.arbeidstaker?.[0]?.skattekort?.forskuddstrekk?.map( (forskuddstrekk: any) => Object.fromEntries(Object.entries(forskuddstrekk)?.filter(([key, value]) => value)), ) _.set(arbeidsgiver, 'arbeidstaker[0].skattekort.forskuddstrekk', forskuddstrekk) - return arbeidsgiver }, ) - return newSkattekortData } From 478e2abb3f69b30fe8f23212d819661576985536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristen=20H=C3=A6rum?= Date: Thu, 15 Aug 2024 08:11:54 +0200 Subject: [PATCH 20/20] Feature/levende arbeidsforhold (#3580) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Forandret navn til v2 i appene vi prater med #deploy-frontend #deploy-kodeverk-service #deploy-organisasjon-faste-data-service #deploy-oversikt-frontend #deploy-proxy #deploy-pdl-proxy * Forandret navn til v2 i appene vi prater med #deploy-frontend #deploy-levende-arbeidsforhold-ansettelse * prøver med schema.sql og data.sql #deploy-levende-arbeidsforhold-ansettelse * prøver med schema.sql og data.sql #deploy-levende-arbeidsforhold-ansettelse * prøver med schema.sql og data.sql #deploy-levende-arbeidsforhold-ansettelse * Legger til validering om intervallet er positivt heltall + legger til const variabler for default intervall og for parameter-navnet til intervall * Fått hjelp av emil til å grante access to table #deploy-levende-arbeidsforhold-ansettelse * Fått hjelp av emil til å grante access to table #deploy-levende-arbeidsforhold-ansettelse * Fått hjelp av emil til å grante access to table * Foraandret sikkerheten tilbake ti insecure #deploy-levende-arbeidsforhold-ansettelse * Tester tilgang til databasen #deploy-levende-arbeidsforhold-ansettelse * Kjører ansettelse-service og starter scheduler på nytt ved spørring til GET /kjor endepunkt * skiftet request #deploy-frontend * Merget inn frontend branchen * Fjernet endepunkt spesifikke respons-headers for gyldig CORS * Endret på property aksessering og henting av options * Henter parameter-data fra backend og displayer i react component * skiftet request #deploy-frontend * Tester tilkobling til levende-arbeidsforhold-api #deploy-frontend * Gydlig tidsrom funksjon for å sjekke om nåværende tidspunkt er innenfor et gyldig tidsrom * Legger til "/" i url-en til levende-arbeidsforhold #deploy-frontend * Forandret entitetene #deploy-testnav-levende-arbeidsforhold-service * Forandret entitetene #deploy-levende-arbeidsforhold-service * Forandret entitetene #deploy-levende-arbeidsforhold-ansettelse * Legger til test for gyldig tidsrom funksjon * Legger til doxygen for gyldigTidsrom-funksjonen * repository fungerer * La til et par tester for gyldig tidsrom funksjonen. * Legger til funksjon for sjekk av nåværende tidspunkt er i gyldig tidsrom * Legger til kall på ansettelseservice funksjon i scheduler-jobben * La til doxygen for sjekk gyldig tidsrom funksjon * Fikser feil i link for lokal kjøring * Sjekke om å hente verdier fungerer på swagger #deploy-levende-arbeidsforhold-ansettelse * Fjerner unødvendige logger i JobbScheduler * Sjekke om å hente verdier fungerer på swagger #deploy-levende-arbeidsforhold-ansettelse * Fjerner ubrukt kode * Sjekke om å hente verdier fungerer på swagger #deploy-levende-arbeidsforhold-ansettelse * Legger til beregning av fødselsår * sjekker hvordan dette fungerer på swagger #deploy-levende-arbeidsforhold-ansettelse * sjekker hvordan dette fungerer på swagger #deploy-levende-arbeidsforhold-ansettelse * sjekker hvordan dette fungerer på swagger #deploy-levende-arbeidsforhold-ansettelse * Fjernet kommentarer og funksjoner som ikke blir brukt. * fikset putmappping i JobbController til å faktisk oppdatere verdi #deploy-levende-arbeidsforhold-ansettelse * Se om put fungerer nå #deploy-levende-arbeidsforhold-ansettelse * Se om put fungerer nå, endret entitet og spliter stringen som kommer inn. #deploy-levende-arbeidsforhold-ansettelse * Se om put fungerer nå, endret entitet og spliter stringen som kommer inn. #deploy-levende-arbeidsforhold-ansettelse * Fetcher riktig fra databasen. Omstrukturerer EditParameter, men er nå hardcoda for kun organisasjoner * Nå skal putmapping fungere som forventet #deploy-levende-arbeidsforhold-ansettelse * Endret AnsettelseService.java slik at den henter parametere fra db * Funker nå å endre parametere fra frontend * Fjerner logging i konsollen * #deploy-frontend * Sletter og rydder masse * Ny scheduler app * Ny scheduler app gradle prosjekt * Legger til doxygen for commander funksjoner + wrapper API spørring i try-catch * importerer commander klasse for kall fra ansettelse-jobb scheduler * Fjerner ubrukte metoder #deploy-levende-arbeidsforhold-ansettelse * Legger til workflow fil for scheduler appen #deploy-levende-arbeidsforhold-scheduler * Legger til dockerfil og config.yml i scheduler appen med security group regler * Legger til inbound og outbound security group regler i ansettelse appen * Legger til ny scheduler app #deploy-levende-arbeidsforhold-scheduler * Endre til riktig port å expose i Dockerfile #deploy-levende-arbeidsforhold-scheduler * Endre til riktig port å expose i Dockerfile #deploy-levende-arbeidsforhold-scheduler * Endre til riktig port å expose i config.yml #deploy-levende-arbeidsforhold-scheduler * Startet å lage graphql spørring * Implementerer inputvalidering i frontend * Legger til levende arbeidsforhold scheduler app i oversikt for å hente ut accesstoken lokalt #deploy-oversikt-frontend * Legger til nytt filter i grapghql-criterion * Prøver å hente tags * lagt til HentTagsCommand * Legger til regex og fikser logikkfeil i pdlservice * Fjerner ett mellomrom * Konverterer postnummer til formatet x??? for å brukes i wildcard * lagt til HentTagsCommand * Legger til hent kalender util funksjon * Legger til klasse for JSON respons body for /status endepunkt * Legger til funksjon for å hente tidspunkt for neste kjøring fra scheduler * importert HenTagsConsumer * Doxygen for hentTidspunktNesteKjoring funksjonen * GET /status request handler funksjon i scheduler appen #deploy-levende-arbeidsforhold-scheduler * refactor scheduler m initielt delay og fiksert intervall og ikke klokketime intervall * refactor reschedule request handler funksjon og refactor sifferTilHeltall til å bruke "optional" * Fjerner cron expression funksjon siden ikke i bruk etter refactor * Kaller på ansettelses command #deploy-levende-arbeidsforhold-scheduler * Forandret sikkerhetetn til oath igjen * Inkluderer måned og dag i alderssjekk for graphql-spørringene * Deploy ansettelse appen med inbound og outbound rules for scheduler appen #deploy-levende-arbeidsforhold-ansettelse * Implementert alias metden * Setter opp kobling til scheduler-appen i frontend og fetcher status * Kaller på ansettelses command med exception logging #deploy-levende-arbeidsforhold-scheduler * implementert consumer * Begynt på å implementere alias metodne * Begynt på å implementere alias metodne #deploy-levende-arbeidsforhold-scheduler * Forandret til requestparam i JobbController.java #deploy-levende-arbeidsforhold-scheduler * lagt til logger #deploy-levende-arbeidsforhold-scheduler * forandret porten #deploy-levende-arbeidsforhold-scheduler * Lager en komponent som viser jobb-status på appstyring-siden * Kaller på ansettelses command med exception logging #deploy-levende-arbeidsforhold-scheduler * Lagt til intervall llisten * Småfiks * Endret port til riktig port #deploy-levende-arbeidsforhold-scheduler * mer logging #deploy-levende-arbeidsforhold-scheduler * mer logging #deploy-levende-arbeidsforhold-scheduler * Endret outbound rules #deploy-levende-arbeidsforhold-scheduler * Byttet bibliotek for token exchange #deploy-levende-arbeidsforhold-scheduler * Fjerner unødvendige imports * La til riktig klasse #deploy-levende-arbeidsforhold-scheduler * Riktig URL #deploy-levende-arbeidsforhold-scheduler * Deploy ansettelse appen med inbound og outbound rules for scheduler appen #deploy-levende-arbeidsforhold-ansettelse #deploy-levende-arbeidsforhold-scheduler * Prøve med bare insecure sikkerhet #deploy-levende-arbeidsforhold-scheduler * Prøve med bare insecure sikkerhet #deploy-levende-arbeidsforhold-asnettelse * Refactor consumer og command for spørring til ansettelse app #deploy-levende-arbeidsforhold-scheduler * Implementert logikk for å benytte alias-metoden * Legger til secure OAuth i ApplicationConfig #deploy-levende-arbeidsforhold-scheduler * Endrer security for lokal kjøring * Endre til riktig domene for spørring om token fra ansettelse app #deploy-levende-arbeidsforhold-scheduler * Setter domene til dolly.svc.cluster.local #deploy-levende-arbeidsforhold-ansettelse * Endre app og domene navn #deploy-levende-arbeidsforhold-scheduler * Fungerer å kjøre men bruker lang tid * Fungerer å kjøre men bruker lang tid #deploy-levende-arbeidsforhold-scheduler * Fungerer å kjøre men bruker lang tid #deploy-levende-arbeidsforhold-scheduler * Forandret tilbake lang tid #deploy-levende-arbeidsforhold-scheduler * Fjerner v2 fra app-navnet * Fjerner v2 fra app-navnet #deploy-proxy #deploy-pdl-proxy #deploy-frontend #deploy-levende-arbeidsforhold-ansettelse #deploy-levende-arbeidsforhold-scheduler #deploy-organisasjon-faste-data-service #deploy-oversikt-frontend * Fjerner v2 fra app-navnet #deploy-frontend * Fjerner v2 fra app-navnet #deploy-levende-arbeidsforhold-scheduler * #deploy-levende-arbeidsforhold-ansettelse * Endrer noe logikk-feil * Implementerer henting av org fra tenor. Byttet til insecure security * Lagt til entitet for ansettelse_logg db * Fik feilmelding fra pdl * Forandret url i application-dev.yml * Lagrer de ansatte i AnsettelseLogg.java * Prøvet å få med stillingsprosent * Endrer noe logikk i kanAnsettes-metoden * Lagt til stillingsprosent * Legger til GET /stopp endepunkt for å stoppe nåværende jobb * Endrer feil i defaultState til statusData #deploy-frontend * Prøver å hent bolk tags * #deploy-frontend * Legger til knapper for aktivering og deaktivering av jobb i frontend app #deploy-levende-arbeidsforhold-scheduler * Endret til èn knapp etter forslag fra Emil #deploy-levende-arbeidsforhold-scheduler * Legger til deaktivering og aktivering med loading og delay for henting av status * Holder på å implementere bolk tags i AnsettelseService.java * #deploy-frontend * Håndterer potensielle feil ved spørring til scheduler grunnet intervall kan mangle * Implementerer bruk av tenor for henting av organisasjoner * Legger til JSON response fra GET /stopp * #deploy-levende-arbeidsforhold-scheduler * Implementerer bruk av tenor i AnsettelseService * Lagt til at den ikke skal bruke personer som er i bruk og lagt til stillingsprosent i JobbParameterNavn.java * Legger til content-type JSON for respons fra GET /stopp i scheduler appen * Legger til sjekk for om deaktivering av scheduler jobben var vellykket * Fikset logge databasen * Bytter Box med Alert og legger til litt spacing * Flyttet det å hente tags til PdlService.java slik at man bare får tilbake personer som har riktig tags * Gjort slik at JobbController.java kaller på ansettelsesService.java. #deploy-levende-arbeidsforhold-ansettelse * Hadde en feil i testklassen. #deploy-levende-arbeidsforhold-ansettelse * Kommenterer, rydder og endrer loggikkfeil i AlderspennList * Fikser postnummer-formatering * Fikset bug-en i GraphQl #deploy-levende-arbeidsforhold-ansettelse * Måtte legge inbound rule i kodeverk service for appen våres, og får se om den ansetter folk #deploy-kodeverk-service #deploy-levende-arbeidsforhold-ansettelse * Legger til avro schema for sommeroppg1-appen som hadde forsvunnet * Byttet sikkerhet til insecure siden fikk feilmelding at den ikke finner jwt #deploy-levende-arbeidsforhold-ansettelse * Prøver å deploye igjen for å se om det fungerer #deploy-testnav-levende-arbeidsforhold-ansettelse * Prøver å deploye igjen for å se om det fungerer #deploy-levende-arbeidsforhold-ansettelse * Prøver å deploye igjen for å se om det fungerer #deploy-levende-arbeidsforhold-ansettelse * Legger til doxygen-kommentering * Legger til sjekk om brregKildedata til organisasjon er null * Legger til sjekk om postnr er null og bytter organisasjon med ny dersom det stemmer * Legger til kommentarer og sletter bruk av organisasjon-faste-data * Fjerner bruk av ereg * Fjerner ubrukte imports * Endrer lambda-statements * Legger til hjelpe-funksjoner for beregner tidspunkt for neste kjøring av jobb + endre på funksjonsnavn * Legger til tester for funksjon med logikk for beregning av forsinkelse for kjøring av neste jobb * Gjør endepunkt for aktivering av scheduler tilgjengelig på /start i tillegg * Omstrukturering av spørring til GET /stopp endepunktet i scheduler appen + endre GET /scheduler endepunktet til å returnere en 500 status kode dersom aktivering av scheduler feiler * #deploy-frontend #deploy-levende-arbeidsforhold-scheduler * Sletter en test-klasse * Har skrevet noen kommentarer, og slettet noen ubrukte kommentarer. * Fjernet unødvendige filer #deploy-levende-arbeidsforhold-ansettelse * Skrevet i redme.md filen * Fikset slik at ansatte personer ble logget. Hadde blitt fjernet. #deploy-levende-arbeidsforhold-ansettelse * Fjernet eventlistener i AnsettelseService.java og forandret linkene i application.yml og fjernet unødvendige bibliotek i settings.gradle. #deploy-levende-arbeidsforhold-ansettelse * Fjernet eventlistener i AnsettelseService.java og forandret linkene i application.yml og fjernet unødvendige bibliotek i settings.gradle. #deploy-levende-arbeidsforhold-ansettelse * Fjernet eventlistener i AnsettelseService.java og forandret linkene i application.yml og fjernet unødvendige bibliotek i settings.gradle. #deploy-levende-arbeidsforhold-ansettelse * Tok det tilbake.. #deploy-levende-arbeidsforhold-ansettelse * Prøvde å fjerne unødvendige ting fra build.gradle og la til oath2-server #deploy-levende-arbeidsforhold-ansettelse * Prøvde å fjerne unødvendige ting fra build.gradle og la til oath2-server #deploy-levende-arbeidsforhold-ansettelse * Forandret sikkerheten til insecure for å se #deploy-levende-arbeidsforhold-ansettelse * Legger til tenor på outbound-rules #deploy-levende-arbeidsforhold-ansettelse * Fjerner at ansatte personer blir lagt til to ganger #deploy-levende-arbeidsforhold-ansettelse * Forhindre potensiell nullpointer exception * Refactor i controller i ansettelse app * Refactor i controller i ansettelse app * Fjernet ubrukt import og funksjoner #deploy-levende-arbeidsforhold-ansettelse * Endret slik at det ble mer ryddig AlderspennList.java * Fjernet eventlistener i AnsettelseService.java * Skrevet litt i README filen * Deployer front-end #deploy-frontend * Lagt til forklaring på jobb-parameter endepunktet i JobbController.java * Endre threadpool til å ha corresponderende antall tråder som er tilgengelig på systemet for å unngå oversubsription * Legger til beskrivelse av GET /ansettelse-jobb * Legger til swagger dokumentasjon for API i scheduler appen + fjerner ekstra JSON parsing siden det skjer automagically * Endrer accessPolicy til kun nødvendige apper #deploy-levende-arbeidsforhold-scheduler * Spesifisere tomcat package versjon i håp om å fikse security vuln #deploy-levende-arbeidsforhold-scheduler * Fjernet dependencies som ikke trengs lenger. * Spesifisere versjon for utdatert package for å fikse security vuln fra nais console #deploy-levende-arbeidsforhold-scheduler * Spesifisere versjon for "nimbus-jose-jwt" for å fikse security vuln fra nais console #deploy-levende-arbeidsforhold-scheduler * Legger til versjon for dependencies for å unngå sikkerhets-sårbarheter etter analyse fra nais console * Legger til versjon for dependencies for å unngå sikkerhets-sårbarheter etter analyse fra nais console #deploy-levende-arbeidsforhold-ansettelse * Remove obsolete files and dependencies Deleted unused Java classes and test config files to streamline the codebase and improve project organization. This cleanup helps maintain a leaner structure and eliminates redundant components. * Remove obsolete files and dependencies Deleted unused Java classes and test config files to streamline the codebase and improve project organization. This cleanup helps maintain a leaner structure and eliminates redundant components. --------- Co-authored-by: Andrea Devold Fjeld Co-authored-by: ulrikHesmyr Co-authored-by: Martineem --- .../app.levende-arbeidsforhold-ansettelse.yml | 26 + .../app.levende-arbeidsforhold-scheduler.yml | 25 + apps/dolly-frontend/config.yml | 3 + .../web/DollyFrontendApplicationStarter.java | 2 + .../no/nav/dolly/web/config/Consumers.java | 2 + .../src/main/js/proxy-routes.json | 10 + .../adminPages/Appstyring/AppstyringPage.tsx | 123 ++- .../adminPages/Appstyring/AppstyringTable.tsx | 37 +- .../adminPages/Appstyring/EditParameter.tsx | 78 +- .../pages/adminPages/Appstyring/StatusBox.tsx | 24 + .../util/LevendeArbeidsforholdRequest.tsx | 13 + .../adminPages/Appstyring/util/Typer.tsx | 11 + .../src/main/resources/application-local.yml | 6 +- .../src/main/resources/application.yml | 10 + .../Dockerfile | 8 + .../README.md | 107 ++ .../levende-arbeidsforhold-ansettelse/TODO.md | 6 + .../build.gradle | 68 ++ .../config.yml | 68 ++ .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43453 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + .../levende-arbeidsforhold-ansettelse/gradlew | 249 +++++ .../gradlew.bat | 92 ++ .../gradlewUpdate.sh | 3 + .../settings.gradle | 19 + ...deArbeidsforholdAnsettelseApplication.java | 13 + .../config/ApplicationConfig.java | 16 + .../config/Consumers.java | 33 + .../config/DevConfig.java | 36 + .../config/OpenApiConfig.java | 54 + .../config/SecurityConfig.java | 37 + .../consumers/AaregConsumer.java | 56 ++ .../JacksonExchangeStrategyUtil.java | 25 + .../consumers/KodeverkServiceConsumer.java | 50 + .../consumers/PdlConsumer.java | 74 ++ .../consumers/TagsConsumer.java | 40 + .../consumers/TenorConsumer.java | 50 + .../aareg/HentArbeidsforholdCommand.java | 62 ++ .../aareg/OpprettArbeidsforholdCommand.java | 43 + .../kodeverk/KodeverkServiceCommand.java | 42 + .../consumers/command/pdl/GraphQLRequest.java | 9 + .../command/pdl/HentTagsCommand.java | 47 + .../command/pdl/SokPersonCommand.java | 69 ++ .../command/pdl/SokPersonPagesCommand.java | 69 ++ .../consumers/command/pdl/TemaGrunnlag.java | 6 + .../tenor/HentOrganisasjonCommand.java | 43 + .../HentOrganisasjonerOversiktCommand.java | 45 + .../controller/JobbController.java | 76 ++ .../domain/DatoIntervall.java | 15 + .../domain/TagsDTO.java | 20 + .../domain/dto/AdresseDTO.java | 28 + .../domain/dto/DetaljerDTO.java | 19 + .../domain/dto/NavnDTO.java | 21 + .../domain/dto/OrganisasjonDTO.java | 37 + .../domain/dto/OrganisasjonDetaljerDTO.java | 22 + .../kodeverk/KodeverkBetydningerResponse.java | 58 ++ .../domain/kodeverk/KodeverkNavn.java | 23 + .../domain/kodeverk/KodeverkResponse.java | 15 + .../domain/organisasjon/Adresse.java | 36 + .../domain/organisasjon/Organisasjon.java | 58 ++ .../domain/pdl/Bostedsadresse.java | 14 + .../domain/pdl/CommonKeysAndUtils.java | 10 + .../domain/pdl/Data.java | 12 + .../domain/pdl/Feilmelding.java | 12 + .../domain/pdl/Foedsel.java | 17 + .../pdl/Folkeregisteridentifikator.java | 16 + .../domain/pdl/Folkeregisterpersonstatus.java | 16 + .../domain/pdl/GraphqlVariables.java | 53 + .../domain/pdl/HentPerson.java | 61 ++ .../domain/pdl/Ident.java | 20 + .../domain/pdl/MetadataDTO.java | 21 + .../domain/pdl/Navn.java | 16 + .../domain/pdl/PdlAktoer.java | 57 ++ .../domain/pdl/PdlHeaders.java | 11 + .../domain/pdl/PdlPerson.java | 20 + .../domain/pdl/Request.java | 17 + .../domain/pdl/SokPersonVariables.java | 60 ++ .../domain/pdl/Vegadresse.java | 15 + .../domain/tenor/Hendelse.java | 50 + .../domain/tenor/LabelEnum.java | 6 + .../domain/tenor/Spesifiseringstype.java | 35 + .../domain/tenor/TekniskNavn.java | 430 ++++++++ .../tenor/TenorOrganisasjonRequest.java | 134 +++ .../tenor/TenorOrganisasjonSelectOptions.java | 160 +++ .../TenorOversiktOrganisasjonResponse.java | 48 + .../domain/tenor/TenorRequest.java | 358 +++++++ .../entity/AnsettelseLogg.java | 52 + .../entity/JobbParameter.java | 37 + .../entity/JobbParameterNavn.java | 14 + .../provider/PdlMiljoer.java | 5 + .../repository/AnsettelseLoggRepository.java | 7 + .../repository/JobberRepository.java | 14 + .../service/AnsettelseLoggService.java | 42 + .../service/AnsettelseService.java | 228 +++++ .../service/ArbeidsforholdService.java | 100 ++ .../service/JobbService.java | 62 ++ .../service/KodeverkService.java | 28 + .../service/PdlService.java | 153 +++ .../service/TenorService.java | 121 +++ .../service/util/AlderspennList.java | 38 + .../service/util/AliasMethod.java | 86 ++ .../src/main/resources/ArbeidKodeverk | 28 + .../src/main/resources/application-dev.yml | 45 + .../src/main/resources/application-prod.yml | 15 + .../src/main/resources/application.yml | 66 ++ .../db/migration/V1.0.0_CreateTables.sql | 19 + .../src/main/resources/logback-spring.xml | 40 + .../src/main/resources/pdl/graphql.config.yml | 8 + .../main/resources/pdl/pdl-api-schema.graphql | 943 ++++++++++++++++++ .../src/main/resources/pdl/sokPerson.graphql | 38 + .../main/resources/pdl/sokPersonPages.graphql | 11 + ...eidsforholdAnsettelseApplicationTests.java | 19 + .../.gitignore | 37 + .../Dockerfile | 8 + .../build.gradle | 87 ++ .../config.yml | 47 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43453 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + apps/levende-arbeidsforhold-scheduler/gradlew | 249 +++++ .../gradlew.bat | 92 ++ .../settings.gradle | 21 + ...ndeArbeidsforholdSchedulerApplication.java | 13 + .../config/ApplicationConfig.java | 17 + .../config/Consumers.java | 29 + .../config/DevConfig.java | 2 +- .../config/OpenApiConfig.java | 5 +- .../config/SchedulerConfig.java | 16 + .../config/SecurityConfig.java | 37 + .../consumer/AnsettelseConsumer.java | 33 + .../consumer/command/AnsettelsesCommand.java | 26 + .../controller/JobbController.java | 98 ++ .../domain/StatusRespons.java | 14 + .../scheduler/AnsettelsesService.java | 16 + .../scheduler/JobbScheduler.java | 168 ++++ .../utils/Utils.java | 82 ++ .../src/main/resources/application-dev.yml | 4 + .../src/main/resources/application.yml | 52 + ...beidsforholdSchedulerApplicationTests.java | 13 + .../scheduler/JobbSchedulerTest.java | 44 + .../utils/UtilsTest.java | 15 + .../build.gradle | 1 + .../settings.gradle | 1 + .../consumers/AaregConsumer.java | 77 -- .../domain/v1/Persontype.java | 6 - ...beidsforholdServiceApplicationStarter.java | 2 +- .../config/ApplicationConfig.java | 2 +- .../config/Consumers.java | 2 +- .../config/DevConfig.java | 36 + .../config/KafkaConfig.java | 2 +- .../config/OpenApiConfig.java | 54 + .../config/SecurityConfig.java | 2 +- .../consumers/AaregConsumer.java | 51 + .../command/EndreArbeidsforholdCommand.java | 23 +- .../command/HentArbeidsforholdCommand.java | 37 +- .../listener/DoedsfallListener.java | 4 +- .../service/ArbeidsforholdService.java | 32 +- .../utility/CallIdUtil.java | 17 + .../ApplicationContextTest.java | 2 +- .../config.yml | 2 + apps/oversikt-frontend/config.yml | 3 + .../v1/Ansettelsesperiode.java | 10 +- .../v1/AntallTimerForTimeloennet.java | 16 +- .../v1/Arbeidsavtale.java | 22 +- .../v1/Arbeidsavtaletype.java | 2 +- .../v1/Arbeidsforhold.java | 20 +- .../v1/Arbeidsforholdoversikt.java | 18 +- .../ArbeidsgiverArbeidsforholdoversikter.java | 10 +- .../v1/Arbeidsgiveroversikt.java | 10 +- .../v1/Bruksperiode.java | 20 +- ...orenkletOppgjoersordningArbeidsavtale.java | 4 +- .../v1/FrilanserArbeidsavtale.java | 4 +- .../v1/Gyldighetsperiode.java | 4 +- .../v1/MaritimArbeidsavtale.java | 10 +- .../v1/OpplysningspliktigArbeidsgiver.java | 10 +- .../OpplysningspliktigArbeidsgiverType.java | 2 +- .../v1/OrdinaerArbeidsavtale.java | 4 +- .../v1/Organisasjon.java | 10 +- .../levendearbeidsforhold}/v1/Periode.java | 22 +- .../v1/PermisjonPermittering.java | 10 +- .../dto/levendearbeidsforhold}/v1/Person.java | 16 +- .../levendearbeidsforhold/v1/Persontype.java | 6 + .../dto/levendearbeidsforhold}/v1/README.md | 0 .../v1/Sporingsinformasjon.java | 20 +- .../v1/Utenlandsopphold.java | 16 +- .../dto/levendearbeidsforhold}/v1/Varsel.java | 10 +- .../v1/Varselentitet.java | 2 +- .../v1/util/TimeUtil.java | 4 +- proxies/ereg-proxy/config.yml | 2 + settings.gradle | 6 + 189 files changed, 7779 insertions(+), 331 deletions(-) create mode 100644 .github/workflows/app.levende-arbeidsforhold-ansettelse.yml create mode 100644 .github/workflows/app.levende-arbeidsforhold-scheduler.yml create mode 100644 apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/StatusBox.tsx create mode 100644 apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/util/LevendeArbeidsforholdRequest.tsx create mode 100644 apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/util/Typer.tsx create mode 100644 apps/levende-arbeidsforhold-ansettelse/Dockerfile create mode 100644 apps/levende-arbeidsforhold-ansettelse/README.md create mode 100644 apps/levende-arbeidsforhold-ansettelse/TODO.md create mode 100644 apps/levende-arbeidsforhold-ansettelse/build.gradle create mode 100644 apps/levende-arbeidsforhold-ansettelse/config.yml create mode 100644 apps/levende-arbeidsforhold-ansettelse/gradle/wrapper/gradle-wrapper.jar create mode 100644 apps/levende-arbeidsforhold-ansettelse/gradle/wrapper/gradle-wrapper.properties create mode 100755 apps/levende-arbeidsforhold-ansettelse/gradlew create mode 100644 apps/levende-arbeidsforhold-ansettelse/gradlew.bat create mode 100755 apps/levende-arbeidsforhold-ansettelse/gradlewUpdate.sh create mode 100644 apps/levende-arbeidsforhold-ansettelse/settings.gradle create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/LevendeArbeidsforholdAnsettelseApplication.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/ApplicationConfig.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/Consumers.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/DevConfig.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/OpenApiConfig.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/SecurityConfig.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/AaregConsumer.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/JacksonExchangeStrategyUtil.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/KodeverkServiceConsumer.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/PdlConsumer.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/TagsConsumer.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/TenorConsumer.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/aareg/HentArbeidsforholdCommand.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/aareg/OpprettArbeidsforholdCommand.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/kodeverk/KodeverkServiceCommand.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/GraphQLRequest.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/HentTagsCommand.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/SokPersonCommand.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/SokPersonPagesCommand.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/TemaGrunnlag.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/tenor/HentOrganisasjonCommand.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/tenor/HentOrganisasjonerOversiktCommand.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/controller/JobbController.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/DatoIntervall.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/TagsDTO.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/AdresseDTO.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/DetaljerDTO.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/NavnDTO.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/OrganisasjonDTO.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/OrganisasjonDetaljerDTO.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/kodeverk/KodeverkBetydningerResponse.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/kodeverk/KodeverkNavn.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/kodeverk/KodeverkResponse.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/organisasjon/Adresse.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/organisasjon/Organisasjon.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Bostedsadresse.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/CommonKeysAndUtils.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Data.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Feilmelding.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Foedsel.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Folkeregisteridentifikator.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Folkeregisterpersonstatus.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/GraphqlVariables.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/HentPerson.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Ident.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/MetadataDTO.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Navn.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/PdlAktoer.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/PdlHeaders.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/PdlPerson.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Request.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/SokPersonVariables.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Vegadresse.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/Hendelse.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/LabelEnum.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/Spesifiseringstype.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TekniskNavn.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TenorOrganisasjonRequest.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TenorOrganisasjonSelectOptions.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TenorOversiktOrganisasjonResponse.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TenorRequest.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/entity/AnsettelseLogg.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/entity/JobbParameter.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/entity/JobbParameterNavn.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/provider/PdlMiljoer.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/repository/AnsettelseLoggRepository.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/repository/JobberRepository.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/AnsettelseLoggService.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/AnsettelseService.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/ArbeidsforholdService.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/JobbService.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/KodeverkService.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/PdlService.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/TenorService.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/util/AlderspennList.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/util/AliasMethod.java create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/resources/ArbeidKodeverk create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/resources/application-dev.yml create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/resources/application-prod.yml create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/resources/application.yml create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/resources/db/migration/V1.0.0_CreateTables.sql create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/resources/logback-spring.xml create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/graphql.config.yml create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/pdl-api-schema.graphql create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/sokPerson.graphql create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/sokPersonPages.graphql create mode 100644 apps/levende-arbeidsforhold-ansettelse/src/test/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/LevendeArbeidsforholdAnsettelseApplicationTests.java create mode 100644 apps/levende-arbeidsforhold-scheduler/.gitignore create mode 100644 apps/levende-arbeidsforhold-scheduler/Dockerfile create mode 100644 apps/levende-arbeidsforhold-scheduler/build.gradle create mode 100644 apps/levende-arbeidsforhold-scheduler/config.yml create mode 100644 apps/levende-arbeidsforhold-scheduler/gradle/wrapper/gradle-wrapper.jar create mode 100644 apps/levende-arbeidsforhold-scheduler/gradle/wrapper/gradle-wrapper.properties create mode 100755 apps/levende-arbeidsforhold-scheduler/gradlew create mode 100644 apps/levende-arbeidsforhold-scheduler/gradlew.bat create mode 100644 apps/levende-arbeidsforhold-scheduler/settings.gradle create mode 100644 apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/LevendeArbeidsforholdSchedulerApplication.java create mode 100644 apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/ApplicationConfig.java create mode 100644 apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/Consumers.java rename apps/{levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold => levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler}/config/DevConfig.java (95%) rename apps/{levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold => levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler}/config/OpenApiConfig.java (97%) create mode 100644 apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/SchedulerConfig.java create mode 100644 apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/SecurityConfig.java create mode 100644 apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/consumer/AnsettelseConsumer.java create mode 100644 apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/consumer/command/AnsettelsesCommand.java create mode 100644 apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/controller/JobbController.java create mode 100644 apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/domain/StatusRespons.java create mode 100644 apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/scheduler/AnsettelsesService.java create mode 100644 apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/scheduler/JobbScheduler.java create mode 100644 apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/utils/Utils.java create mode 100644 apps/levende-arbeidsforhold-scheduler/src/main/resources/application-dev.yml create mode 100644 apps/levende-arbeidsforhold-scheduler/src/main/resources/application.yml create mode 100644 apps/levende-arbeidsforhold-scheduler/src/test/java/no/nav/testnav/levendearbeidsforholdscheduler/LevendeArbeidsforholdSchedulerApplicationTests.java create mode 100644 apps/levende-arbeidsforhold-scheduler/src/test/java/no/nav/testnav/levendearbeidsforholdscheduler/scheduler/JobbSchedulerTest.java create mode 100644 apps/levende-arbeidsforhold-scheduler/src/test/java/no/nav/testnav/levendearbeidsforholdscheduler/utils/UtilsTest.java delete mode 100644 apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/consumers/AaregConsumer.java delete mode 100644 apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Persontype.java rename apps/levende-arbeidsforhold-service/src/main/java/no/nav/{registre/testnorge/levendearbeidsforhold => testnav/levendearbeidsforholdservice}/LevendeArbeidsforholdServiceApplicationStarter.java (86%) rename apps/levende-arbeidsforhold-service/src/main/java/no/nav/{registre/testnorge/levendearbeidsforhold => testnav/levendearbeidsforholdservice}/config/ApplicationConfig.java (87%) rename apps/levende-arbeidsforhold-service/src/main/java/no/nav/{registre/testnorge/levendearbeidsforhold => testnav/levendearbeidsforholdservice}/config/Consumers.java (93%) create mode 100644 apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/DevConfig.java rename apps/levende-arbeidsforhold-service/src/main/java/no/nav/{registre/testnorge/levendearbeidsforhold => testnav/levendearbeidsforholdservice}/config/KafkaConfig.java (98%) create mode 100644 apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/OpenApiConfig.java rename apps/levende-arbeidsforhold-service/src/main/java/no/nav/{registre/testnorge/levendearbeidsforhold => testnav/levendearbeidsforholdservice}/config/SecurityConfig.java (96%) create mode 100644 apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/consumers/AaregConsumer.java rename apps/levende-arbeidsforhold-service/src/main/java/no/nav/{registre/testnorge/levendearbeidsforhold => testnav/levendearbeidsforholdservice}/consumers/command/EndreArbeidsforholdCommand.java (70%) rename apps/levende-arbeidsforhold-service/src/main/java/no/nav/{registre/testnorge/levendearbeidsforhold => testnav/levendearbeidsforholdservice}/consumers/command/HentArbeidsforholdCommand.java (66%) rename apps/levende-arbeidsforhold-service/src/main/java/no/nav/{registre/testnorge/levendearbeidsforhold => testnav/levendearbeidsforholdservice}/listener/DoedsfallListener.java (91%) rename apps/levende-arbeidsforhold-service/src/main/java/no/nav/{registre/testnorge/levendearbeidsforhold => testnav/levendearbeidsforholdservice}/service/ArbeidsforholdService.java (56%) create mode 100644 apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/utility/CallIdUtil.java rename apps/levende-arbeidsforhold-service/src/test/java/no/nav/{registre/testnorge/levendearbeidsforhold => testnav/levendearbeidsforholdservice}/ApplicationContextTest.java (89%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/Ansettelsesperiode.java (88%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/AntallTimerForTimeloennet.java (79%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/Arbeidsavtale.java (87%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/Arbeidsavtaletype.java (77%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/Arbeidsforhold.java (88%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/Arbeidsforholdoversikt.java (89%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/ArbeidsgiverArbeidsforholdoversikter.java (89%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/Arbeidsgiveroversikt.java (84%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/Bruksperiode.java (81%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/ForenkletOppgjoersordningArbeidsavtale.java (91%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/FrilanserArbeidsavtale.java (91%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/Gyldighetsperiode.java (87%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/MaritimArbeidsavtale.java (90%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/OpplysningspliktigArbeidsgiver.java (79%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/OpplysningspliktigArbeidsgiverType.java (54%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/OrdinaerArbeidsavtale.java (91%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/Organisasjon.java (87%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/Periode.java (77%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/PermisjonPermittering.java (88%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/Person.java (80%) create mode 100644 libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Persontype.java rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/README.md (100%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/Sporingsinformasjon.java (83%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/Utenlandsopphold.java (80%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/Varsel.java (80%) rename {apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold}/v1/Varselentitet.java (74%) rename apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/util/JavaTimeUtil.java => libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/util/TimeUtil.java (93%) diff --git a/.github/workflows/app.levende-arbeidsforhold-ansettelse.yml b/.github/workflows/app.levende-arbeidsforhold-ansettelse.yml new file mode 100644 index 00000000000..3b0ea26af28 --- /dev/null +++ b/.github/workflows/app.levende-arbeidsforhold-ansettelse.yml @@ -0,0 +1,26 @@ +name: levende-arbeidsforhold-ansettelse + +on: + push: + paths: + - libs/commands/** + - libs/data-transfer-objects/** + - libs/security-core/** + - libs/servlet-core/** + - libs/servlet-security/** + - libs/servlet-insecure-security/** + - apps/levende-arbeidsforhold-ansettelse/** + - .github/workflows/app.levende-arbeidsforhold-ansettelse.yml + + +jobs: + workflow: + uses: ./.github/workflows/common.workflow.backend.yml + with: + working-directory: "apps/levende-arbeidsforhold-ansettelse" + deploy-tag: "#deploy-levende-arbeidsforhold-ansettelse" + sonar-enabled: false + permissions: + contents: read + id-token: write + secrets: inherit diff --git a/.github/workflows/app.levende-arbeidsforhold-scheduler.yml b/.github/workflows/app.levende-arbeidsforhold-scheduler.yml new file mode 100644 index 00000000000..c787c4db4f5 --- /dev/null +++ b/.github/workflows/app.levende-arbeidsforhold-scheduler.yml @@ -0,0 +1,25 @@ +name: levende-arbeidsforhold-scheduler + +on: + push: + paths: + - libs/commands/** + - libs/data-transfer-objects/** + - libs/security-core/** + - libs/servlet-core/** + - libs/servlet-security/** + - apps/levende-arbeidsforhold-scheduler/** + - .github/workflows/app.levende-arbeidsforhold-scheduler.yml + + +jobs: + workflow: + uses: ./.github/workflows/common.workflow.backend.yml + with: + working-directory: "apps/levende-arbeidsforhold-scheduler" + deploy-tag: "#deploy-levende-arbeidsforhold-scheduler" + sonar-enabled: false + permissions: + contents: read + id-token: write + secrets: inherit diff --git a/apps/dolly-frontend/config.yml b/apps/dolly-frontend/config.yml index 9307d463c81..3dc3fb906cc 100644 --- a/apps/dolly-frontend/config.yml +++ b/apps/dolly-frontend/config.yml @@ -64,6 +64,9 @@ spec: - application: testnav-varslinger-service - application: testnorge-profil-api - application: testnorge-tilbakemelding-api + - application: testnav-levende-arbeidsforhold-ansettelse + - application: testnav-levende-arbeidsforhold-scheduler + external: - host: testnav-pensjon-testdata-facade-proxy.dev-fss-pub.nais.io - host: testnav-sigrunstub-proxy.dev-fss-pub.nais.io diff --git a/apps/dolly-frontend/src/main/java/no/nav/dolly/web/DollyFrontendApplicationStarter.java b/apps/dolly-frontend/src/main/java/no/nav/dolly/web/DollyFrontendApplicationStarter.java index 06c00ec7121..1ed7244d723 100644 --- a/apps/dolly-frontend/src/main/java/no/nav/dolly/web/DollyFrontendApplicationStarter.java +++ b/apps/dolly-frontend/src/main/java/no/nav/dolly/web/DollyFrontendApplicationStarter.java @@ -83,6 +83,8 @@ public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { .route(createRoute(consumers.getGenererNavnService())) .route(createRoute(consumers.getTestnavKodeverkService())) .route(createRoute(consumers.getTestnavTenorSearchService())) + .route(createRoute(consumers.getTestnavLevendeArbeidsforholdAnsettelse(), "testnav-levende-arbeidsforhold-ansettelse")) + .route(createRoute(consumers.getTestnavLevendeArbeidsforholdScheduler(), "testnav-levende-arbeidsforhold-scheduler")) .build(); } diff --git a/apps/dolly-frontend/src/main/java/no/nav/dolly/web/config/Consumers.java b/apps/dolly-frontend/src/main/java/no/nav/dolly/web/config/Consumers.java index e6a490b6be1..1fa869c9e14 100644 --- a/apps/dolly-frontend/src/main/java/no/nav/dolly/web/config/Consumers.java +++ b/apps/dolly-frontend/src/main/java/no/nav/dolly/web/config/Consumers.java @@ -62,5 +62,7 @@ public class Consumers { private ServerProperties testnorgeProfilApi; private ServerProperties testnorgeTilbakemeldingApi; private ServerProperties testnavTenorSearchService; + private ServerProperties testnavLevendeArbeidsforholdAnsettelse; + private ServerProperties testnavLevendeArbeidsforholdScheduler; } diff --git a/apps/dolly-frontend/src/main/js/proxy-routes.json b/apps/dolly-frontend/src/main/js/proxy-routes.json index 0b650890bcf..6275c7ed9ad 100644 --- a/apps/dolly-frontend/src/main/js/proxy-routes.json +++ b/apps/dolly-frontend/src/main/js/proxy-routes.json @@ -228,5 +228,15 @@ "target": "http://localhost:8020", "changeOrigin": true, "secure": false + }, + "/testnav-levende-arbeidsforhold-ansettelse/api": { + "target": "http://localhost:8020", + "changeOrigin": true, + "secure": false + }, + "/testnav-levende-arbeidsforhold-scheduler/scheduler": { + "target": "http://localhost:8020", + "changeOrigin": true, + "secure": false } } \ No newline at end of file diff --git a/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/AppstyringPage.tsx b/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/AppstyringPage.tsx index 5356cbfd244..de8c0d278ad 100644 --- a/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/AppstyringPage.tsx +++ b/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/AppstyringPage.tsx @@ -1,34 +1,115 @@ -import { AdminAccessDenied } from '@/pages/adminPages/AdminAccessDenied' -import { Alert } from '@navikt/ds-react' -import { AppstyringTable } from '@/pages/adminPages/Appstyring/AppstyringTable' -import { erDollyAdmin } from '@/utils/DollyAdmin' +import {AdminAccessDenied} from '@/pages/adminPages/AdminAccessDenied' +import {Alert, Button} from '@navikt/ds-react' +import {AppstyringTable} from '@/pages/adminPages/Appstyring/AppstyringTable' +import {erDollyAdmin} from '@/utils/DollyAdmin' +import React, {useEffect, useState} from "react"; +import {FetchData, Jobbstatus} from "@/pages/adminPages/Appstyring/util/Typer"; +import {StatusBox} from "@/pages/adminPages/Appstyring/StatusBox"; export default () => { if (!erDollyAdmin()) { - return + return } - //TODO: Implementer henting av data fra backend - const dataMock = [ - { parameter: 'Parameter 1', verdi: 'verdi1' }, - { parameter: 'Parameter 2', verdi: 'verdi2' }, - { parameter: 'Parameter 3', verdi: 'verdi3' }, - { parameter: 'Parameter 4', verdi: 'verdi4' }, - { parameter: 'Parameter 5', verdi: 'verdi5' }, - { parameter: 'Parameter 6', verdi: 'verdi6' }, - { parameter: 'Parameter 7', verdi: 'verdi7' }, - { parameter: 'Parameter 8', verdi: 'verdi8' }, - { parameter: 'Parameter 9', verdi: 'verdi9' }, - { parameter: 'Parameter 10', verdi: 'verdi10' }, - ] + const [apiData , setApiData] = useState>([]); + const [statusData , setStatusData] = useState({nesteKjoring: "", status: false}); + const [henterStatus, setHenterStatus] = useState(false); + + let optionsData: FetchData[] = []; + + const SCHEDULER_DOMENE : string = "/testnav-levende-arbeidsforhold-scheduler"; + const ANSETTELSE_DOMENE : string = "/testnav-levende-arbeidsforhold-ansettelse"; + + /** + * Callback-funksjon som behandler feil ved API-spørringer. Dersom en feilmelding ikke er spesifisert, så betyr det + * at feilen ved spørringen skjedde på klienten sin side og kjører med default parameter verdi + */ + function feilHandtering(feilMelding : string = "Spørring feilet, sjekk internettforbindelsen og prøv igjen!"){ + alert(feilMelding); + } + + /** + * Funksjon som aktiverer jobb-scheduler + */ + async function aktiverScheduler(){ + + let intervall = apiData.find(d => d.navn == "intervall"); + + if (intervall){ + await sendSporringScheduler(`${SCHEDULER_DOMENE}/scheduler?intervall=${intervall.verdi}`); + } else { + feilHandtering("Intervall er ikke spesifisert") + } + } + + /** + * Funksjon som deaktiverer jobb-scheduler + */ + async function deaktiverScheduler(){ + if (window.confirm("Vil du deaktivere jobben? Du kan aktivere ny jobb igjen når som helst.")){ + await sendSporringScheduler(`${SCHEDULER_DOMENE}/scheduler/stopp`); + } + } + + /** + * Funksjon som kan brukes til å sende spørring til scheduler appen sitt API for å enten aktiver eller deaktivere + * scheduler basert på url parameteren + * @param url URL til endepunktet i scheduler APIet som spørring skal sendes til + */ + async function sendSporringScheduler(url : string){ + setHenterStatus(true); + await fetch(url).then(async res => { + + setTimeout(()=>{ + if (!res.ok) { + feilHandtering(`${res.body}`); + } + + fetchStatusScheduler(); + setHenterStatus(false); + }, 200) + }).catch(feilHandtering); + } + /** + * Funksjon som sender spørring til scheduler appen sitt API for å hente ut status på om scheduleren er aktiv + * eller ikke + */ + async function fetchStatusScheduler() { + const data = await fetch(`${SCHEDULER_DOMENE}/scheduler/status`) + .then(res => res.json()) + .catch(feilHandtering); + setStatusData(data); + } + + /** + * Funksjon som henter ut dataen for parameterne som brukes i jobben (aka ansettelses-jobben) som kjøres av + * scheduleren for det gitte intervallet + */ + async function hentParametere() { + await fetch(`${ANSETTELSE_DOMENE}/api`) + .then(res => res.json()) + .then(res => { + res.map((r: FetchData) => optionsData.push(r)) + + }).catch(err => console.error(err)); + setApiData(optionsData); + } + + useEffect(() => { + hentParametere(); + fetchStatusScheduler(); + }, []); + return ( <>

App-styring

- + Denne siden er under utvikling. - + + {!statusData.status ? : } + ) -} +} \ No newline at end of file diff --git a/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/AppstyringTable.tsx b/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/AppstyringTable.tsx index 4a33377fbd2..d765df25329 100644 --- a/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/AppstyringTable.tsx +++ b/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/AppstyringTable.tsx @@ -1,24 +1,10 @@ -import { Box, Table } from '@navikt/ds-react' +import {Box, Table} from '@navikt/ds-react' import React from 'react' -import { ErrorBoundary } from '@/components/ui/appError/ErrorBoundary' -import { EditParameter } from '@/pages/adminPages/Appstyring/EditParameter' +import {ErrorBoundary} from '@/components/ui/appError/ErrorBoundary' +import {EditParameter} from '@/pages/adminPages/Appstyring/EditParameter' +import {FetchData} from "@/pages/adminPages/Appstyring/util/Typer"; -export const AppstyringTable = ({ data }: any) => { - //TODO: Implementer henting av options pr parameter fra backend - const getOptions = (parameter: string) => { - return [ - { value: 'verdi1', label: 'Verdi 1' }, - { value: 'verdi2', label: 'Verdi 2' }, - { value: 'verdi3', label: 'Verdi 3' }, - { value: 'verdi4', label: 'Verdi 4' }, - { value: 'verdi5', label: 'Verdi 5' }, - { value: 'verdi6', label: 'Verdi 6' }, - { value: 'verdi7', label: 'Verdi 7' }, - { value: 'verdi8', label: 'Verdi 8' }, - { value: 'verdi9', label: 'Verdi 9' }, - { value: 'verdi10', label: 'Verdi 10' }, - ] - } +export const AppstyringTable = ({data, setData}: { data: Array, setData: (data: Array) => void }) => { return ( @@ -30,16 +16,19 @@ export const AppstyringTable = ({ data }: any) => { Rediger - {data.map((row: any, idx: number) => { + {data.map((row: FetchData, idx: number) => { return ( - - {row.parameter} + + {row.tekst} {row.verdi} diff --git a/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/EditParameter.tsx b/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/EditParameter.tsx index c98bc49ed4b..3e6b5c4bb4e 100644 --- a/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/EditParameter.tsx +++ b/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/EditParameter.tsx @@ -1,24 +1,55 @@ -import { PencilWritingIcon } from '@navikt/aksel-icons' -import { Button } from '@navikt/ds-react' +import {PencilWritingIcon} from '@navikt/aksel-icons' +import {Button, Select} from '@navikt/ds-react' import React from 'react' import useBoolean from '@/utils/hooks/useBoolean' import DollyModal from '@/components/ui/modal/DollyModal' -import ModalActionKnapper from '@/components/ui/modal/ModalActionKnapper' -import { FormSelect } from '@/components/ui/form/inputs/select/Select' -import { ErrorBoundary } from '@/components/ui/appError/ErrorBoundary' -import { FormProvider, useForm } from 'react-hook-form' +import {ErrorBoundary} from '@/components/ui/appError/ErrorBoundary' +import {useForm} from 'react-hook-form' +import {FetchData} from "@/pages/adminPages/Appstyring/util/Typer"; -export const EditParameter = ({ name, initialValue, getOptions }: any) => { +interface Props { + name: string, + label: string + initialValue: string, + options: Array + data: Array + setData: (data: Array) => void +} + +export const EditParameter = ({name, label, initialValue, options, data, setData }: Props) => { const [modalIsOpen, openModal, closeModal] = useBoolean(false) - const formMethods = useForm({ defaultValues: { [name]: initialValue } }) + //const formMethods = useForm({ defaultValues: { [name]: initialValue } }) - //TODO: Implementer lagring av verdi paa parameter - const onSubmit = (data: any) => { - console.log('Lagrer... ', data) //TODO - SLETT MEG - closeModal() + const { register, handleSubmit, formState: { errors} } = useForm<{value: string}>( + { defaultValues: {value: initialValue}}) + + + async function oppdaterParameterverdi(value: string) { + await fetch(`/testnav-levende-arbeidsforhold-ansettelse/api/oppdatereVerdier/${name}`, + {method: "PUT", body: JSON.stringify(value)}).then(res => res.status === 200 ? onSubmit(value) : console.error('Feil feil feil')); } - const options = getOptions(name) + const validerParameter = (value: string | undefined): string | undefined => { + if (name === "antallOrganisasjoner") { + const antallPersoner = data.find(obj => obj.navn === "antallPersoner")?.verdi + if (!value) return 'Må settes' + else if (Number.parseInt(value!) > Number.parseInt(antallPersoner!)) return `Kan ikke være flere organisasjoner enn antall personer` + } + else if (name === "antallPersoner") { + const antallOrganisasjoner = data.find(obj => obj.navn === "antallOrganisasjoner")?.verdi + if (!value) return 'Må settes' + else if (Number.parseInt(value!) < Number.parseInt(antallOrganisasjoner!)) return `Kan ikke være færre personer enn antall organisasjoner` + } + return undefined + } + + const onSubmit = (value: string) => { + const kopi = [...data] + const nyttObjektIndex = kopi.findIndex(obj => obj.navn === name) + kopi[nyttObjektIndex] = {...kopi[nyttObjektIndex], verdi: value} + setData(kopi) + closeModal() + } return ( <> @@ -29,21 +60,24 @@ export const EditParameter = ({ name, initialValue, getOptions }: any) => { size={'small'} /> - +
{ + oppdaterParameterverdi(value) + })}>

Rediger parameter


- - + +
+
-
) diff --git a/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/StatusBox.tsx b/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/StatusBox.tsx new file mode 100644 index 00000000000..50e83eae818 --- /dev/null +++ b/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/StatusBox.tsx @@ -0,0 +1,24 @@ +import {Alert, VStack} from "@navikt/ds-react"; +import React from "react"; +import {Jobbstatus} from "@/pages/adminPages/Appstyring/util/Typer"; + + +export const StatusBox = (data: Jobbstatus) => { + + const renderedBox = (status: boolean) => { + if (!status) { + return + Ingen aktiv jobb + + } + return + Aktiv jobb: Neste kjøring vil starte {data.nesteKjoring} + + } + + return ( + + {renderedBox(data.status)} + + ); +}; \ No newline at end of file diff --git a/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/util/LevendeArbeidsforholdRequest.tsx b/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/util/LevendeArbeidsforholdRequest.tsx new file mode 100644 index 00000000000..9c532b4ece6 --- /dev/null +++ b/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/util/LevendeArbeidsforholdRequest.tsx @@ -0,0 +1,13 @@ + +export const REQUEST_ERROR = 'REQUEST_ERROR' + +export const runningE2ETest = () => { + // @ts-ignore + return window?.isRunningTest +} + +export default class LevendeArbeidsforholdRequest { + static get(url: string, headers: Record = {}) { + return + } +} \ No newline at end of file diff --git a/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/util/Typer.tsx b/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/util/Typer.tsx new file mode 100644 index 00000000000..dcc96feefe1 --- /dev/null +++ b/apps/dolly-frontend/src/main/js/src/pages/adminPages/Appstyring/util/Typer.tsx @@ -0,0 +1,11 @@ +export interface FetchData { + navn: string + tekst: string + verdi: string + verdier: Array +} + +export interface Jobbstatus { + nesteKjoring: string + status: boolean +} \ No newline at end of file diff --git a/apps/dolly-frontend/src/main/resources/application-local.yml b/apps/dolly-frontend/src/main/resources/application-local.yml index d25e52393fe..1793e88c46b 100644 --- a/apps/dolly-frontend/src/main/resources/application-local.yml +++ b/apps/dolly-frontend/src/main/resources/application-local.yml @@ -75,4 +75,8 @@ consumers: testnav-kodeverk-service: url: https://testnav-kodeverk-service.intern.dev.nav.no/ testnav-tenor-search-service: - url: https://testnav-tenor-search-service.intern.dev.nav.no \ No newline at end of file + url: https://testnav-tenor-search-service.intern.dev.nav.no + testnav-levende-arbeidsforhold-ansettelse: + url: https://testnav-levende-arbeidsforhold-ansettelse.intern.dev.nav.no + testnav-levende-arbeidsforhold-scheduler: + url: https://testnav-levende-arbeidsforhold-scheduler.intern.dev.nav.no \ No newline at end of file diff --git a/apps/dolly-frontend/src/main/resources/application.yml b/apps/dolly-frontend/src/main/resources/application.yml index e92d3318b18..70c47a66318 100644 --- a/apps/dolly-frontend/src/main/resources/application.yml +++ b/apps/dolly-frontend/src/main/resources/application.yml @@ -218,6 +218,16 @@ consumers: namespace: dolly name: testnav-tenor-search-service url: http://testnav-tenor-search-service.dolly.svc.cluster.local + testnav-levende-arbeidsforhold-ansettelse: + cluster: dev-gcp + namespace: dolly + name: testnav-levende-arbeidsforhold-ansettelse + url: http://testnav-levende-arbeidsforhold-ansettelse.dolly.svc.cluster.local + testnav-levende-arbeidsforhold-scheduler: + cluster: dev-gcp + namespace: dolly + name: testnav-levende-arbeidsforhold-scheduler + url: http://testnav-levende-arbeidsforhold-scheduler.dolly.svc.cluster.local management: endpoints: diff --git a/apps/levende-arbeidsforhold-ansettelse/Dockerfile b/apps/levende-arbeidsforhold-ansettelse/Dockerfile new file mode 100644 index 00000000000..dd8161548f8 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/Dockerfile @@ -0,0 +1,8 @@ +FROM ghcr.io/navikt/baseimages/temurin:21 +LABEL maintainer="Team Dolly" + +ENV JAVA_OPTS="-Dspring.profiles.active=prod" + +ADD /build/libs/app.jar /app/app.jar + +EXPOSE 8080 \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/README.md b/apps/levende-arbeidsforhold-ansettelse/README.md new file mode 100644 index 00000000000..fceaff59f07 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/README.md @@ -0,0 +1,107 @@ +# Levende arbeidsforhold-ansettelse + + +## Swagger + +Swagger finnes under [/swagger](https://testnav-levende-arbeidsforhold-ansettelse.intern.dev.nav.no/swagger-ui/index.html#/jobb-controller/ansettelseJobb) -endepunktet til +applikasjonen. + +## Forbedringspotensial +* Nå så blir samme antall mennesker ansatt i hver organisasjon og vi tenker at dette er noe som kan bli forbedret. +* Vi har ikke lagt til forskjellige arbeidsforhold typer noe som kan gjøre dette mer realistisk. +* Vi gjør nå to oppslag i search-tenor-service noe som vi tenker kan reduseres til en ved å gjøre endringer i tenor-searc-service eller forandre hvordan denne appen finner organisasjoner. +* Å gjøre mengden mennesker som blir hentet i PdlService mer dynamisk. +* Skrive om til å bruke asynchronous (flux) overalt. + +## Flyt +For å starte en jobb så bruker man endepunktet "/api/ansettelse-jobb", som vil kalle på runAnsettelsesService i AnsettelseService.java. + +Det er i AnsettelsesService hvor selve logikken i applikasjonen blir gjennomført. +Flyten i AnsettelsesService: +1. i AnsettelsesService er at runAnsettelsesService lager en thread slik at vi kunne implementere en timeout funksjon i tilfelle +det skjedde en uendelig loop. +2. ansettelseService blir kalt. +3. Henter yrke kodene fra KodeverkService -> KodeverkConsumer -> KodeverkCommand. For å kunne gi de syntetiske personene tilfeldig yrke. +4. Så initialiseres alderspennlisten som er gitt i /service/util/AlderspennList.java hvor alderspennene som kan bli valgt utifra er gitt. +5. Så blir alias tabellen initialisert ved å bruke sannsynlighetsfordeling som er gitt i /service/util/AlderspennList +6. Så blir parameterne hentet fra jobb-parameter db som ett map. +7. Henter antallet organisasjoner fra TenorService.java -> TenorConsumer -> TenorCommand +8. Går igjennom hver organisasjon og henter personer fra pdl, med samme første siffer i postnummer med det gitte aldersintervallet som blir bestemt fra aliastabellen. +9. PdlService vil sjekke om personen ikke er i bruk ved å sjekke om de bare har "TESTNORGE" tag. +10. Velger så ut en tilfeldig person fra de mulige personene og sjekker om denne kan ansettes, ved å se om den kombinerte nye stillingsprosenten <=100. Dette gjøres ved å hente eksisterende arbeidsforhold fra aareg. +11. Hvis personen ikke kan ansettes så fjernes denne personen fra mulige personer og en ny velges. +12. Hvis personen kan ansettes så blir en ny arbeidsavtale oprettet ved å opprette ett arbeidsforhold i aareg via AnsettelsesService.java +13. Så blir personene som er ansatt i denne organisajonen logget til ansettelse-logg db. +14. Så blir skritt 8-13 gjentatt for det riktige antallet personer og organisasjoner. + +## Services +TenorService.java +* Henter Organisasjoner og OrganisasjonsOrvesik fra app: tenor-search-service +PdlService +* Henter personer fra pdl gjennom pdl-proxy og bruker graphQL for å hente personer med de hensynene vi trenger. +* Henter også tags i bolk for å sjekke om personene ikke er i bruk (at de bare har "TESTNORGE" taggen) +KodeverkService +* Henter kodeverk som en List som er en liste av kodene fra app: kodeverk-service +JobbService +* Klassen som henter og oppdaterer jobb_parameter db. +ArbeidsforholdService +* Henter og oppretter arbeidsforhold fra aareg igjennom aareg-proxy +AnsettelsesService +* Klassen som inneholder logikken for å ansette mennesker i organisasjoner. + * Tar hensyn til lokasjon ved at første siffer i postnummeret til personen og organisasjonen skal være likt + * Tar hensyn til alder ved å å trekke ut ett alderspenn ved å bruke alias metoden + * Kan ansette mennesker med forskjellig stillingsprosent ved at ansettelsesService sjekker at ikke den totale gjeldende stillingsprosenten er over 100% +* Henter verdiene som skal brukes fra jobb_parameter db +* Logger de som er ansatt i ansettelse_logg db +AnssettelsesLoggService +* Klassen som logger til ansettelses_logg db + +### Forklaring av alias metoden +Alias metoden fungerer slik at når man initaliserer alias metoden så vil den lage en alias tabell +av sannsynlighetsfordelingen som er gitt, denne sannsynlighetsfordeling trenger ikke å være normalisert +siden det er det første metoden gjør. +Man kan se på alias tabellen slik at hver indeks korresponderer til 1/n av den totale sannsynligheten. +Hvis ett utfall har større sannsynlighet enn dette så må den bli delt opp og fordelt til utfall som har en mindre sannsynlighet. +Se: https://pbr-book.org/4ed/Sampling_Algorithms/The_Alias_Method og https://en.wikipedia.org/wiki/Alias_method +for en mer inngående forklaring. + +For å sette opp tabellen har en kompleksitet på O(nlogn), men hvert trekk fra alis tabllen vil ha en kompleksitet av O(1). +Dette betyr at dette er en mer effektiv metode å gjøre trekk fra en sannsynlighets fordeling med distinkte sannsynligheter. + +### Sannsynlighetsfordelingen: +Jeg fant disse tallene fra ssb i tabell 1 som vi følte korresponderte til det vi skulle. +https://www.ssb.no/arbeid-og-lonn/sysselsetting/statistikk/antall-arbeidsforhold-og-lonn + +| Alder | <25 | 25-39 | 40-54 | 55-66 | over 67 | +|---|---------|-----------|---------|---------|---------| +| Antall | 436 106 | 1 022 448 | 976 833 | 563 804 | 72 363 | + +### Apper testnav-levende-arbeidsforhold-ansettelse prater med +* pdl-proxy +* aareg-proxy +* tenor-search-service +* kodeverk-service + +### Persistent lagring +* testnav-levende-arbeidsforhold-ansettelse: + * jobb_parameter: Database for å lagre de forskjellige parameterene som kan stilles på, og verdien som er aktiv pluss en text array med mulige verdier. + * ansettelse_logg: Database for å logge hvem som har blitt ansatt i hvem organisasjon. + + +## Lokal kjøring + +Ha naisdevice kjørende og kjør GenererNavnServiceApplicationStarter med følgende argumenter: + +``` +-Dspring.cloud.vault.token=[vault-token] +-Dspring.profiles.active=dev +``` + +### Utviklerimage + +I utviklerimage brukes ikke naisdevice og du må legge til følgende ekstra argumenter: + +``` +-Djavax.net.ssl.trustStore=[path til lokal truststore] +-Djavax.net.ssl.trustStorePassword=[passord til lokal truststore] +``` diff --git a/apps/levende-arbeidsforhold-ansettelse/TODO.md b/apps/levende-arbeidsforhold-ansettelse/TODO.md new file mode 100644 index 00000000000..505b7c190fc --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/TODO.md @@ -0,0 +1,6 @@ + +### TODO liste +1. Admin siden og deploye front-end +2. Lag slik at man kan kjøre jobben så ofte som behøves +3. Rydde og gjøre koden mer leselig +4. Hvis vi får tid kanskje skrive om slik at vi bruker flux (async) istedenfor mono. \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/build.gradle b/apps/levende-arbeidsforhold-ansettelse/build.gradle new file mode 100644 index 00000000000..4adade239f3 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/build.gradle @@ -0,0 +1,68 @@ +plugins { + id "dolly-apps" +} + +test { + useJUnitPlatform() +} + +sonarqube { + properties { + property "sonar.dynamicAnalysis", "reuseReports" + property "sonar.host.url", "https://sonarcloud.io" + property "sonar.java.coveragePlugin", "jacoco" + property "sonar.language", "java" + property "sonar.token", System.getenv("SONAR_TOKEN") + property "sonar.organization", "navikt" + property "sonar.project.monorepo.enabled", true + property "sonar.projectKey", "testnav-levende-arbeidsforhold-ansettelse" + property "sonar.projectName", "testnav-levende-arbeidsforhold-ansettelse" + property "sonar.sourceEncoding", "UTF-8" + } +} + + +dependencies { + implementation 'no.nav.testnav.libs:security-core' + implementation 'no.nav.testnav.libs:reactive-core' + implementation 'no.nav.testnav.libs:servlet-core' + implementation 'no.nav.testnav.libs:servlet-insecure-security' + implementation 'no.nav.testnav.libs:data-transfer-objects' + + implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + + implementation 'org.springframework.cloud:spring-cloud-starter-vault-config' + + implementation 'org.postgresql:postgresql:42.7.2' + + implementation 'io.micrometer:micrometer-registry-prometheus' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0' + implementation 'io.swagger.core.v3:swagger-annotations-jakarta:2.2.21' + + implementation 'org.hibernate.validator:hibernate-validator' + + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.cloud:spring-cloud-contract-wiremock' + + implementation 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + testAnnotationProcessor 'org.projectlombok:lombok' + + implementation 'com.zaxxer:HikariCP' + implementation 'com.h2database:h2' + + //Spesifiserer versjoner av dependencies' dependencies som er utdatert og har sikkerhets-risikoer, bruker derfor de nedenfor + implementation 'org.apache.commons:commons-compress:1.26.2' + implementation 'org.apache.tomcat.embed:tomcat-embed-core:10.1.25' + implementation 'org.apache.tomcat.embed:tomcat-embed-websocket:10.1.19' + implementation 'org.apache.tomcat.embed:tomcat-embed-core:10.1.25' + implementation 'org.springframework.security:spring-security-core:6.2.3' + implementation 'org.springframework:spring-core:6.1.3' + implementation 'org.springframework:spring-web:6.1.6' + implementation 'com.nimbusds:nimbus-jose-jwt:9.37.2' + implementation 'io.netty:netty-codec-http:4.1.108.Final' + implementation 'com.h2database:h2:2.3.230' + implementation 'org.bouncycastle:bcprov-jdk18on:1.78' +} + diff --git a/apps/levende-arbeidsforhold-ansettelse/config.yml b/apps/levende-arbeidsforhold-ansettelse/config.yml new file mode 100644 index 00000000000..5a6b3fe7b9a --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/config.yml @@ -0,0 +1,68 @@ +apiVersion: nais.io/v1alpha1 +kind: Application +metadata: + name: testnav-levende-arbeidsforhold-ansettelse + namespace: dolly + labels: + team: dolly +spec: + image: "{{image}}" + port: 8080 + accessPolicy: + inbound: + rules: + - application: team-dolly-lokal-app + - application: testnav-oversikt-frontend + - application: dolly-frontend + - application: testnav-levende-arbeidsforhold-scheduler + outbound: + rules: + - application: testnav-levende-arbeidsforhold-scheduler + - application: testnav-kodeverk-service + - application: testnav-tenor-search-service + + external: + - host: testnav-aareg-proxy.dev-fss-pub.nais.io + - host: testnav-pdl-proxy.dev-fss-pub.nais.io + azure: + application: + allowAllUsers: true + enabled: true + tenant: nav.no + liveness: + path: /internal/isAlive + initialDelay: 4 + periodSeconds: 5 + failureThreshold: 500 + readiness: + path: /internal/isReady + initialDelay: 4 + periodSeconds: 5 + failureThreshold: 500 + prometheus: + enabled: true + path: /internal/metrics + replicas: + min: 1 + max: 1 + resources: + requests: + cpu: 200m + memory: 1024Mi + limits: + memory: 2048Mi + ingresses: + - "https://testnav-levende-arbeidsforhold-ansettelse.intern.dev.nav.no" + gcp: + sqlInstances: + - autoBackupHour: 3 #Lager backup av hele SQL instancen hver dag kl 03:00 + type: POSTGRES_14 + databases: + - name: testnav-levende-arbeidsforhold-db + insights: + enabled: true + recordApplicationTags: true + recordClientAddress: true + tier: db-f1-micro + diskAutoresize: true #Kanskje ikke nødvendig? + #collation: DESC \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/gradle/wrapper/gradle-wrapper.jar b/apps/levende-arbeidsforhold-ansettelse/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..e6441136f3d4ba8a0da8d277868979cfbc8ad796 GIT binary patch literal 43453 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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
NnX)EH+Nua)3Y(c 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 '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/apps/levende-arbeidsforhold-ansettelse/gradlew.bat b/apps/levende-arbeidsforhold-ansettelse/gradlew.bat new file mode 100644 index 00000000000..7101f8e4676 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/apps/levende-arbeidsforhold-ansettelse/gradlewUpdate.sh b/apps/levende-arbeidsforhold-ansettelse/gradlewUpdate.sh new file mode 100755 index 00000000000..e5ee6361152 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/gradlewUpdate.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +gradle wrapper \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/settings.gradle b/apps/levende-arbeidsforhold-ansettelse/settings.gradle new file mode 100644 index 00000000000..e91fac3452f --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/settings.gradle @@ -0,0 +1,19 @@ +plugins { + id "com.gradle.develocity" version "3.17.4" +} + +rootProject.name = 'levende-arbeidsforhold-ansettelse' + +includeBuild '../../libs/security-core' +includeBuild '../../libs/servlet-core' +includeBuild '../../libs/reactive-core' +includeBuild '../../libs/servlet-insecure-security' +includeBuild '../../libs/data-transfer-objects' +includeBuild '../../.github/workflows' + +develocity { + buildScan { + termsOfUseUrl = "https://gradle.com/terms-of-service" + termsOfUseAgree = "yes" + } +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/LevendeArbeidsforholdAnsettelseApplication.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/LevendeArbeidsforholdAnsettelseApplication.java new file mode 100644 index 00000000000..c825eae956e --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/LevendeArbeidsforholdAnsettelseApplication.java @@ -0,0 +1,13 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class LevendeArbeidsforholdAnsettelseApplication { + + public static void main(String[] args) { + SpringApplication.run(LevendeArbeidsforholdAnsettelseApplication.class, args); + } + +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/ApplicationConfig.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/ApplicationConfig.java new file mode 100644 index 00000000000..048db8ea6e8 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/ApplicationConfig.java @@ -0,0 +1,16 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.config; + +import no.nav.testnav.libs.servletcore.config.ApplicationCoreConfig; +import no.nav.testnav.libs.standalone.servletsecurity.config.InsecureJwtServerToServerConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@Import({ + ApplicationCoreConfig.class, + InsecureJwtServerToServerConfiguration.class +}) +public class ApplicationConfig { + +} + diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/Consumers.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/Consumers.java new file mode 100644 index 00000000000..56485834e4d --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/Consumers.java @@ -0,0 +1,33 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.config; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import no.nav.testnav.libs.securitycore.domain.ServerProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import static lombok.AccessLevel.PACKAGE; + +/** + * Samler alle placeholders for ulike {@code consumers.*}-konfigurasjon her, dvs. subklasser av {@code ServerProperties}. + *

+ * Husk at Spring Boot bruker relaxed binding + * mellom configuration properties og field names. + * + * @see ServerProperties + */ +@Configuration +@ConfigurationProperties(prefix = "consumers") +@NoArgsConstructor(access = PACKAGE) +@Getter +@Setter(PACKAGE) +public class Consumers { + + private ServerProperties testnavAaregProxy; + private ServerProperties testnavTenorSearchService; + private ServerProperties testnavEregProxy; + private ServerProperties pdlProxy; + private ServerProperties testnavOrganisasjonFasteDataService; + private ServerProperties testnavKodeverkService; +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/DevConfig.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/DevConfig.java new file mode 100644 index 00000000000..e3ef191048a --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/DevConfig.java @@ -0,0 +1,36 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.vault.annotation.VaultPropertySource; +import org.springframework.vault.authentication.ClientAuthentication; +import org.springframework.vault.authentication.TokenAuthentication; +import org.springframework.vault.client.VaultEndpoint; +import org.springframework.vault.config.AbstractVaultConfiguration; + +import static io.micrometer.common.util.StringUtils.isBlank; + +@Configuration +@Profile("dev") +@VaultPropertySource(value = "secret/dolly/lokal", ignoreSecretNotFound = false) +public class DevConfig extends AbstractVaultConfiguration { + + private static final String VAULT_TOKEN = "spring.cloud.vault.token"; + + @Override + public VaultEndpoint vaultEndpoint() { + return VaultEndpoint.create("vault.adeo.no", 443); + } + + @Override + public ClientAuthentication clientAuthentication() { + if (System.getenv().containsKey("VAULT_TOKEN")) { + System.setProperty(VAULT_TOKEN, System.getenv("VAULT_TOKEN")); + } + var token = System.getProperty(VAULT_TOKEN); + if (isBlank(token)) { + throw new IllegalArgumentException("Påkrevet property 'spring.cloud.vault.token' er ikke satt."); + } + return new TokenAuthentication(System.getProperty(VAULT_TOKEN)); + } +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/OpenApiConfig.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/OpenApiConfig.java new file mode 100644 index 00000000000..8b71c18d28f --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/OpenApiConfig.java @@ -0,0 +1,54 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.config; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Contact; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import no.nav.testnav.libs.servletcore.config.ApplicationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.util.Arrays; + +@Configuration +public class OpenApiConfig implements WebMvcConfigurer { + + @Bean + public OpenAPI openApi(ApplicationProperties applicationProperties) { + return new OpenAPI() + .components(new Components().addSecuritySchemes("bearer-jwt", new SecurityScheme() + .type(SecurityScheme.Type.HTTP) + .scheme("bearer") + .bearerFormat("JWT") + .in(SecurityScheme.In.HEADER) + .name("Authorization") + )) + .addSecurityItem( + new SecurityRequirement().addList("bearer-jwt", Arrays.asList("read", "write"))) + .info(new Info() + .title(applicationProperties.getName()) + .version(applicationProperties.getVersion()) + .description(applicationProperties.getDescription()) + .termsOfService("https://nav.no") + .contact(new Contact() + .url("https://nav-it.slack.com/archives/CA3P9NGA2") + .email("dolly@nav.no") + .name("Team Dolly") + ) + .license(new License() + .name("MIT License") + .url("https://opensource.org/licenses/MIT") + ) + ); + } + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/swagger").setViewName("redirect:/swagger-ui.html"); + } +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/SecurityConfig.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/SecurityConfig.java new file mode 100644 index 00000000000..7b7eed929dc --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/config/SecurityConfig.java @@ -0,0 +1,37 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; + +@EnableWebSecurity +@Configuration +public class SecurityConfig { + + @Bean + @SuppressWarnings("java:S4502") + public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { + + httpSecurity.sessionManagement(sessionConfig -> sessionConfig.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .csrf(AbstractHttpConfigurer::disable) + .authorizeHttpRequests(authorizeConfig -> authorizeConfig.requestMatchers( + "/internal/**", + "/webjars/**", + "/swagger-resources/**", + "/v3/api-docs/**", + "/swagger-ui/**", + "/swagger", + "/error", + "/swagger-ui.html" + ).permitAll().requestMatchers("/api/**").fullyAuthenticated()) + .oauth2ResourceServer(oauth2RSConfig -> oauth2RSConfig.jwt(Customizer.withDefaults())); + + return httpSecurity.build(); + } +} + diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/AaregConsumer.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/AaregConsumer.java new file mode 100644 index 00000000000..59e07a2e291 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/AaregConsumer.java @@ -0,0 +1,56 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers; + +import lombok.extern.slf4j.Slf4j; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.config.Consumers; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.aareg.HentArbeidsforholdCommand; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.aareg.OpprettArbeidsforholdCommand; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Arbeidsforhold; +import no.nav.testnav.libs.securitycore.domain.ServerProperties; +import no.nav.testnav.libs.standalone.servletsecurity.exchange.TokenExchange; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClient; + +import java.util.List; +import java.util.Optional; + +@Slf4j +@Component +public class AaregConsumer { + + private final WebClient webClient; + private final ServerProperties serverProperties; + private final TokenExchange tokenExchange; + + public AaregConsumer( + Consumers consumers, + TokenExchange tokenExchange) { + + this.serverProperties = consumers.getTestnavAaregProxy(); + this.tokenExchange = tokenExchange; + + this.webClient = WebClient + .builder() + .baseUrl(serverProperties.getUrl()) + .build(); + } + + public List hentArbeidsforhold(String ident) { + + return tokenExchange.exchange(serverProperties) + .flatMapMany(token -> new HentArbeidsforholdCommand(webClient, token.getTokenValue(), ident).call()) + .collectList() + .block(); + } + + public Optional opprettArbeidsforhold(Arbeidsforhold requests) { + + return tokenExchange.exchange(serverProperties) + .flatMap(token -> new OpprettArbeidsforholdCommand(webClient, requests, token.getTokenValue()).call()) + .map(resultat -> Optional.of(resultat) + .map(ResponseEntity::getStatusCode)) + .block(); + } +} + diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/JacksonExchangeStrategyUtil.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/JacksonExchangeStrategyUtil.java new file mode 100644 index 00000000000..a06b432461e --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/JacksonExchangeStrategyUtil.java @@ -0,0 +1,25 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.experimental.UtilityClass; +import org.springframework.http.MediaType; +import org.springframework.http.codec.json.Jackson2JsonDecoder; +import org.springframework.http.codec.json.Jackson2JsonEncoder; +import org.springframework.web.reactive.function.client.ExchangeStrategies; + +@UtilityClass +public final class JacksonExchangeStrategyUtil { + + public static ExchangeStrategies getJacksonStrategy(ObjectMapper objectMapper) { + return ExchangeStrategies.builder() + .codecs(config -> { + config.defaultCodecs() + .maxInMemorySize(32 * 1024 * 1024); + config.defaultCodecs() + .jackson2JsonEncoder(new Jackson2JsonEncoder(objectMapper, MediaType.APPLICATION_JSON)); + config.defaultCodecs() + .jackson2JsonDecoder(new Jackson2JsonDecoder(objectMapper, MediaType.APPLICATION_JSON)); + }).build(); + } + +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/KodeverkServiceConsumer.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/KodeverkServiceConsumer.java new file mode 100644 index 00000000000..7a01f63480f --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/KodeverkServiceConsumer.java @@ -0,0 +1,50 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.config.Consumers; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.kodeverk.KodeverkServiceCommand; +import no.nav.testnav.libs.securitycore.domain.ServerProperties; +import no.nav.testnav.libs.standalone.servletsecurity.exchange.TokenExchange; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.ExchangeStrategies; +import org.springframework.web.reactive.function.client.WebClient; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@Slf4j +@Component +public class KodeverkServiceConsumer { + private final WebClient webClient; + private final ServerProperties serverProperties; + private final TokenExchange tokenExchange; + private final ObjectMapper objectMapper; + + public KodeverkServiceConsumer( + Consumers consumers, + TokenExchange tokenExchange) { + + serverProperties = consumers.getTestnavKodeverkService(); + ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder() + .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(16 * 1024 * 1024)) + .build(); + this.webClient = WebClient + .builder() + .baseUrl(serverProperties.getUrl()) + .exchangeStrategies(exchangeStrategies) + .build(); + this.tokenExchange = tokenExchange; + objectMapper = new ObjectMapper(); + } + + public List hentKodeverk(String kodeverk) { + + return tokenExchange.exchange(serverProperties) + .flatMap(token -> new KodeverkServiceCommand(webClient, token.getTokenValue(), kodeverk, objectMapper).call()) + .map(Map::keySet) + .map(ArrayList::new) + .block(); + } +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/PdlConsumer.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/PdlConsumer.java new file mode 100644 index 00000000000..5044b26064a --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/PdlConsumer.java @@ -0,0 +1,74 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers; + +import com.fasterxml.jackson.databind.JsonNode; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.config.Consumers; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.pdl.SokPersonCommand; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.pdl.SokPersonPagesCommand; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl.GraphqlVariables; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.provider.PdlMiljoer; +import no.nav.testnav.libs.securitycore.domain.AccessToken; +import no.nav.testnav.libs.securitycore.domain.ServerProperties; +import no.nav.testnav.libs.standalone.servletsecurity.exchange.TokenExchange; +import org.springframework.core.io.ClassPathResource; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.stream.Collectors; + +import static java.nio.charset.StandardCharsets.UTF_8; + +@Slf4j +@Service +public class PdlConsumer { + + private final TokenExchange tokenService; + private final ServerProperties serverProperties; + private final WebClient webClient; + + public PdlConsumer( + TokenExchange tokenService, + Consumers consumers, + WebClient.Builder webClientBuilder) { + + serverProperties = consumers.getPdlProxy(); + this.tokenService = tokenService; + webClient = webClientBuilder + .baseUrl(serverProperties.getUrl()) + .build(); + } + + public Mono getSokPerson( + GraphqlVariables.Paging paging, + GraphqlVariables.Criteria criteria, + PdlMiljoer pdlMiljoe) { + return tokenService.exchange(serverProperties) + .flatMap((AccessToken token) -> new SokPersonCommand(webClient, paging, criteria, token.getTokenValue(), pdlMiljoe) + .call()); + } + + public Mono getSokPersonPages( + GraphqlVariables.Paging paging, + GraphqlVariables.Criteria criteria, + PdlMiljoer pdlMiljoe) { + return tokenService.exchange(serverProperties) + .flatMap((AccessToken token) -> new SokPersonPagesCommand(webClient, paging, criteria, token.getTokenValue(), pdlMiljoe) + .call()); + } + + public static String hentQueryResource(String pathResource) { + + val resource = new ClassPathResource(pathResource); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream(), UTF_8))) { + return reader.lines().collect(Collectors.joining("\n")); + } catch (IOException e) { + log.error("Lesing av query ressurs {} feilet", pathResource, e); + return null; + } + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/TagsConsumer.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/TagsConsumer.java new file mode 100644 index 00000000000..0f62ad2cc69 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/TagsConsumer.java @@ -0,0 +1,40 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers; + +import lombok.extern.slf4j.Slf4j; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.config.Consumers; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.pdl.HentTagsCommand; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.TagsDTO; +import no.nav.testnav.libs.securitycore.domain.ServerProperties; +import no.nav.testnav.libs.standalone.servletsecurity.exchange.TokenExchange; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; + +import java.util.List; + +@Slf4j +@Service +public class TagsConsumer { + private final TokenExchange tokenService; + private final ServerProperties serverProperties; + private final WebClient webClient; + + public TagsConsumer( + TokenExchange tokenService, + Consumers consumers, + WebClient.Builder webClientBuilder) { + + serverProperties = consumers.getPdlProxy(); + + this.tokenService = tokenService; + webClient = webClientBuilder + .baseUrl(serverProperties.getUrl()) + .build(); + } + + public TagsDTO hentTags(List identer) { + + return tokenService.exchange(serverProperties) + .flatMap(token -> new HentTagsCommand(webClient, token.getTokenValue(), identer).call()) + .block(); + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/TenorConsumer.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/TenorConsumer.java new file mode 100644 index 00000000000..b6c895f8f95 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/TenorConsumer.java @@ -0,0 +1,50 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers; + +import lombok.extern.slf4j.Slf4j; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.config.Consumers; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.tenor.HentOrganisasjonCommand; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.tenor.HentOrganisasjonerOversiktCommand; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor.TenorOrganisasjonRequest; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor.TenorOversiktOrganisasjonResponse; +import no.nav.testnav.libs.securitycore.domain.ServerProperties; +import no.nav.testnav.libs.standalone.servletsecurity.exchange.TokenExchange; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClient; + +@Slf4j +@Component +public class TenorConsumer { + + private final WebClient webClient; + private final TokenExchange tokenExchange; + private final ServerProperties serverProperties; + + + public TenorConsumer( + TokenExchange tokenExchange, + Consumers consumers) { + + this.serverProperties = consumers.getTestnavTenorSearchService(); + this.tokenExchange = tokenExchange; + + this.webClient = WebClient + .builder() + .baseUrl(serverProperties.getUrl()) + .build(); + } + + public TenorOversiktOrganisasjonResponse hentOrganisasjonerOversikt(TenorOrganisasjonRequest tenorOrgRequest, String antallOrganisasjoner) { + + return tokenExchange.exchange(serverProperties) + .flatMap(token -> new HentOrganisasjonerOversiktCommand(webClient, token.getTokenValue(), + tenorOrgRequest, antallOrganisasjoner).call()) + .block(); + } + + public TenorOversiktOrganisasjonResponse hentOrganisasjon(TenorOrganisasjonRequest tenorOrgRequest) { + + return tokenExchange.exchange(serverProperties) + .flatMap(token -> new HentOrganisasjonCommand(webClient, token.getTokenValue(), tenorOrgRequest).call()) + .block(); + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/aareg/HentArbeidsforholdCommand.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/aareg/HentArbeidsforholdCommand.java new file mode 100644 index 00000000000..922a4398f92 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/aareg/HentArbeidsforholdCommand.java @@ -0,0 +1,62 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.aareg; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Arbeidsforhold; +import no.nav.testnav.libs.reactivecore.utils.WebClientFilter; +import no.nav.testnav.libs.servletcore.headers.NavHeaders; +import org.springframework.http.HttpHeaders; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientResponseException; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.util.retry.Retry; + +import java.time.Duration; +import java.util.UUID; +import java.util.concurrent.Callable; + +import static java.lang.String.format; + + +@Slf4j +@RequiredArgsConstructor +public class HentArbeidsforholdCommand implements Callable> { + + private static final String miljoe = "q2"; + private static final String NAV_PERSON_IDENT = "Nav-Personident"; + private static final String CONSUMER = "Dolly"; + + private final WebClient webClient; + private final String token; + private final String ident; + + private static String getNavCallId() { + return format("%s %s", CONSUMER, UUID.randomUUID()); + } + + @Override + public Flux call() { + + return webClient + .get() + .uri(builder -> builder + .path("/{miljoe}/api/v1/arbeidstaker/arbeidsforhold") + .queryParam("arbeidsforholdtype", "forenkletOppgjoersordning", + "frilanserOppdragstakerHonorarPersonerMm", "maritimtArbeidsforhold", + "ordinaertArbeidsforhold") + .build(miljoe)) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + token) + .header(NAV_PERSON_IDENT, ident) + .header(NavHeaders.NAV_CONSUMER_ID, CONSUMER) + .header(NavHeaders.NAV_CALL_ID, getNavCallId()) + .retrieve() + .bodyToFlux(Arbeidsforhold.class) + .retryWhen(Retry + .backoff(3, Duration.ofSeconds(5)) + .filter(WebClientFilter::is5xxException)) + .doOnError(WebClientFilter::logErrorMessage) + .onErrorResume(WebClientResponseException.NotFound.class, error -> Mono.empty()) + .onErrorResume(WebClientResponseException.class, error -> Mono.empty()); + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/aareg/OpprettArbeidsforholdCommand.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/aareg/OpprettArbeidsforholdCommand.java new file mode 100644 index 00000000000..d298c0068db --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/aareg/OpprettArbeidsforholdCommand.java @@ -0,0 +1,43 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.aareg; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Arbeidsforhold; +import no.nav.testnav.libs.reactivecore.utils.WebClientFilter; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; +import reactor.util.retry.Retry; + +import java.time.Duration; +import java.util.concurrent.Callable; +@Slf4j +@RequiredArgsConstructor +public class OpprettArbeidsforholdCommand implements Callable>> { + + private final String navArbeidsforholdKilde = "Dolly-automatisk-ansettelse" ; + private final String miljoe = "q2"; + + private final WebClient webClient; + private final Arbeidsforhold requests; + private final String token; + + @Override + public Mono> call() { + + return webClient.post() + .uri(builder -> builder.path("/{miljoe}/api/v1/arbeidsforhold") + .build(miljoe)) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + token) + .header("Nav-Arbeidsforhold-Kildereferanse", navArbeidsforholdKilde) + .bodyValue(requests) + .retrieve() + .toBodilessEntity() + .retryWhen(Retry.backoff(3, Duration.ofSeconds(5)) + .filter(WebClientFilter::is5xxException)) + .doOnError(WebClientFilter::logErrorMessage); + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/kodeverk/KodeverkServiceCommand.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/kodeverk/KodeverkServiceCommand.java new file mode 100644 index 00000000000..706c5406e3d --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/kodeverk/KodeverkServiceCommand.java @@ -0,0 +1,42 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.kodeverk; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import no.nav.testnav.libs.reactivecore.utils.WebClientFilter; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.util.Map; +import java.util.concurrent.Callable; + +import static java.util.Objects.nonNull; + +@Slf4j +@RequiredArgsConstructor +public class KodeverkServiceCommand implements Callable>> { + + private final WebClient webClient; + private final String token; + private final String kodeverk; ///api/v1/kodeverk/Yrker/koder + private final ObjectMapper mapper; + + @Override + public Mono> call() { + + return webClient.get() + .uri(builder -> builder + .path("/api/v1/kodeverk") + .queryParam("kodeverk", kodeverk) + .build()) + .header("Authorization", "Bearer " + token) + .retrieve() + .bodyToMono(JsonNode.class) + .map(node -> (Map) (nonNull(node) ? + mapper.convertValue(node.get("kodeverk"), new TypeReference<>(){}) : Mono.empty())) + .doOnError(WebClientFilter::logErrorMessage) + .onErrorResume(error -> Mono.empty()); + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/GraphQLRequest.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/GraphQLRequest.java new file mode 100644 index 00000000000..444272140a6 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/GraphQLRequest.java @@ -0,0 +1,9 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.pdl; + +import lombok.Builder; + +import java.util.Map; + +@Builder +public record GraphQLRequest(String query, Map variables) { +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/HentTagsCommand.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/HentTagsCommand.java new file mode 100644 index 00000000000..ac2796ddb9a --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/HentTagsCommand.java @@ -0,0 +1,47 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.pdl; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.TagsDTO; +import no.nav.testnav.libs.reactivecore.utils.WebClientFilter; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; +import reactor.util.retry.Retry; + +import java.time.Duration; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; + +@Slf4j +@RequiredArgsConstructor +public class HentTagsCommand implements Callable> { + private static final String PDL_TAGS_URL = "/api/v1/bestilling/tags/bolk"; + private static final String PDL_TESTDATA = "/pdl-testdata"; + private static final String PERSONIDENTER = "Nav-Personidenter"; + + private final WebClient webClient; + private final String token; + private final List identer; + + @Override + public Mono call() { + + return webClient.get().uri(builder -> builder.path(PDL_TESTDATA) + .path(PDL_TAGS_URL) + .build()) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + token) + .header(PERSONIDENTER, String.join(",", identer)) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .retrieve() + .bodyToMono(Map.class) + .map(resultat -> TagsDTO.builder() + .personerTags(resultat) + .build()) + .retryWhen(Retry.backoff(3, Duration.ofSeconds(5)) + .filter(WebClientFilter::is5xxException)) + .doOnError(WebClientFilter::logErrorMessage); + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/SokPersonCommand.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/SokPersonCommand.java new file mode 100644 index 00000000000..f2a87b7a58f --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/SokPersonCommand.java @@ -0,0 +1,69 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.pdl; + +import com.fasterxml.jackson.databind.JsonNode; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl.GraphqlVariables; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.provider.PdlMiljoer; +import no.nav.testnav.libs.reactivecore.utils.WebClientFilter; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientResponseException; +import reactor.core.publisher.Mono; +import reactor.util.retry.Retry; + +import java.time.Duration; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.Callable; + +import static no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.pdl.TemaGrunnlag.GEN; +import static no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl.CommonKeysAndUtils.DOLLY; +import static no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl.CommonKeysAndUtils.HEADER_NAV_CONSUMER_ID; +import static no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl.PdlHeaders.HEADER_NAV_CALL_ID; +import static no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.PdlConsumer.hentQueryResource; +import static org.springframework.http.HttpHeaders.AUTHORIZATION; + +@Slf4j +@RequiredArgsConstructor +public class SokPersonCommand implements Callable> { + + private static final String TEMA = "Tema"; + private static final String GRAPHQL_URL = "/graphql"; + private static final String PDL_API_URL = "/pdl-api"; + private static final String SOK_PERSON_QUERY = "pdl/sokPerson.graphql"; + + private final WebClient webClient; + private final GraphqlVariables.Paging paging; + private final GraphqlVariables.Criteria criteria; + private final String token; + private final PdlMiljoer pdlMiljoe; + + @Override + public Mono call() { + + return webClient + .post() + .uri(uriBuilder -> uriBuilder + .path(PDL_API_URL) + .path(pdlMiljoe.equals(PdlMiljoer.Q2) ? "" : "-" + pdlMiljoe.name().toLowerCase()) + .path(GRAPHQL_URL) + .build()) + .header(AUTHORIZATION, "Bearer " + token) + .header(HEADER_NAV_CONSUMER_ID, DOLLY) + .header(HEADER_NAV_CALL_ID, "Dolly: " + UUID.randomUUID()) + .header(TEMA, GEN.name()) + .body(BodyInserters + .fromValue(new GraphQLRequest(hentQueryResource(SOK_PERSON_QUERY), + Map.of("paging", paging, "criteria", criteria)))) + .retrieve() + .bodyToMono(JsonNode.class) + .doOnError(WebClientFilter::logErrorMessage) + .retryWhen(Retry.backoff(3, Duration.ofSeconds(5)) + .filter(WebClientFilter::is5xxException)) + .onErrorResume(throwable -> throwable instanceof WebClientResponseException.NotFound, + throwable -> Mono.empty()); + } +} + diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/SokPersonPagesCommand.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/SokPersonPagesCommand.java new file mode 100644 index 00000000000..22a36f44822 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/SokPersonPagesCommand.java @@ -0,0 +1,69 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.pdl; + +import com.fasterxml.jackson.databind.JsonNode; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl.GraphqlVariables; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.provider.PdlMiljoer; +import no.nav.testnav.libs.reactivecore.utils.WebClientFilter; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientResponseException; +import reactor.core.publisher.Mono; +import reactor.util.retry.Retry; + +import java.time.Duration; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.Callable; + +import static no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.pdl.TemaGrunnlag.GEN; +import static no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl.CommonKeysAndUtils.DOLLY; +import static no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl.CommonKeysAndUtils.HEADER_NAV_CONSUMER_ID; +import static no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl.PdlHeaders.HEADER_NAV_CALL_ID; +import static no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.PdlConsumer.hentQueryResource; +import static org.springframework.http.HttpHeaders.AUTHORIZATION; + +@Slf4j +@RequiredArgsConstructor +public class SokPersonPagesCommand implements Callable> { + + private static final String TEMA = "Tema"; + private static final String GRAPHQL_URL = "/graphql"; + private static final String PDL_API_URL = "/pdl-api"; + private static final String SOK_PERSON_QUERY = "pdl/sokPersonPages.graphql"; + + private final WebClient webClient; + private final GraphqlVariables.Paging paging; + private final GraphqlVariables.Criteria criteria; + private final String token; + private final PdlMiljoer pdlMiljoe; + + @Override + public Mono call() { + + return webClient + .post() + .uri(uriBuilder -> uriBuilder + .path(PDL_API_URL) + .path(pdlMiljoe.equals(PdlMiljoer.Q2) ? "" : "-" + pdlMiljoe.name().toLowerCase()) + .path(GRAPHQL_URL) + .build()) + .header(AUTHORIZATION, "Bearer " + token) + .header(HEADER_NAV_CONSUMER_ID, DOLLY) + .header(HEADER_NAV_CALL_ID, "Dolly: " + UUID.randomUUID()) + .header(TEMA, GEN.name()) + .body(BodyInserters + .fromValue(new GraphQLRequest(hentQueryResource(SOK_PERSON_QUERY), + Map.of("paging", paging, "criteria", criteria)))) + .retrieve() + .bodyToMono(JsonNode.class) + .doOnError(WebClientFilter::logErrorMessage) + .retryWhen(Retry.backoff(3, Duration.ofSeconds(5)) + .filter(WebClientFilter::is5xxException)) + .onErrorResume(throwable -> throwable instanceof WebClientResponseException.NotFound, + throwable -> Mono.empty()); + } +} + diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/TemaGrunnlag.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/TemaGrunnlag.java new file mode 100644 index 00000000000..7b301af3976 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/pdl/TemaGrunnlag.java @@ -0,0 +1,6 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.pdl; + +public enum TemaGrunnlag { + + GEN, PEN +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/tenor/HentOrganisasjonCommand.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/tenor/HentOrganisasjonCommand.java new file mode 100644 index 00000000000..9d404f56226 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/tenor/HentOrganisasjonCommand.java @@ -0,0 +1,43 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.tenor; + +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor.TenorOrganisasjonRequest; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor.TenorOversiktOrganisasjonResponse; +import no.nav.testnav.libs.reactivecore.utils.WebClientFilter; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; +import reactor.util.retry.Retry; + +import java.time.Duration; +import java.util.concurrent.Callable; + +@Slf4j +@RequiredArgsConstructor +public class HentOrganisasjonCommand implements Callable> { + private static final String PATH = "/api/v1/tenor/testdata/organisasjoner"; + + private final WebClient webClient; + private final String token; + private final TenorOrganisasjonRequest tenorOrgRequest; + + @SneakyThrows + @Override + public Mono call() { + + return webClient + .post() + .uri(builder -> builder + .path(PATH) + .build() + ) + .header("Authorization", "Bearer " + token) + .body(BodyInserters.fromValue(tenorOrgRequest)) + .retrieve() + .bodyToMono(TenorOversiktOrganisasjonResponse.class) + .retryWhen(Retry.backoff(3, Duration.ofSeconds(5)) + .filter(WebClientFilter::is5xxException)); + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/tenor/HentOrganisasjonerOversiktCommand.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/tenor/HentOrganisasjonerOversiktCommand.java new file mode 100644 index 00000000000..0bad766e847 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/consumers/command/tenor/HentOrganisasjonerOversiktCommand.java @@ -0,0 +1,45 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.command.tenor; + +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor.TenorOrganisasjonRequest; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor.TenorOversiktOrganisasjonResponse; +import no.nav.testnav.libs.reactivecore.utils.WebClientFilter; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; +import reactor.util.retry.Retry; + +import java.time.Duration; +import java.util.concurrent.Callable; + +@Slf4j +@RequiredArgsConstructor +public class HentOrganisasjonerOversiktCommand implements Callable> { + private static final String PATH = "/api/v1/tenor/testdata/organisasjoner/oversikt"; + + private final WebClient webClient; + private final String token; + private final TenorOrganisasjonRequest tenorOrgRequest; + private final String antallOrganisasjoner; + + @SneakyThrows + @Override + public Mono call() { + + return webClient + .post() + .uri(builder -> builder + .path(PATH) + .queryParam("antall", antallOrganisasjoner) + .build() + ) + .header("Authorization", "Bearer " + token) + .body(BodyInserters.fromValue(tenorOrgRequest)) + .retrieve() + .bodyToMono(TenorOversiktOrganisasjonResponse.class) + .retryWhen(Retry.backoff(3, Duration.ofSeconds(5)) + .filter(WebClientFilter::is5xxException)); + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/controller/JobbController.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/controller/JobbController.java new file mode 100644 index 00000000000..8e407a1524c --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/controller/JobbController.java @@ -0,0 +1,76 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.controller; + + +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.entity.JobbParameter; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.service.AnsettelseService; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.service.JobbService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@Slf4j +@RestController +@RequestMapping("/api") +@RequiredArgsConstructor +public class JobbController { + + @Autowired + private final JobbService jobbService; + private final AnsettelseService ansettelseService; + + /** + * Endepunktet som blir benyttet av frontend for å hente alle parameterene og verdiene + * @return returnerer parameterne + */ + @GetMapping + @Operation(description = "Henter alle parametere med verdier") + public ResponseEntity> hentAlleJobber() { + try { + return ResponseEntity.ok(jobbService.hentAlleParametere()); + } + catch (Exception e){ + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); + } + } + + /** + * Endepunktet som testnav-levende-arbeidsforhold-scheduler sender spørring til for å + * starte jobb. + * @return 200 OK hvis ansettelses jobben var vellykket + */ + @GetMapping("/ansettelse-jobb") + @Operation(description = "Starter en ansettelse jobb hvor x antall personer blir ansatt i x antall bedrifter") + public ResponseEntity ansettelseJobb(){ + try { + ansettelseService.runAnsettelseService(); + return ResponseEntity.ok("Kjørte ansettelse-service"); + } catch (Exception e){ + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); + } + } + + /** + * Endepunktet frontenden bruker for å opdatere gjeldende verdi i jobb_parameter db. + * @param parameterNavn navnet på parameteren som skal bli oppdatert + * @param verdi ER den nye verdien som skal bli oppdatert + * @return Enten den nye jobbParameterEntity eller feilmeldingen. + */ + @PutMapping("/oppdatereVerdier/{parameterNavn}") + @Operation(description = "Legg inn nye verdier for en parameter") + public ResponseEntity oppdatereVerdier(@PathVariable("parameterNavn") String parameterNavn, @RequestBody String verdi){ + try { + JobbParameter jobbParameter = jobbService.hentJobbParameter(parameterNavn); + verdi = verdi.replace("\"", ""); + jobbParameter.setVerdi(verdi); + return ResponseEntity.ok(jobbService.updateVerdi(jobbParameter)); + } catch (Exception e){ + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); + } + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/DatoIntervall.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/DatoIntervall.java new file mode 100644 index 00000000000..88c919ad39f --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/DatoIntervall.java @@ -0,0 +1,15 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDate; + +@Builder +@Getter +@Setter +public class DatoIntervall { + private LocalDate tom; + private LocalDate from; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/TagsDTO.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/TagsDTO.java new file mode 100644 index 00000000000..c330c5b4e7a --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/TagsDTO.java @@ -0,0 +1,20 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TagsDTO { + + private Map> personerTags; + private String message; + private String details; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/AdresseDTO.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/AdresseDTO.java new file mode 100644 index 00000000000..d8c91273a52 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/AdresseDTO.java @@ -0,0 +1,28 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NoArgsConstructor; +import lombok.Value; + +@Builder +@Value +@NoArgsConstructor(force = true) +@AllArgsConstructor +public class AdresseDTO { + @JsonProperty + String adresselinje1; + @JsonProperty + String adresselinje2; + @JsonProperty + String adresselinje3; + @JsonProperty + String kommunenummer; + @JsonProperty + String landkode; + @JsonProperty + String postnummer; + @JsonProperty + String poststed; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/DetaljerDTO.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/DetaljerDTO.java new file mode 100644 index 00000000000..9773e5f83f5 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/DetaljerDTO.java @@ -0,0 +1,19 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.dto; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NoArgsConstructor; +import lombok.Value; + +@Value +@NoArgsConstructor(force = true) +@AllArgsConstructor +@Builder +@JsonIgnoreProperties(ignoreUnknown = true) +public class DetaljerDTO { + @JsonProperty + String enhetstype; +} + diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/NavnDTO.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/NavnDTO.java new file mode 100644 index 00000000000..cedd9b678b3 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/NavnDTO.java @@ -0,0 +1,21 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.dto; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NoArgsConstructor; +import lombok.Value; + +@Value +@Builder +@NoArgsConstructor(force = true) +@AllArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class NavnDTO { + + @JsonProperty + String redigertnavn; + @JsonProperty + String navnelinje1; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/OrganisasjonDTO.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/OrganisasjonDTO.java new file mode 100644 index 00000000000..0abaf24400b --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/OrganisasjonDTO.java @@ -0,0 +1,37 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.dto; + +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.*; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@Value +@Builder +@NoArgsConstructor(force = true) +@AllArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +@ToString +public class OrganisasjonDTO { + @JsonProperty(required = true) + String organisasjonsnummer; + @JsonProperty(required = true) + @JsonAlias({"virksomhetDetaljer", "juridiskEnhetDetaljer", "organisasjonsleddDetaljer"}) + DetaljerDTO detaljer; + @JsonProperty(required = true) + NavnDTO navn; + @JsonProperty(required = true) + String type; + @JsonProperty + @JsonAlias({"inngaarIJuridiskEnheter"}) + List parents = new ArrayList<>(); + @JsonProperty + OrganisasjonDetaljerDTO organisasjonDetaljer; + @JsonProperty + @JsonAlias({"driverVirksomheter"}) + List children = new ArrayList<>(); +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/OrganisasjonDetaljerDTO.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/OrganisasjonDetaljerDTO.java new file mode 100644 index 00000000000..bd8a488572d --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/dto/OrganisasjonDetaljerDTO.java @@ -0,0 +1,22 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.dto; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NoArgsConstructor; +import lombok.Value; + +import java.util.List; + +@Value +@NoArgsConstructor(force = true) +@AllArgsConstructor +@Builder +@JsonIgnoreProperties(ignoreUnknown = true) +public class OrganisasjonDetaljerDTO { + @JsonProperty + List forretningsadresser; + @JsonProperty + List postadresser; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/kodeverk/KodeverkBetydningerResponse.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/kodeverk/KodeverkBetydningerResponse.java new file mode 100644 index 00000000000..c629756f0b0 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/kodeverk/KodeverkBetydningerResponse.java @@ -0,0 +1,58 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.kodeverk; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static java.util.Objects.isNull; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class KodeverkBetydningerResponse { + + private Map> betydninger; + + public Map> getBetydninger() { + + if (isNull(betydninger)) { + betydninger = new HashMap<>(); + } + return this.betydninger; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Betydning { + + private LocalDate gyldigFra; + private LocalDate gyldigTil; + private Map beskrivelser; + + public Map getBeskrivelser() { + if (isNull(beskrivelser)) { + beskrivelser = new HashMap<>(); + } + return beskrivelser; + } + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Beskrivelse { + + private String term; + private String tekst; + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/kodeverk/KodeverkNavn.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/kodeverk/KodeverkNavn.java new file mode 100644 index 00000000000..59ab6367878 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/kodeverk/KodeverkNavn.java @@ -0,0 +1,23 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.kodeverk; + +public enum KodeverkNavn { + YRKER ("Yrker"), + ARBEIDSTIDSORDNINGER ("Arbeidstidsordninger"), + AVLOENNINGSTYPER ("Avlønningstyper"), + PERMISJONOGPERMITTERINGSBESKRIVELSE ("PermisjonsOgPermitteringsBeskrivelse"), + SLUUAARSAKAAREG ("SluttårsakAareg"), + ANSETTELSESFORMAAREG ("AnsettelsesformAareg"), + SKIPSREGISTRE ("Skipsregistre"), + SKIPSTYPER ("Skipstyper"), + FARTSOMRAADER ("Fartsområder"), + VALUTAER ("Valutaer"); + + public final String value; + + KodeverkNavn(String value) { + this.value = value; + } + String getValue() { + return value; + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/kodeverk/KodeverkResponse.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/kodeverk/KodeverkResponse.java new file mode 100644 index 00000000000..1a0bc967feb --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/kodeverk/KodeverkResponse.java @@ -0,0 +1,15 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.kodeverk; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class KodeverkResponse { + public String kode; + public String yrke; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/organisasjon/Adresse.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/organisasjon/Adresse.java new file mode 100644 index 00000000000..db34fe0201a --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/organisasjon/Adresse.java @@ -0,0 +1,36 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.organisasjon; + +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.dto.AdresseDTO; + +public class Adresse { + private final String kommunenummer; + private final String adresselinje1; + private final String adresselinje2; + private final String adresselinje3; + private final String landkode; + private final String postnummer; + private final String poststed; + + public Adresse(AdresseDTO dto) { + this.kommunenummer = dto.getKommunenummer(); + this.adresselinje1 = dto.getAdresselinje1(); + this.adresselinje2 = dto.getAdresselinje2(); + this.adresselinje3 = dto.getAdresselinje3(); + this.landkode = dto.getLandkode(); + this.postnummer = dto.getPostnummer(); + this.poststed = dto.getPoststed(); + } + + public no.nav.testnav.libs.dto.organisasjon.v1.AdresseDTO toDTO() { + return no.nav.testnav.libs.dto.organisasjon.v1.AdresseDTO.builder() + .kommunenummer(kommunenummer) + .adresselinje1(adresselinje1) + .adresselinje2(adresselinje2) + .adresselinje3(adresselinje3) + .landkode(landkode) + .postnummer(postnummer) + .poststed(poststed) + .build(); + } + +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/organisasjon/Organisasjon.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/organisasjon/Organisasjon.java new file mode 100644 index 00000000000..ea7762f7658 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/organisasjon/Organisasjon.java @@ -0,0 +1,58 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.organisasjon; + +import lombok.Value; +import lombok.extern.slf4j.Slf4j; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.dto.OrganisasjonDTO; + + +import java.util.Collections; +import java.util.List; + + +@Slf4j +@Value +public class Organisasjon { + String orgnummer; + String enhetType; + String navn; + String juridiskEnhet; + Adresse postadresse; + Adresse forretningsadresser; + String redigertnavn; + List driverVirksomheter; + + public Organisasjon(OrganisasjonDTO dto) { + + navn = dto.getNavn().getNavnelinje1(); + orgnummer = dto.getOrganisasjonsnummer(); + juridiskEnhet = dto.getParents().isEmpty() ? null : dto.getParents().get(0).getOrganisasjonsnummer(); + redigertnavn = dto.getNavn().getRedigertnavn(); + enhetType = dto.getDetaljer().getEnhetstype(); + + driverVirksomheter = dto.getChildren() != null + ? dto.getChildren().stream().map(OrganisasjonDTO::getOrganisasjonsnummer).toList() + : Collections.emptyList(); + + if (dto.getOrganisasjonDetaljer() != null) { + var postadresser = dto.getOrganisasjonDetaljer().getPostadresser(); + if (postadresser != null && !postadresser.isEmpty()) { + this.postadresse = new Adresse(postadresser.get(0)); + } else { + this.postadresse = null; + } + var forretningsadresser = dto.getOrganisasjonDetaljer().getForretningsadresser(); + if (forretningsadresser != null && !forretningsadresser.isEmpty()) { + this.forretningsadresser = new Adresse(forretningsadresser.get(0)); + } else { + this.forretningsadresser = null; + } + } else { + this.postadresse = null; + this.forretningsadresser = null; + } + } + + public no.nav.testnav.libs.dto.organisasjon.v1.OrganisasjonDTO toDTO() { + return no.nav.testnav.libs.dto.organisasjon.v1.OrganisasjonDTO.builder().navn(navn).enhetType(enhetType).orgnummer(orgnummer).juridiskEnhet(juridiskEnhet).postadresse(postadresse != null ? postadresse.toDTO() : null).forretningsadresser(forretningsadresser != null ? forretningsadresser.toDTO() : null).redigertnavn(redigertnavn).driverVirksomheter(driverVirksomheter).build(); + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Bostedsadresse.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Bostedsadresse.java new file mode 100644 index 00000000000..3a7b1ab189e --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Bostedsadresse.java @@ -0,0 +1,14 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.Value; + +@EqualsAndHashCode(callSuper = true) +@Value +@AllArgsConstructor +@NoArgsConstructor(force = true) +public class Bostedsadresse extends MetadataDTO { + Vegadresse vegadresse; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/CommonKeysAndUtils.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/CommonKeysAndUtils.java new file mode 100644 index 00000000000..76d0307fc74 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/CommonKeysAndUtils.java @@ -0,0 +1,10 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.experimental.UtilityClass; + +@UtilityClass +public final class CommonKeysAndUtils { + + public static final String HEADER_NAV_CONSUMER_ID = "Nav-Consumer-Id"; + public static final String DOLLY = "Dolly"; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Data.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Data.java new file mode 100644 index 00000000000..59f6a79493d --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Data.java @@ -0,0 +1,12 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.Value; + +@Value +@AllArgsConstructor +@NoArgsConstructor(force = true) +public class Data { + HentPerson hentPerson; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Feilmelding.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Feilmelding.java new file mode 100644 index 00000000000..1be51529389 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Feilmelding.java @@ -0,0 +1,12 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.Value; + +@Value +@AllArgsConstructor +@NoArgsConstructor(force = true) +public class Feilmelding { + String message; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Foedsel.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Foedsel.java new file mode 100644 index 00000000000..799046824c1 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Foedsel.java @@ -0,0 +1,17 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.Value; + +import java.time.LocalDate; + +@EqualsAndHashCode(callSuper = true) +@Value +@AllArgsConstructor +@NoArgsConstructor(force = true) +public class Foedsel extends MetadataDTO { + + LocalDate foedselsdato; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Folkeregisteridentifikator.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Folkeregisteridentifikator.java new file mode 100644 index 00000000000..eaafd4da6d8 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Folkeregisteridentifikator.java @@ -0,0 +1,16 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.Value; + +@EqualsAndHashCode(callSuper = true) +@Value +@AllArgsConstructor +@NoArgsConstructor(force = true) +public class Folkeregisteridentifikator extends MetadataDTO { + String identifikasjonsnummer; + String status; + String type; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Folkeregisterpersonstatus.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Folkeregisterpersonstatus.java new file mode 100644 index 00000000000..2dd0c78bad0 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Folkeregisterpersonstatus.java @@ -0,0 +1,16 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.Value; + +@EqualsAndHashCode(callSuper = true) +@Value +@AllArgsConstructor +@NoArgsConstructor(force = true) +public class Folkeregisterpersonstatus extends MetadataDTO { + String identifikasjonsnummer; + String status; + String type; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/GraphqlVariables.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/GraphqlVariables.java new file mode 100644 index 00000000000..6cf84fdc4b8 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/GraphqlVariables.java @@ -0,0 +1,53 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.*; + +import java.util.List; +import java.util.Map; + +@Builder +@Getter +@Setter +@NoArgsConstructor +public class GraphqlVariables { + + @Builder + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class Filter { + private String fieldName; + private Map searchRule; + + } + + @Builder + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class Paging{ + private int pageNumber; + private int resultsPerPage; + } + + @Builder + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class Criteria{ + private List and; + } + + @Builder + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class Root{ + private Paging paging; + private Criteria criteria; + } +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/HentPerson.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/HentPerson.java new file mode 100644 index 00000000000..5d2f217fc57 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/HentPerson.java @@ -0,0 +1,61 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Objects.isNull; + +@Data +@AllArgsConstructor +@NoArgsConstructor(force = true) +public class HentPerson { + List navn; + List foedsel; + List bostedsadresse; + List folkeregisteridentifikator; + List folkeregisterpersonstatus; + + public List getNavn() { + + if (isNull(navn)) { + navn = new ArrayList<>(); + } + return navn; + } + + public List getFoedsel() { + + if (isNull(foedsel)) { + foedsel = new ArrayList<>(); + } + return foedsel; + } + + public List getBostedsadresse() { + + if (isNull(bostedsadresse)) { + bostedsadresse = new ArrayList<>(); + } + return bostedsadresse; + } + + public List getFolkeregisteridentifikator() { + + if (isNull(folkeregisteridentifikator)) { + folkeregisteridentifikator = new ArrayList<>(); + } + return folkeregisteridentifikator; + } + + public List getFolkeregisterpersonstatus() { + + if (isNull(folkeregisterpersonstatus)) { + folkeregisterpersonstatus = new ArrayList<>(); + } + return folkeregisterpersonstatus; + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Ident.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Ident.java new file mode 100644 index 00000000000..6885ed773b9 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Ident.java @@ -0,0 +1,20 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.*; + +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class Ident { + private String ident; + private String gruppe; + + @Override + public String toString() { + return "Ident{" + + "ident='" + ident + '\'' + + ", gruppe='" + gruppe + '\'' + + '}'; + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/MetadataDTO.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/MetadataDTO.java new file mode 100644 index 00000000000..f824b01bcf3 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/MetadataDTO.java @@ -0,0 +1,21 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor(force = true) +public class MetadataDTO { + + Metadata metadata; + + @Data + @AllArgsConstructor + @NoArgsConstructor(force = true) + public static class Metadata { + + String opplysningsId; + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Navn.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Navn.java new file mode 100644 index 00000000000..1b45bb68e75 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Navn.java @@ -0,0 +1,16 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.Value; + +@EqualsAndHashCode(callSuper = true) +@Value +@AllArgsConstructor +@NoArgsConstructor(force = true) +public class Navn extends MetadataDTO { + String fornavn; + String mellomnavn; + String etternavn; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/PdlAktoer.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/PdlAktoer.java new file mode 100644 index 00000000000..c56cca23d2f --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/PdlAktoer.java @@ -0,0 +1,57 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.Value; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static java.util.Objects.isNull; + +@Value +@AllArgsConstructor +@NoArgsConstructor(force = true) +public class PdlAktoer { + List errors; + Data data; + + @Value + @AllArgsConstructor + @NoArgsConstructor(force = true) + public static class Data { + HentIdenter hentIdenter; + HentPerson hentPerson; + } + + @lombok.Data + @AllArgsConstructor + @NoArgsConstructor(force = true) + public static class HentIdenter { + List identer; + + public List getIdenter() { + if (isNull(identer)) { + identer = new ArrayList<>(); + } + return identer; + } + } + + @Value + @ToString + @AllArgsConstructor + @NoArgsConstructor(force = true) + public static class AktoerIdent { + String ident; + Boolean historisk; + String gruppe; + } + + + public List getErrors() { + return errors == null ? Collections.emptyList() : errors; + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/PdlHeaders.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/PdlHeaders.java new file mode 100644 index 00000000000..8fec12459d0 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/PdlHeaders.java @@ -0,0 +1,11 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +public class PdlHeaders { + private PdlHeaders() { + } + public static final String NAV_PERSONIDENT = "Nav-Personident"; + public static final String HEADER_NAV_CALL_ID = "Nav-Call-Id"; + public static final String HEADER_NAV_CONSUMER_TOKEN = "Nav-Consumer-Token"; + public static final String TEMA = "Tema"; + public static final String KILDE = "kilde"; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/PdlPerson.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/PdlPerson.java new file mode 100644 index 00000000000..c932235a401 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/PdlPerson.java @@ -0,0 +1,20 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.Value; + +import java.util.Collections; +import java.util.List; + +@Value +@AllArgsConstructor +@NoArgsConstructor(force = true) +public class PdlPerson { + List errors; + Data data; + + public List getErrors() { + return errors == null ? Collections.emptyList() : errors; + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Request.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Request.java new file mode 100644 index 00000000000..a6e12c0ba99 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Request.java @@ -0,0 +1,17 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NoArgsConstructor; +import lombok.Value; + +import java.util.Map; + +@Value +@Builder +@AllArgsConstructor +@NoArgsConstructor(force = true) +public class Request { + private String query; + private Map variables; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/SokPersonVariables.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/SokPersonVariables.java new file mode 100644 index 00000000000..a352795f266 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/SokPersonVariables.java @@ -0,0 +1,60 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.*; + +import java.util.List; +import java.util.Map; + +@Builder +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class SokPersonVariables { + + private int pageNumber; + private int resultsPerPage; + private String from; + private String to; + private String postnr; + private final String identRegex = "\\w+[0-9]{2}[8-9]{1}[0-9]{5}\\w+"; + + public GraphqlVariables.Criteria lagSokPersonCriteria() { + + Map searchRuleFoedselsdato = new java.util.HashMap<>(); + searchRuleFoedselsdato.put("from", from); + searchRuleFoedselsdato.put("to", to ); + + GraphqlVariables.Filter filterBostedPostnr = GraphqlVariables.Filter.builder() + .fieldName("person.bostedsadresse.vegadresse.postnummer") + .searchRule(Map.of("wildcard", postnr)) + .build(); + + GraphqlVariables.Filter filterOppholdPostnr = GraphqlVariables.Filter.builder() + .fieldName("person.oppholdsadresse.vegadresse.postnummer") + .searchRule(Map.of("wildcard", postnr)) + .build(); + + GraphqlVariables.Filter filterFoedselsdato = GraphqlVariables.Filter.builder() + .fieldName("person.foedselsdato.foedselsdato") + .searchRule(searchRuleFoedselsdato) + .build(); + + GraphqlVariables.Filter filterIdent = GraphqlVariables.Filter.builder() + .fieldName("identer.ident") + .searchRule(Map.of("regex", identRegex)) + .build(); + + Map> or = Map.of("or", List.of(filterBostedPostnr, filterOppholdPostnr)); + List and = List.of(or, filterFoedselsdato, filterIdent); + + return GraphqlVariables.Criteria.builder().and(and).build(); + } + + public GraphqlVariables.Paging lagSokPersonPaging() { + return GraphqlVariables.Paging.builder() + .pageNumber(pageNumber) + .resultsPerPage(resultsPerPage) + .build(); + } +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Vegadresse.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Vegadresse.java new file mode 100644 index 00000000000..95e6db6f65f --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/pdl/Vegadresse.java @@ -0,0 +1,15 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl; + +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.Value; + +@Value +@AllArgsConstructor +@NoArgsConstructor(force = true) +public class Vegadresse { + String adressenavn; + String husnummer; + String postnummer; + String kommunenummer; +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/Hendelse.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/Hendelse.java new file mode 100644 index 00000000000..992739342fa --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/Hendelse.java @@ -0,0 +1,50 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor; + +@SuppressWarnings("java:S115") +public enum Hendelse { + + EndringIAdressebeskyttelse, + EndringIBostedsadresse, + EndringIBostedsadresseUtenFlytting, + EndringIBrukAvSamiskSpraak, + EndringIDeltBosted, + EndringIDoedsfall, + EndringIFalskIdentitet, + EndringIFamilierelasjon, + EndringIFoedsel, + EndringIFoedselINorge, + EndringIForeldreansvar, + EndringIFratattRettsligHandleevne, + EndringIIdentifikasjonsnummer, + EndringIIdentitetsgrunnlag, + EndringIInnflytting, + EndringIKjoenn, + EndringIKontaktinformasjon, + EndringIKontaktopplysningerForDoedsbo, + EndringILegitimasjonsdokument, + EndringINavn, + EndringIOpphold, + EndringIOppholdPaaSvalbard, + EndringIOppholdsadresse, + EndringIPerson, + EndringIRettsligHandleevne, + EndringISametingetsValgmanntall, + EndringISivilstand, + EndringIStatsborgerskap, + EndringIStatus, + EndringIUtenlandskPersonidentifikasjon, + EndringIUtflytting, + EndringIUtlendingsmyndighetenesIdentifikasjonsnummer, + EndringIVergemaal, + PersonErBosatt, + PersonErDoed, + PersonErEndretVedSplitting, + PersonErGjenopprettetVedSplitting, + PersonErOppdatert, + PersonErOpphoert, + PersonErOpphoertSomDublett, + PersonErOpprettet, + PersonErReaktivert, + PersonErUtflyttet, + PersonErViderefoertSomGjeldendeVedSammenslaaing +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/LabelEnum.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/LabelEnum.java new file mode 100644 index 00000000000..29d4cdf9d44 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/LabelEnum.java @@ -0,0 +1,6 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor; + +public interface LabelEnum { + String getName(); + String getLabel(); +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/Spesifiseringstype.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/Spesifiseringstype.java new file mode 100644 index 00000000000..a7412575662 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/Spesifiseringstype.java @@ -0,0 +1,35 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor; + +@SuppressWarnings("java:S115") +public enum Spesifiseringstype { + + AksjeIkkeIAksjonaerregisteret, + Aksjesparekonto, + AndreBeloepKnyttetTilBoligOgEiendeler, + AnnenKapitalkostnad, + AnnetFinansprodukt, + DeltakersAndelAvFormueOgInntekt, + Eiendom, + Fondskonto, + Fordring, + FritidsbaatMedSalgsverdiOverSalgsverdigrense, + Generisk, + GrunnlagKnyttetTilLottaker, + KapitalisertFesteavgift, + Kjoeretoey, + KollektivPensjonsordning, + Konto, + Livsforsikring, + LoennOgTilsvarendeYtelser, + Naeringsopplysninger, + ObligasjonOgSertifikat, + OekonomiskeForholdKnyttetTilBoligsameieEllerBoligselskap, + PrivatGjeldsforholdUtenforVirksomhet, + SamletGjeldOgFormuesobjekterINaering, + Skadeforsikring, + SkyldigRestskatt, + SykepengerOgAnnenInntektMvFraOppgavegiver, + Verdipapirfond, + VirtuellEiendel, + VirtuellValuta +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TekniskNavn.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TekniskNavn.java new file mode 100644 index 00000000000..1453a4c5535 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TekniskNavn.java @@ -0,0 +1,430 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor; + +@SuppressWarnings("java:S115") +public enum TekniskNavn { + AaretsFremfoerbareNegativPersoninntekt, + AarsavgiftForKontoIVerdipapirregister, + AlderspensjonFraFolketrygden, + AlderspensjonFraIPAOgIPS, + AlminneligInntektFoerSaerfradrag, + AndelAvFellesgjeldISDF, + AndelAvUnderskuddFraTidligereAarVedDriftAvVaaningshusSomAnvendesIAaret, + AndelIFellesTapVedSalgAvAndelISDF, + AndelIFellesTilleggIAlminneligInntektFraSDF, + AndelIFellesTilleggIAlminneligInntektFraSDFInnenAnnenNaering, + AndelIFellesTilleggIAlminneligInntektFraSDFInnenBarnepassIBarnepasserensHjem, + AndreFradragsberettigedeKostnader, + AnnenArbeidsinntekt, + AnnenGjeld, + AnnenPensjonFoerAlderspensjon, + AnnenSkattepliktigKapitalinntektFraAnnetFinansprodukt, + AnnenSkattepliktigKapitalinntektFraVirtuellValuta, + AnnetInntektsfradrag, + Arbeidsavklaringspenger, + ArbeidsinntektFraKompensasjonsytelseUtbetaltAvNav, + AvkortetFordelVedElektroniskKommunikasjon, + BarnepensjonFraAndreEnnFolketrygden, + BarnepensjonFraFolketrygden, + BarnepensjonFraIPAOgIPS, + BetaltPremieTilSykeOgUlykkesforsikringForNaeringsdrivende, + BetaltUnderholdsbidrag, + BetalteForsinkelsesrenter, + Bruttoformue, + DagpengerForFisker, + DagpengerForNaeringsdrivende, + DagpengerForNaeringsdrivendeOgFisker, + DagpengerVedSykehusoppholdMvFraBarneforsikring, + EktefelletilleggTilPensjon, + EktefelletilleggTilUfoeretrygd, + EngangsutbetalingFraIPSIPA, + EtterlattepensjonFraFolketrygden, + Foederaad, + FormuesverdiAvPrivatUtestaaendeFordring, + FormuesverdiAvUtestaaendeFordring, + FormuesverdiForAndelIRentedelIVerdipapirfond, + FormuesverdiForAnnenFastEiendom, + FormuesverdiForAnnenFastEiendomInnenforInntektsgivendeAktivitet, + FormuesverdiForAnnenFastEiendomUtenforInntektsgivendeAktivitet, + FormuesverdiForAnnetFinansprodukt, + FormuesverdiForBorett, + FormuesverdiForBuskap, + FormuesverdiForEgenFritaksbehandletBolig, + FormuesverdiForFormuesobjekterINaeringIkkeOmfattetAvVerdsettingsrabatt, + FormuesverdiForFritidsbaatMedSalgsverdiOverSalgsverdigrense, + FormuesverdiForGaardsbruk, + FormuesverdiForInnboLoesoereOgFritidsbaatUnderSalgsverdigrense, + FormuesverdiForKjoeretoey, + FormuesverdiForKontanterIAksjesparekonto, + FormuesverdiForKontanterMvIFondskonto, + FormuesverdiForNaeringseiendom, + FormuesverdiForObligasjon, + FormuesverdiForObligasjonerOpsjonerMvIkkeRegistrertIVerdipapirsentralen, + FormuesverdiForObligasjonerOpsjonerMvRegistrertIVerdipapirsentralen, + FormuesverdiForPrimaerbolig, + FormuesverdiForRegnskapsbehandletBolig, + FormuesverdiForRegnskapsbehandletFritidseiendom, + FormuesverdiForSekundaerbolig, + FormuesverdiForSkogeiendom, + FormuesverdiForTomt, + FormuesverdiForUbetingetOpsjonIArbeidsforhold, + FormuesverdiForUtestaaendeFordringerINaering, + FormuesverdiForUtleidFlerboligbygning, + FormuesverdiForVarelager, + FormuesverdiForVirtuellValuta, + Fortsettelsesforsikring, + ForvaltningskostnadKnyttetTilAksjesparekonto, + ForvaltningskostnadKnyttetTilFondskonto, + ForvaltningskostnadKnyttetTilVerdipapirfond, + ForvaltningskostnaderFinans, + FradragForFagforeningskontingent, + FradragForGaverTilFrivilligeOrganisasjoner, + FradragForIndividuellSparingTilPensjon, + FradragForKostnaderKnyttetTilArbeid, + FradragForMerkostnadVedArbeidsoppholdUtenforHjemmet, + FradragForPengetilskudd, + FradragForVergegodtgjoerelse, + FradragsberettigedeFoederaadsytelserOgUnderholdsbidragTilAnnenPerson, + FradragsberettigetTapPaaKapitalforsikringsavtale, + FradragsberettigetTapVedRealisasjonAvFastEiendom, + FradragsberettigetTapVedRealisasjonAvFastEiendomIUtlandet, + FremfoerbartUnderskuddIEnkeltpersonforetak, + GevinstOgAnnenInntektFraVirtuellEiendel, + GevinstValutalaan, + GevinstVedRealisasjonAvAksje, + GevinstVedRealisasjonAvAksjeOgVerdipapirfondAksjedel, + GevinstVedRealisasjonAvAksjesparekonto, + GevinstVedRealisasjonAvAndelIAksjedelIVerdipapirfond, + GevinstVedRealisasjonAvAndelIRentedelIVerdipapirfond, + GevinstVedRealisasjonAvAnnetFinansprodukt, + GevinstVedRealisasjonAvFastEiendomMv, + GevinstVedRealisasjonAvFastEiendomMvIUtlandet, + GevinstVedRealisasjonAvObligasjonVerdipapirfondRentedelMv, + GevinstVedRealisasjonAvObligasjonerSertifikaterMv, + GevinstVedRealisasjonAvOgUttakFraAksjedelIFondskonto, + GevinstVedRealisasjonAvOgUttakFraRentedelIFondskonto, + GevinstVedRealisasjonAvVerdipapirfondsandelIKombifondKnyttetTilAksjedel, + GevinstVedRealisasjonAvVerdipapirfondsandelKnyttetTilAksjedel, + GevinstVedRealisasjonAvVirtuellValuta, + GevinstVedSalgAvAndelINOKUS, + GevinstVedSalgAvAndelISDF, + GjeldIInnenlandskeBanker, + GjeldINaering, + GjeldIUtlandet, + GjeldPaaAnnetFinansprodukt, + GjeldsfradragForKapitalisertFesteavgift, + GjeldsreduksjonForFastEiendomIUtlandetUnntattBeskatningINorgeEtterSkatteavtale, + GjeldsreduksjonForFastEiendomUtenforSvalbardUnntattBeskatningPaaSvalbard, + GjeldsrentereduksjonForFormueIUtlandetUnntattBeskatningINorgeEtterSkatteavtale, + GjeldsrentereduksjonForFormueUtenforSvalbardUnntattBeskatningPaaSvalbard, + GjenkjoepsverdiForLivsforsikring, + GrunnlagForKildeskattPaaPensjonOgUfoereytelser, + GrunnlagForSkattPaaAlminneligInntektSvalbard, + GrunnlagForSkattPaaNaeringsoverskuddSvalbard, + Innskudd, + InnskuddIUtlandet, + InntektFraGevinstOgTapskonto, + InntektFraLottEllerPartTilFiskerOgFangstmann, + InntektVedUtleieAvFritidseiendomSomSkattepliktigeHarBrukt, + InntektsfoeringAvNegativSaldo, + InntektsfradragAvRentefordelPaaLaanIArbeidsforhold, + InntektsfradragAvRentefordelPaaLaanIPensjonsforhold, + InntektsfradragFraGevinstOgTapskonto, + InntektsreduksjonVedAvkastningAvEngangserstatning, + Introduksjonsstoenad, + InvesteringIOppstartsselskap, + KaarytelseUtenforJordOgSkogbruksvirksomhet, + KapitalinntektFraSkogbruk, + KapitalkostnadFraSkogbruk, + KompensasjonsytelseUtbetaltAvNavInnenFiskeOgFangst, + Kontantbeloep, + Kvalifiseringsstoenad, + LatentEllerRealisertGevinstPaaAksjeAndelMvVedUtflytting, + LatentEllerRealisertGevinstPaaAnnetFinansproduktMvVedUtflytting, + LatentEllerRealisertTapPaaAksjeAndelMvVedUtflytting, + LatentEllerRealisertTapPaaAnnetFinansproduktMvVedUtflytting, + LivrenterIArbeidsforhold, + LivrenterUtenforArbeidsforhold, + LoennsinntektMedTrygdeavgiftspliktOmfattetAvLoennstrekkordningen, + LoennsinntektPaaSvalbardOver12G, + LoennsinntektTilBarn, + LoennsinntektUtenTrygdeavgiftspliktOgMedTrekkplikt, + LoennsinntektUtenTrygdeavgiftspliktOmfattetAvLoennstrekkordningen, + MinstefradragIBarnepensjon, + MinstefradragIBarnepensjonTilBarn, + MinstefradragIEktefelletillegg, + MinstefradragIInntekt, + MinstefradragIInntektTilBarn, + MottattFesteavgift, + NaeringsinntektFraKompensasjonsytelseUtbetaltAvNavInnenAnnenNaering, + NaeringsinntektFraKompensasjonsytelseUtbetaltAvNavInnenBarnepassIBarnepasserensHjem, + NaeringsinntektFraKompensasjonsytelseUtbetaltAvNavInnenFiskeOgFangst, + NegativAlminneligInntektOverfoertFraEktefelle, + NegativAlminneligInntektOverfoertTilEktefelle, + NegativFormueOverfoertFraEktefelle, + NettoLoennsinntektFraArbeidINorge, + Nettoformue, + NettoinntektVedUtleieAvFastEiendomMv, + OevrigInntekt, + OppjustertTilleggTilAndelIFellesTapVedSalgAvAndelISDF, + OppjustertTilleggTilAndelIFellesTilleggIAlminneligInntektFraSDF, + OppjustertTilleggTilAndelIFellesTilleggIAlminneligInntektFraSDFInnenAnnenNaering, + OppjustertTilleggTilAndelIFellesTilleggIAlminneligInntektFraSDFInnenBarnepassIBarnepasserensHjem, + OppjustertTilleggTilGevinstVedRealisasjonAvAksje, + OppjustertTilleggTilGevinstVedRealisasjonAvAksjeOgVerdipapirfondAksjedel, + OppjustertTilleggTilGevinstVedRealisasjonAvAksjesparekonto, + OppjustertTilleggTilGevinstVedRealisasjonAvAndelIAksjedelIVerdipapirfond, + OppjustertTilleggTilGevinstVedRealisasjonAvOgUttakFraAksjedelIFondskonto, + OppjustertTilleggTilGevinstVedRealisasjonAvVerdipapirfondsandelIKombifondKnyttetTilAksjedel, + OppjustertTilleggTilGevinstVedRealisasjonAvVerdipapirfondsandelKnyttetTilAksjedel, + OppjustertTilleggTilGevinstVedSalgAvAndelINOKUS, + OppjustertTilleggTilGevinstVedSalgAvAndelISDF, + OppjustertTilleggTilLatentEllerRealisertGevinstPaaAksjeAndelMvVedUtflytting, + OppjustertTilleggTilLatentEllerRealisertTapPaaAksjeAndelMvVedUtflytting, + OppjustertTilleggTilRenteinntektMedEkstrabeskatningForLaanTilSelskap, + OppjustertTilleggTilSkattepliktigAksjegevinst, + OppjustertTilleggTilSkattepliktigUtbytteFraAksjeINOKUSIkkeRegistrertIVerdipapirsentralen, + OppjustertTilleggTilSkattepliktigUtbytteFraAksjeIkkeRegistrertIVerdipapirsentralen, + OppjustertTilleggTilSkattepliktigUtbytteFraAksjeOgVerdipapirfondAksjedel, + OppjustertTilleggTilSkattepliktigUtbytteFraAksjerRegistrertIVerdipapirsentralen, + OppjustertTilleggTilSkattepliktigUtbytteFraVerdipapirfondsandel, + OppjustertTilleggTilSkattepliktigUtbytteFraVerdipapirfondsandelTilBarn, + OppjustertTilleggTilTapVedRealisajonAvOgUttakFraAksjedelIFondskonto, + OppjustertTilleggTilTapVedRealisasjonAvAksje, + OppjustertTilleggTilTapVedRealisasjonAvAksjeOgVerdipapirfondAksjedel, + OppjustertTilleggTilTapVedRealisasjonAvAksjesparekonto, + OppjustertTilleggTilTapVedRealisasjonAvAndelIAksjedelIVerdipapirfond, + OppjustertTilleggTilTapVedRealisasjonAvOgUttakFraAksjedelIFondskonto, + OppjustertTilleggTilTapVedRealisasjonAvVerdipapirfondsandelIKombifondKnyttetTilAksjedel, + OppjustertTilleggTilTapVedRealisasjonAvVerdipapirfondsandelKnyttetTilAksjedel, + OppjustertTilleggTilTapVedSalgAvAndelINOKUS, + OppjustertTilleggTilUtbytteFraAksje, + OppjustertTilleggTilUtbytteFraAksjesparekonto, + OppjustertTilleggTilUtbytteFraVerdipapirfond, + OpptjenteRenterFraPrivatUtestaaendeFordring, + OpptjenteRenterFraUtestaaendeFordring, + OvergangsstoenadTilEnsligForelder, + OverskuddAvEnkeltpersonforetakInnenAnnenNaeringUtenTrygdeavgiftsplikt, + OverskuddAvEnkeltpersonforetakInnenJordbrukGartneriPelsdyrMv, + OverskuddAvEnkeltpersonforetakInnenReindrift, + OverskuddAvEnkeltpersonforetakInnenSkiferproduksjon, + OverskuddAvEnkeltpersonforetakInnenSkogbruk, + OverskuddAvSDF, + OverskuddAvUtgiftsgodtgjoerelseVedSmusstillegg, + OverskuddFraNaeringsinntekt, + PaaloepteRenterFraAnnenGjeld, + PaaloepteRenterFraInkassoselskap, + PaaloepteRenterFraPrivatGjeld, + PensjonFraUtlandetSkattefriINorge, + PensjonFraUtlandetSkattepliktigINorge, + Pensjonsinnbetaling, + PensjonsinntektFritattForSkattEtterSkatteavtale, + PensjonsinntektIEOESTilsvarendeAlderspensjonEllerAFP, + PensjonsinntektOmfattetAvLoennstrekkordningen, + PersoninntektFraKompensasjonsytelseUtbetaltAvNavInnenAnnenNaering, + PersoninntektFraKompensasjonsytelseUtbetaltAvNavInnenBarnepassIBarnepasserensHjem, + PersoninntektFraKompensasjonsytelseUtbetaltAvNavInnenFiskeOgFangst, + PersoninntektFraSDFInnenAnnenNaering, + PersoninntektFraSDFInnenFiskeEllerBarnepassIBarnepasserensHjem, + PersoninntektFraSkattefriLottMedTrygdeavgiftspliktForUtenlandskFisker, + PositivPersoninntektFraEnkeltpersonforetakPaaSvalbard, + PremieTilEgenTilleggstrygdForNaeringsdrivende, + Premiefond, + PremiefondIndividuellPensjonsavtale, + PremiefondLivsforsikring, + PrivatGjeldsbeloep, + Reisefradrag, + RenteinntektAvAnnetFinansprodukt, + RenteinntektAvLivsforsikring, + RenteinntektAvObligasjon, + RenteinntektAvObligasjonVerdipapirfondRentedelMv, + RenteinntektAvObligasjonVerdipapirfondRentedelMvIUtlandet, + RenteinntektAvSkadeforsikring, + RenteinntektAvVerdipapirfondsandel, + RenteinntektMedEkstrabeskatningForLaanTilSelskap, + ReturAvPremieFraIndividuellPensjonssparing, + ReturprovisjonKnyttetTilAksjesparekonto, + ReturprovisjonKnyttetTilFondskonto, + ReturprovisjonKnyttetTilVerdipapirfond, + SaerfradragForEnsligForsoerger, + SaerfradragOverfoertFraBarn, + SaerfradragOverfoertFraEktefelle, + SaerfradragOverfoertTilEktefelle, + SaerfradragOverfoertTilForelder, + SaerskiltFradragForFiskereOgFangstfolk, + SaerskiltFradragForSjoefolk, + SaerskiltInntektsfradragIBarnsInntekt, + SamledeAndreOpptjenteRenter, + SamledeAndrePaaloepteRenter, + SamledeOpptjenteRenterIInnenlandskeBanker, + SamledeOpptjenteRenterIUtenlandskeBanker, + SamledeOpptjenteRenterIUtlandet, + SamledePaaloepteRenter, + SamledePaaloepteRenterPaaGjeldIInnenlandskeBanker, + SamledePaaloepteRenterPaaGjeldIUtlandet, + SamledeUfoererenterOgLivrenter, + SamledeUnderholdsbidrag, + SamletAndelAvFellesgjeldIBoligselskapEllerBoligsameie, + SamletAndelAvFradragsberettigetFelleskostnadForBoligselskapEllerBoligsameie, + SamletAndelAvInntektIBoligselskapEllerBoligsameie, + SamletAnnenGjeld, + SamletAnnenInntektForForskudd, + SamletAnnenPensjonMedTrekkpliktEksklusiveEktefelletillegg, + SamletAnnenPensjonUtenTrekkplikt, + SamletAnnenRenteinntekt, + SamletAvkastningAvKapitalforsikringsavtale, + SamletAvtalefestetPensjon, + SamletBarnepensjonOgLivrente, + SamletBarnepensjonOgLivrenteTilBarn, + SamletFormuesverdiAvPrivatUtestaaendeFordring, + SamletFormuesverdiAvUtestaaendeFordring, + SamletFormuesverdiForAndelAnnenFormueIBoligselskapEllerBoligsameie, + SamletFormuesverdiForAndelerIRentedelAvVerdipapirfond, + SamletFormuesverdiForAnnenFastEiendom, + SamletFormuesverdiForFastEiendomIUtlandet, + SamletFormuesverdiForOevrigFormue, + SamletFormuesverdiForOevrigFormueIUtlandet, + SamletFormuesverdiForSekundaerbolig, + SamletFormuesverdiForSelveidFritidseiendomEllerAndelIFritidsboligselskap, + SamletFradragsberettigetKostnadTilknyttetArbeidMv, + SamletFradragsberettigetUnderskuddVedUtleieAvFastEiendom, + SamletFremfoerbartUnderskuddFraTidligereAar, + SamletGevinstVedRealisasjonAvAndreFinansprodukter, + SamletGevinstVedRealisasjonAvVerdipapirfondsandelKnyttetTilRentedel, + SamletGjeld, + SamletGjenkjoepsverdiForLivsforsikring, + SamletGrunnlagForInntektsskattTilKommuneOgFylkeskommuneStatsskattOgFellesskatt, + SamletInnenlandskGjeld, + SamletInnskuddIInnenlandskeBanker, + SamletInntektSomGirRettTilSaerskiltFradragForSjoefolk, + SamletLoennsinntektMedTrygdeavgiftspliktOgMedTrekkplikt, + SamletLoennsinntektUtenTrygdeavgiftspliktOgMedTrekkplikt, + SamletLoennsinntektUtenTrygdeavgiftspliktOgUtenTrekkplikt, + SamletMerkostnadVedArbeidsoppholdUtenforHjem, + SamletOverskuddAvEnkeltpersonforetakInnenAnnenNaering, + SamletOverskuddAvEnkeltpersonforetakInnenFamiliebarnehageEllerDagmammaIEgetHjem, + SamletOverskuddAvEnkeltpersonforetakInnenFiskeOgFangst, + SamletOverskuddAvSDFInnenAnnenNaering, + SamletOverskuddAvSDFInnenFiskeEllerFamiliebarnehage, + SamletOverskuddPaaUtgiftsgodtgjoerelse, + SamletPensjonFraFolketrygden, + SamletPensjonsinnbetalingTilIndividuellPensjonsordning, + SamletPersoninntektFraEnkeltpersonforetakInnenFamiliebarnehageEllerDagmammaIEgetHjem, + SamletPersoninntektFraEnkeltpersonforetakInnenFiskeOgFangst, + SamletPersoninntektFraEnkeltpersonforetakInnenJordbrukReindriftSkiferproduksjonOgAnnenNaering, + SamletPremiefond, + SamletSaerfradrag, + SamletSaerfradragForStoreSykdomsutgifter, + SamletSaerfradragForUfoerhetIhtOvergangsregel, + SamletSaerskiltFradragForJordbrukReindriftOgSkiferproduksjon, + SamletSkattefriDelAvFormue, + SamletSkattepliktigGevinstVedRealisasjonAvObligasjonEllerVerdipapirfondsandel, + SamletSkattepliktigOverskuddFraUtleieAvFastEiendom, + SamletSkattepliktigOverskuddFraUtleieAvFastEiendomIUtlandet, + SamletTapVedRealisasjonAvVerdipapirfondsandelKnyttetTilRentedel, + SamletUfoeretrygdFraFolketrygdenEksklusiveEktefelletillegg, + SamletUfoereytelseFraAndreEnnFolketrygden, + SamletUnderskuddAvSDF, + SamletUnderskuddAvSDFPaaSvalbard, + SamletUnderskuddINaeringsvirksomhet, + SamletUnderskuddINaeringsvirksomhetPaaSvalbard, + SamletUtgiftsgodtgjoerelseMedTrekkplikt, + SkattefradragForFormuesskattBetaltIUtlandet, + SkattefriLoennsinntektMedTrygdeavgiftspliktOgMedTrekkplikt, + SkattepliktigAksjegevinst, + SkattepliktigAvkastningEllerKundeutbytte, + SkattepliktigEtterloennOgEtterpensjon, + SkattepliktigUtbytteFraAksjeINOKUSIkkeRegistrertIVerdipapirsentralen, + SkattepliktigUtbytteFraAksjeIkkeRegistrertIVerdipapirsentralen, + SkattepliktigUtbytteFraAksjeOgVerdipapirfondAksjedel, + SkattepliktigUtbytteFraAksjerRegistrertIVerdipapirsentralen, + SkattepliktigUtbytteFraVerdipapirfondsandel, + SkattepliktigUtbytteFraVerdipapirfondsandelTilBarn, + Skjermingsfradrag, + SkjermingstilleggTilAlderspensjon, + SkyldigRestskatt, + SkyldigUnderholdsbidrag, + Slitertillegg, + Standardfradrag, + StyrehonorarFraNorskSelskapTilSkattepliktigBosattIUtlandet, + SumFradragIAlminneligInntekt, + SumGjeldsreduksjon, + SumInntekterIAlminneligInntektFoerFordelingsfradrag, + SumMinstefradrag, + SumVerdsettingsrabatt, + SupplerendeStoenad, + SupplerendeStoenadTilUfoerFlyktning, + TapOgAnnenKostnadFraVirtuellEiendel, + TapValutalaan, + TapVedRealisajonAvOgUttakFraAksjedelIFondskonto, + TapVedRealisasjonAvAksje, + TapVedRealisasjonAvAksjeOgVerdipapirfondAksjedel, + TapVedRealisasjonAvAksjesparekonto, + TapVedRealisasjonAvAndelIAksjedelIVerdipapirfond, + TapVedRealisasjonAvAndelIRentedelIVerdipapirfond, + TapVedRealisasjonAvAnnetFinansprodukt, + TapVedRealisasjonAvObligasjonVerdipapirfondRentedelMv, + TapVedRealisasjonAvObligasjoner, + TapVedRealisasjonAvOgUttakFraAksjedelIFondskonto, + TapVedRealisasjonAvOgUttakFraRentedelIFondskonto, + TapVedRealisasjonAvVerdipapirfondsandelIKombifondKnyttetTilAksjedel, + TapVedRealisasjonAvVerdipapirfondsandelKnyttetTilAksjedel, + TapVedRealisasjonAvVirtuellValuta, + TapVedSalgAvAndelINOKUS, + UfoererenterOgLivrenterUtenforArbeidsforhold, + UfoeretrygdFoerAlderspensjon, + UfoeretrygdOmfattetAvLoennstrekkordningen, + UfoereytelseFraIPAOgIPS, + UfoereytelseFraUtlandet, + UnderholdsbidragFraTidligereEktefelle, + UnderholdsbidragTilGode, + UnderskuddAvEnkeltpersonforetakFordeltFraEktefelle, + UnderskuddAvEnkeltpersonforetakPaaSvalbard, + UnderskuddFraSDF, + UnderskuddOverfoertFraBarnOgFordelt, + UnderskuddOverfoertTilForeldre, + UnderskuddVedUtleieMvAvFastEiendomUtenforNaering, + UtbetalingFraAvtaleOmSkattefavorisertIndividuellSparingTilPensjonTegnetFomNov2017, + UtbetalingFraSkadeforsikring, + UtbytteFraAksje, + UtbytteFraAksjesparekonto, + UtbytteFraVerdipapirfond, + UtgiftVedRefinansieringAvLaan, + UtgifterTilPassOgStellAvHjemmevaerendeBarn, + VerdiFoerVerdsettingsrabattForAksje, + VerdiFoerVerdsettingsrabattForAksjeIUtlandet, + VerdiFoerVerdsettingsrabattForAksjeIVPS, + VerdiFoerVerdsettingsrabattForAksjeIkkeIVPS, + VerdiFoerVerdsettingsrabattForAksjeOgAksjefondIFondskonto, + VerdiFoerVerdsettingsrabattForAksjedelIAksjesparekonto, + VerdiFoerVerdsettingsrabattForAndelIAksjedelIVerdipapirfond, + VerdiFoerVerdsettingsrabattForAndelIFellesNettoformueISDF, + VerdiFoerVerdsettingsrabattForAndelINOKUS, + VerdiFoerVerdsettingsrabattForAnnenFormueFraDriftsmidlerAndelISDFMvGenerell, + VerdiFoerVerdsettingsrabattForAnnenFormueInnenforInntektsgivendeAktivitet, + VerdiFoerVerdsettingsrabattForBilerMaskinerOgInventar, + VerdiFoerVerdsettingsrabattForFormuesobjekterINaeringOmfattetAvVerdsettingsrabatt, + VerdiFoerVerdsettingsrabattForInventarLoesoereVedUtleie, + VerdiFoerVerdsettingsrabattForKapitalisertFesteavgift, + VerdiFoerVerdsettingsrabattForRettigheterKnyttetTilSkogUtmark, + VerdiFoerVerdsettingsrabattForSkipFiskeOgFangstfartoey, + VerdiFoerVerdsettingsrabattForVerdipapirfondsandel, + VerdiFoerVerdsettingsrabattForVerdipapirfondsandelTilBarn, + VerdsettingsrabattForAksje, + VerdsettingsrabattForAksjeIUtlandet, + VerdsettingsrabattForAksjeIVPS, + VerdsettingsrabattForAksjeIkkeIVPS, + VerdsettingsrabattForAksjeOgAksjefondIFondskonto, + VerdsettingsrabattForAksjedelIAksjesparekonto, + VerdsettingsrabattForAndelIAksjedelIVerdipapirfond, + VerdsettingsrabattForAndelIFellesNettoformueISDF, + VerdsettingsrabattForAndelINOKUS, + VerdsettingsrabattForAnnenFormueInnenforInntektsgivendeAktivitet, + VerdsettingsrabattForBilerMaskinerOgInventar, + VerdsettingsrabattForFormuesobjekterINaeringOmfattetAvVerdsettingsrabatt, + VerdsettingsrabattForInventarLoesoereVedUtleie, + VerdsettingsrabattForKapitalisertFesteavgift, + VerdsettingsrabattForRettigheterKnyttetTilSkogUtmark, + VerdsettingsrabattForSkipFiskeOgFangstfartoey, + VerdsettingsrabattForVerdipapirfondsandel, + VerdsettingsrabattForVerdipapirfondsandelTilBarn +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TenorOrganisasjonRequest.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TenorOrganisasjonRequest.java new file mode 100644 index 00000000000..3093174a0ad --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TenorOrganisasjonRequest.java @@ -0,0 +1,134 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor.TenorOrganisasjonSelectOptions.Grunnlagsdata; + +import java.math.BigInteger; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TenorOrganisasjonRequest { + + private String organisasjonsnummer; + private Organisasjonsform organisasjonsform; + private Adresse forretningsadresse; + private Boolean harUtenlandskForretningsadresse; + private Boolean harUtenlandskPostadresse; + private String naeringBeskrivelse; + private String naeringKode; + private Boolean registrertIMvaregisteret; + private Boolean registrertIForetaksregisteret; + private Boolean registrertIFrivillighetsregisteret; + private EnhetStatus enhetStatuser; + private Boolean slettetIEnhetsregisteret; + private TenorRequest.Intervall antallAnsatte; + private Boolean revisorer; + private Boolean regnskapsfoerere; + private Boolean dagligLeder; + private Boolean styremedlemmer; + private Boolean forretningsfoerer; + private Boolean kontaktpersoner; + private Boolean norsk_representant; + private ErUnderenhet erUnderenhet; + private Boolean harUnderenheter; + private Integer antallUnderenheter; + private TenorRelasjoner tenorRelasjoner; + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Organisasjonsform { + + private TenorOrganisasjonSelectOptions.OrganisasjonForm kode; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Adresse { + private String kommunenummer; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class EnhetStatus { + + private TenorOrganisasjonSelectOptions.EnhetStatus kode; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class ErUnderenhet { + + private Boolean hovedenhet; + } + + @Data + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class TestinnsendingSkattEnhet { + private BigInteger inntektsaar; + private Boolean harSkattemeldingUtkast; + private Boolean harSkattemeldingFastsatt; + private Boolean harSelskapsmeldingUtkast; + private Boolean harSelskapsmeldingFastsatt; + private Grunnlagsdata manglendeGrunnlagsdata; + private Grunnlagsdata manntall; + } + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Arbeidsforhold { + private TenorRequest.DatoIntervall startDato; + private TenorRequest.DatoIntervall sluttDato; + private Boolean harPermisjoner; + private Boolean harPermitteringer; + private Boolean harTimerMedTimeloenn; + private Boolean harUtenlandsopphold; + private Boolean harHistorikk; + private TenorOrganisasjonSelectOptions.ArbeidsforholdType arbeidsforholdtype; + } + + @Data + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class SamletReskontroinnsyn { + private Boolean harKrav; + private Boolean harInnbetaling; + } + + @Data + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class TjenestepensjonsavtaleOpplysningspliktig { + private String tjenestepensjonsinnretningOrgnr; + private String periode; + } + + @Data + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class TenorRelasjoner { + private TestinnsendingSkattEnhet testinnsendingSkattEnhet; + private Arbeidsforhold arbeidsforhold; + private SamletReskontroinnsyn samletReskontroinnsyn; + private TjenestepensjonsavtaleOpplysningspliktig tjenestepensjonsavtaleOpplysningspliktig; + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TenorOrganisasjonSelectOptions.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TenorOrganisasjonSelectOptions.java new file mode 100644 index 00000000000..5e4c6fbd549 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TenorOrganisasjonSelectOptions.java @@ -0,0 +1,160 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +public class TenorOrganisasjonSelectOptions { + + @Getter + @AllArgsConstructor + public enum OrganisasjonForm implements LabelEnum { + AAFY("Underenhet til ikke-næringsdrivende"), + ADOS("Administrativ enhet - offentlig sektor"), + ANNA("Annen juridisk person"), + ANS("Ansvarlig selskap med solidarisk ansvar"), + AS("Aksjeselskap"), + ASA("Allmennaksjeselskap"), + BA("Selskap med begrenset ansvar"), + BBL("Boligbyggelag"), + BEDR("Underenhet til næringsdrivende og offentlig forvaltning"), + BO("Andre bo"), + BRL("Borettslag"), + DA("Ansvarlig selskap med delt ansvar"), + ENK("Enkeltpersonforetak"), + EØFG("Europeisk økonomisk foretaksgruppe"), + ESEK("Eierseksjonssameie"), + FKF("Fylkeskommunalt foretak"), + FLI("Forening/lag/innretning"), + FYLK("Fylkeskommune"), + GFS("Gjensidig forsikringsselskap"), + IKJP("Andre ikke-juridiske personer"), + IKS("Interkommunalt selskap"), + KBO("Konkursbo"), + KF("Kommunalt foretak"), + KIRK("Den norske kirke"), + KOMM("Kommune"), + KS("Kommandittselskap"), + KTRF("Kontorfellesskap"), + NUF("Norskregistrert utenlandsk foretak"), + OPMV("Særskilt oppdelt enhet, jf. mval. § 2-2"), + ORGL("Organisasjonsledd"), + PERS("Andre enkeltpersoner som registreres i tilknyttet register"), + PK("Pensjonskasse"), + PRE("Partrederi"), + SA("Samvirkeforetak"), + SAM("Tingsrettslig sameie"), + SE("Europeisk selskap"), + SF("Statsforetak"), + SPA("Sparebank"), + STAT("Staten"), + STI("Stiftelse"), + SÆR("Annet foretak iflg. særskilt lov"), + TVAM("Tvangsregisrert for MVA"), + UTLA("Utenlandsk enhet"), + VPFO("Verdipapirfond"); + + private final String label; + + @Override + public String getName() { + return name(); + } + + @Override + public String getLabel() { + return label; + } + } + + @Getter + @AllArgsConstructor + public enum EnhetStatus implements LabelEnum { + OPPL("Oppløst"), + KONK("Åpnet konkurs"); + + private final String label; + + @Override + public String getName() { + return name(); + } + + @Override + public String getLabel() { + return label; + } + } + + @Getter + @AllArgsConstructor + public enum Grunnlagsdata implements LabelEnum { + AKSJESPAREKONTO("Aksjesparekonto"), + BARNEPASS("Betaling for pass og stell av barn"), + BETALINGER_NAERINGSDRIVENDE("Betalinger til selvstendig næringsdrivende"), + BOLIGSAMEIE("Boligsameie"), + BOLIGSELSKAP("Boligselskap"), + BSU("Boligsparing for ungdom "), + CRSFATCA("Internasjonal rapportering"), + DROSJESENTRALER("Drosjetjenester"), + EIENDOMSUTLEIE("Utleie av fast eiendom fra formidlingsselskap"), + ENOVA("Enova"), + FAGFORENINGSKONTINGENT("Fagforeningskontingent"), + FINANSPRODUKTER("Finansprodukter"), + FONDSKONTO("Fondskonto"), + GAVER_TIL_ORG("Gaver til organisasjoner"), + GODTGJOERELSE_OPPHAVSMANN("Godtgjøring til opphaver til åndsverk"), + INDIVIDUELLE_PENSJONSORDNINGER("Individuelle pensjonsordninger"), + KOP_EGG("Kjøp fra primærnæring - egg"), + KOP_FISK("Kjøp fra primærnæring - fisk"), + KOP_JORD_HAGEBRUK("Kjøp fra primærnæring - jord- og hagebruk"), + KOP_KORN("Kjøp fra primærnæring - korn"), + KOP_MELK("Kjøp fra primærnæring - melk"), + KOP_PELSDYRSKINN("Kjøp fra primærnæring - pelsdyr"), + KOP_SLAKT("Kjøp fra primærnæring - slakt"), + KOP_TILSKUDD("Tilskudd innen primærnæringene"), + KOP_TOEMMER("Kjøp fra primærnæring - tømmer"), + LIVSFORSIKRING("Livsforsikring"), + SALDO_RENTE("Innskudd, utlån og renter m.v."), + SKADEFORSIKRING("Skadeforsikring"), + SKATTEFRIE_UTBETALINGER("Skattefrie utbetalinger fra offentlig myndighet"), + SKATTEPLIKTIG_KUNDEUTBYTTE("Skattepliktig kundeutbytte"), + SKE_A_ORDNING_INNTEKTSMOTTAKER("a-melding"), + TILDELTE_OPSJONER("Opsjoner i oppstartsselskap"), + TILSKUDD_FORSK("Tilskudd til forskning eller yrkesopplæring"), + UNDERHOLDSBIDRAG("Underholdsbidrag"), + VERDIPAPIRFOND("Verdipapirfond"); + + private final String label; + + @Override + public String getName() { + return name(); + } + + @Override + public String getLabel() { + return label; + } + } + + @Getter + @AllArgsConstructor + public enum ArbeidsforholdType implements LabelEnum { + OrdinaertArbeidsforhold("Ordinært"), + MaritimtArbeidsforhold("Maritimt"), + FrilanserOppdragstakerHonorarPersonerMm("Frilanser med mer"); + + private final String label; + + @Override + public String getName() { + return name(); + } + + @Override + public String getLabel() { + return label; + } + } + +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TenorOversiktOrganisasjonResponse.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TenorOversiktOrganisasjonResponse.java new file mode 100644 index 00000000000..28bc91e470f --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TenorOversiktOrganisasjonResponse.java @@ -0,0 +1,48 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor; + +import com.fasterxml.jackson.databind.JsonNode; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.http.HttpStatus; + +import java.util.List; +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TenorOversiktOrganisasjonResponse { + private HttpStatus status; + private Data data; + private String query; + private String error; + + @lombok.Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Data { + + private Integer treff; + private Integer rader; + private Integer offset; + private Integer nesteSide; + private Integer seed; + private List organisasjoner; + } + + @lombok.Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class Organisasjon { + + private String navn; + private String organisasjonsnummer; + private JsonNode tenorMetadata; + private JsonNode tenorRelasjoner; + private JsonNode brregKildedata; + private List kilder; + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TenorRequest.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TenorRequest.java new file mode 100644 index 00000000000..3c8a0fdc2a0 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/domain/tenor/TenorRequest.java @@ -0,0 +1,358 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigInteger; +import java.time.LocalDate; +import java.time.YearMonth; +import java.util.ArrayList; +import java.util.List; + +import static java.util.Objects.isNull; + +@Data +@NoArgsConstructor +@SuppressWarnings("java:S115") +public class TenorRequest { + + public enum IdentifikatorType {Foedselsnummer, DNummer, DNummerOgFoedselsnr} + + public enum Kjoenn {Mann, Kvinne} + + public enum Rolle {DagligLeder} + + public enum Personstatus {Bosatt, Doed, Forsvunnet, Foedselsregistrert, IkkeBosatt, Inaktiv, Midlertidig, Opphoert, Utflyttet} + + public enum Sivilstand {EnkeEllerEnkemann, Gift, GjenlevendePartner, RegistrertPartner, Separert, SeparertPartner, Skilt, SkiltPartner, Ugift, Uoppgitt} + + public enum UtenlandskPersonIdentifikasjon {UtenlandskIdentifikasjonsnummer, TaxIdentificationNumber, SocialSecurityNumber, UtlendingsmyndighetenesIdentifikasjonsnummer} + + public enum IdentitetsgrunnlagStatus {IkkeKontrollert, IngenStatus, Kontrollert} + + public enum Adressebeskyttelse {Fortrolig, StrengtFortrolig} + + public enum AdresseGradering {Ugradert, Klientadresse, Fortrolig} + + public enum Relasjon {Barn, Far, Medmor, Mor, Partner} + + public enum Skattemeldingstype {KunUtkast, UtkastOgFastsatt} + + public enum Inntektstype {Loennsinntekt, Naeringsinntekt, PensjonEllerTrygd, YtelseFraOffentlige} + + public enum AOrdningBeskrivelse { + Alderspensjon, AlderspensjonSkjermingstillegg, AndreBeskrivelser, + Arbeidsavklaringspenger, AvtalefestetPensjon, Bil, Bonus, DagpengerVedArbeidsloeshet, Ektefelletillegg, + ElektroniskKommunikasjon, Fagforeningskontingent, FastBilgodtgjoerelse, Fastloenn, FastTillegg, Feriepenger, + Foreldrepenger, IpaEllerIpsPeriodiskeYtelser, Kvalifiseringsstoenad, NyAvtalefestetPensjonPrivatSektor, + PensjonOgLivrenterIArbeidsforhold, ReiseKostMedOvernattingPaaHybelMedKokEllerPrivat, + ReiseKostMedOvernattingPaaHybelUtenKokEllerPensjonatEllerBrakke, Sykepenger, Timeloenn, Ufoeretrygd + } + + public enum Forskuddstrekk { + OrdinaertForskuddstrekk, Barnepensjon, KildeskattPaaPensjon, Svalbard, + JanMayenOgBilandene, BetaltTrygdeavgiftTilJanMayen + } + + public enum Skattepliktstype {SkattepliktTilNorge, SkattepliktTilSvalbard} + + public enum SaerskiltSkatteplikt { + KildeskattepliktPaaLoenn, KildeskattepliktPaaPensjon, + SkattepliktAvNaeringsdriftEiendomMv, SkattepliktEtterPetroleumsskatteloven, + SkattepliktPaaLoennFraDenNorskeStatOpptjentIUtlandet, SkattepliktSomSjoemann, + SkattepliktSomUtenrikstjenestemann, SkattepliktVedUtenriksoppholdINorskStatstjenesteEllerNato + } + + public enum TilleggsskattType { + FradragForTvangsmulkt, SkjerpetTilleggsskattFraUriktigeOpplysninger, TilleggsskattFraUriktigeOpplysninger, + TilleggsskattFraManglendeInnlevering, SkjerpetTilleggsskattFraManglendeInnlevering + } + + public enum Arbeidsforholdstype { + OrdinaertArbeidsforhold, MaritimtArbeidsforhold, FrilanserOppdragstakerHonorarPersonerMm + } + + public enum Oppgjoerstype {Fastland, Svalbard, KildeskattPaaLoenn} + + public enum Stadietype {Utkast, Fastsatt, Oppgjoer} + + @Schema(description = "Personidentifikator, fødselsnummer eller d-nummer") + private String identifikator; + private IdentifikatorType identifikatorType; + private DatoIntervall foedselsdato; + private DatoIntervall doedsdato; + private Kjoenn kjoenn; + private Personstatus personstatus; + private Sivilstand sivilstand; + private List utenlandskPersonIdentifikasjon; + private IdentitetsgrunnlagStatus identitetsgrunnlagStatus; + private Adressebeskyttelse adressebeskyttelse; + private Boolean harLegitimasjonsdokument; + private Boolean harFalskIdentitet; + private Boolean harNorskStatsborgerskap; + private Boolean harFlereStatsborgerskap; + private Navn navn; + private Adresser adresser; + private Relasjoner relasjoner; + private Hendelser hendelser; + + private List roller; + private Tjenestepensjonsavtale tjenestepensjonsavtale; + private Skattemelding skattemelding; + private Inntekt inntekt; + private Skatteplikt skatteplikt; + private Tilleggsskatt tilleggsskatt; + private Arbeidsforhold arbeidsforhold; + private BeregnetSkatt beregnetSkatt; + private TestinnsendingSkattPerson testinnsendingSkattPerson; + private SamletReskontroInnsyn samletReskontroInnsyn; + private SummertSkattegrunnlag summertSkattegrunnlag; + private SpesisfisertSummertSkattegrunnlag spesifisertSummertSkattegrunnlag; + + public List getUtenlandskPersonIdentifikasjon() { + + if (isNull(utenlandskPersonIdentifikasjon)) { + utenlandskPersonIdentifikasjon = new ArrayList<>(); + } + return utenlandskPersonIdentifikasjon; + } + + public List getRoller() { + + if (isNull(roller)) { + roller = new ArrayList<>(); + } + return roller; + } + + @Data + @NoArgsConstructor + public static class DatoIntervall { + + @Schema(type = "string", format = "YYYY-MM-DD", example = "2018-07-01") + private LocalDate fraOgMed; + @Schema(type = "string", format = "YYYY-MM-DD", example = "2020-07-01") + private LocalDate tilOgMed; + } + + @Data + @NoArgsConstructor + public static class Intervall { + + private BigInteger fraOgMed; + private BigInteger tilOgMed; + } + + @Data + @NoArgsConstructor + public static class Navn { + + private Intervall navnLengde; + private Boolean harFlereFornavn; + private Boolean harMellomnavn; + private Boolean harNavnSpesialtegn; + } + + @Data + @NoArgsConstructor + public static class Adresser { + + @Schema(description = "Adressesøk, fritekst") + private AdresseGradering adresseGradering; + private BigInteger kommunenummer; + private Boolean harBostedsadresse; + private Boolean harOppholdAnnetSted; + private Boolean harPostadresseNorge; + private Boolean harPostadresseUtland; + private Boolean harKontaktadresseDoedsbo; + private Boolean harAdresseSpesialtegn; + } + + @Data + @NoArgsConstructor + public static class Relasjoner { + + private Relasjon relasjon; + private Intervall antallBarn; + private Boolean harForeldreAnsvar; + private Intervall relasjonMedFoedselsaar; + private Boolean harDeltBosted; + private Boolean harVergemaalEllerFremtidsfullmakt; + private Boolean borMedMor; + private Boolean borMedFar; + private Boolean borMedMedmor; + private Boolean foreldreHarSammeAdresse; + } + + @Data + @NoArgsConstructor + public static class Hendelser { + + private Hendelse hendelse; + private Hendelse sisteHendelse; + } + + @Data + @NoArgsConstructor + public static class Tjenestepensjonsavtale { + + @Schema(description = "Pensjonsinnretningen organisasjonsnummer, 9 siffre") + private String pensjonsinnretningOrgnr; + @Schema(type = "string", format = "YYYY-MM", example = "2020-07") + private YearMonth periode; + } + + @Data + @NoArgsConstructor + public static class Skattemelding { + + @Schema(description = "Inntektsår, 4 siffre, årene 2018, 2019, 2020, 2021, 2022 ... osv opptil i forfjor") + private BigInteger inntektsaar; + private Skattemeldingstype skattemeldingstype; + } + + @Data + @NoArgsConstructor + public static class Inntekt { + + private MonthInterval periode; + private BigInteger opplysningspliktig; + private List inntektstyper; + private AOrdningBeskrivelse beskrivelse; + private List forskuddstrekk; + private Boolean harHistorikk; + + public List getInntektstyper() { + + if (isNull(inntektstyper)) { + inntektstyper = new ArrayList<>(); + } + return inntektstyper; + } + + public List getForskuddstrekk() { + + if (isNull(forskuddstrekk)) { + forskuddstrekk = new ArrayList<>(); + } + return forskuddstrekk; + } + } + + @Data + @NoArgsConstructor + public static class MonthInterval { + + @Schema(type = "string", format = "YYYY-MM", example = "2020-07") + private YearMonth fraOgMed; + @Schema(type = "string", format = "YYYY-MM", example = "2020-07") + private YearMonth tilOgMed; + } + + @Data + @NoArgsConstructor + public static class Skatteplikt { + + @Schema(description = "Inntektsår, 4 siffre, årene 2019, 2019, 2020, 2021, 2022, 2023 ... osv opptil i fjor") + private BigInteger inntektsaar; + private List skattepliktstyper; + private SaerskiltSkatteplikt saerskiltSkatteplikt; + + public List getSkattepliktstyper() { + + if (isNull(skattepliktstyper)) { + skattepliktstyper = new ArrayList<>(); + } + return skattepliktstyper; + } + } + + @Data + @NoArgsConstructor + public static class Tilleggsskatt { + + private BigInteger inntektsaar; + private List tilleggsskattTyper; + + public List getTilleggsskattTyper() { + + if (isNull(tilleggsskattTyper)) { + tilleggsskattTyper = new ArrayList<>(); + } + return tilleggsskattTyper; + } + } + + @Data + @NoArgsConstructor + public static class Arbeidsforhold { + + private DatoIntervall startDatoPeriode; + private DatoIntervall sluttDatoPeriode; + private Boolean harPermisjoner; + private Boolean harPermitteringer; + private Boolean harArbeidsgiver; + private Boolean harTimerMedTimeloenn; + private Boolean harUtenlandsopphold; + private Boolean harHistorikk; + private Arbeidsforholdstype arbeidsforholdstype; + } + + @Data + @NoArgsConstructor + public static class BeregnetSkatt { + + @Schema(description = "Inntektsår, 4 siffre, årene 2018, 2019, 2020, 2021, 2022, 2023 ... osv opptil i fjor") + private BigInteger inntektsaar; + private Oppgjoerstype oppgjoerstype; + private Boolean pensjonsgivendeInntekt; + } + + @Data + @NoArgsConstructor + @Schema(description = "Opplysninger fra skatteetatens innsendingsmiljoe") + public static class TestinnsendingSkattPerson { + + @Schema(description = "Inntektsår, 4 siffre, årene 2020, 2021, 2022, 2023 ... osv opptil i fjor") + private BigInteger inntektsaar; + @Schema(description = "Skattemelding utkast, merk at false indikerer har ikke skatteMeldingUtkast") + private Boolean harSkattemeldingUtkast; + @Schema(description = "Skattemelding fastsatt, merk at false indikerer har ikke skatteMeldingFastsatt") + private Boolean harSkattemeldingFastsatt; + } + + @Data + @NoArgsConstructor + public static class SamletReskontroInnsyn { + + private Boolean harKrav; + private Boolean harInnbetaling; + } + + @Data + @NoArgsConstructor + public static class SummertSkattegrunnlag { + + @Schema(description = "Inntektsår, 4 siffre, årene 2019, 2020, 2021, 2022, 2023 ... osv opptil i fjor") + private BigInteger inntektsaar; + private Stadietype stadietype; + private Oppgjoerstype oppgjoerstype; + private TekniskNavn tekniskNavn; + private Intervall alminneligInntektFoerSaerfradragBeloep; + } + + @Data + @NoArgsConstructor + public static class SpesisfisertSummertSkattegrunnlag { + + @Schema(description = "Inntektsår, 4 siffre, årene 2019, 2020, 2021, 2022, 2023 ... osv opptil i fjor") + private BigInteger inntektsaar; + private Stadietype stadietype; + private Oppgjoerstype oppgjoerstype; + private TekniskNavn tekniskNavn; + private Spesifiseringstype spesifiseringstype; + private Intervall alminneligInntektFoerSaerfradragBeloep; + } +} + diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/entity/AnsettelseLogg.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/entity/AnsettelseLogg.java new file mode 100644 index 00000000000..b5c78d1f4a1 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/entity/AnsettelseLogg.java @@ -0,0 +1,52 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.entity; + +import jakarta.persistence.*; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.*; +import org.hibernate.annotations.ColumnDefault; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.OffsetDateTime; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "ansettelse_logg") +public class AnsettelseLogg { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", nullable = false) + private Integer id; + + @Size(max = 255) + @NotNull + @Column(name = "organisasjonsnummer", nullable = false) + private String organisasjonsnummer; + + @Size(max = 255) + @NotNull + @Column(name = "folkeregisterident", nullable = false) + private String folkeregisterident; + + + @NotNull + @Column(name = "\"timestamp\"", nullable = false) + private OffsetDateTime timestamp; + + @NotNull + @Column(name = "ansattfra", nullable = false) + private LocalDate ansattfra; + + @Size(max = 255) + @Column(name = "arbeidsforhold_type") + private String arbeidsforholdType; + + @Column(name = "stillingsprosent") + private BigDecimal stillingsprosent; + +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/entity/JobbParameter.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/entity/JobbParameter.java new file mode 100644 index 00000000000..8d7434a1ce0 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/entity/JobbParameter.java @@ -0,0 +1,37 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@Entity +@Table(name = "jobb_parameter") +public class JobbParameter { + @Id + @Size(max = 255) + @Column(name = "navn", nullable = false) + private String navn; + + @Size(max = 255) + @NotNull + @Column(name = "tekst", nullable = false) + private String tekst; + + @Size(max = 255) + @Column(name = "verdi") + private String verdi; + + @Column(name = "verdier") + private List verdier; + + +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/entity/JobbParameterNavn.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/entity/JobbParameterNavn.java new file mode 100644 index 00000000000..e86758f600e --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/entity/JobbParameterNavn.java @@ -0,0 +1,14 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.entity; + +import lombok.Getter; + +public enum JobbParameterNavn { + ANTALL_ORGANISASJONER ("antallOrganisasjoner"), + ANTALL_PERSONER ("antallPersoner"), + INTERVALL ("intervall"), + STILLINGSPROSENT ("stillingsprosent"), + ARBEIDSFORHOLD_TYPE ("arbeidsforholdType"); + + public final String value; + JobbParameterNavn(String value){this.value = value;} +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/provider/PdlMiljoer.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/provider/PdlMiljoer.java new file mode 100644 index 00000000000..f135ef0e8c2 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/provider/PdlMiljoer.java @@ -0,0 +1,5 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.provider; + +public enum PdlMiljoer { + Q1, Q2 + } \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/repository/AnsettelseLoggRepository.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/repository/AnsettelseLoggRepository.java new file mode 100644 index 00000000000..e1c481d14f2 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/repository/AnsettelseLoggRepository.java @@ -0,0 +1,7 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.repository; + +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.entity.AnsettelseLogg; +import org.springframework.data.repository.CrudRepository; + +public interface AnsettelseLoggRepository extends CrudRepository { +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/repository/JobberRepository.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/repository/JobberRepository.java new file mode 100644 index 00000000000..277d6af393d --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/repository/JobberRepository.java @@ -0,0 +1,14 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.repository; + + +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.entity.JobbParameter; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface JobberRepository extends JpaRepository { + //@Query("select * from JOBB_PARAM") + List findAll(); + + JobbParameter findByNavn(String navn); +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/AnsettelseLoggService.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/AnsettelseLoggService.java new file mode 100644 index 00000000000..7573acfd9f5 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/AnsettelseLoggService.java @@ -0,0 +1,42 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.service; + +import lombok.RequiredArgsConstructor; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.dto.OrganisasjonDTO; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl.Ident; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.entity.AnsettelseLogg; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.repository.AnsettelseLoggRepository; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.OffsetDateTime; + +/** + * Klasse for å lagre ansedttelsene som har blir gjort i ansettelse_ligg db. + */ +@Service +@RequiredArgsConstructor +public class AnsettelseLoggService { + + private final AnsettelseLoggRepository ansettelseLoggRepository; + + /** + * Funksjonen som lagrer ansettelsen i db + * @param person Ident objektet til personen som har blir ansatt. + * @param org OrgaisasjonDTO objektet til organisasjonen personen har + * blitt ansatt i. + * @param stillingsprosent Stillingsprosenten i arbeidsavtalen til personen. + * @param arbeidsforholdType Arbeidsforholdtypen i arbeidsatalen til personen. + */ + public void lagreAnsettelse(Ident person, OrganisasjonDTO org, Double stillingsprosent, String arbeidsforholdType){ + AnsettelseLogg ansettelseLogg = AnsettelseLogg.builder() + .folkeregisterident(person.getIdent()) + .organisasjonsnummer(org.getOrganisasjonsnummer()) + .timestamp(OffsetDateTime.now()) + .arbeidsforholdType(arbeidsforholdType) + .stillingsprosent(BigDecimal.valueOf(stillingsprosent)) + .ansattfra(LocalDate.now()) + .build(); + ansettelseLoggRepository.save(ansettelseLogg); + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/AnsettelseService.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/AnsettelseService.java new file mode 100644 index 00000000000..8b34499c212 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/AnsettelseService.java @@ -0,0 +1,228 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.DatoIntervall; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.dto.OrganisasjonDTO; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.kodeverk.KodeverkNavn; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl.Ident; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.entity.JobbParameterNavn; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.service.util.AlderspennList; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.service.util.AliasMethod; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Arbeidsforhold; +import org.springframework.http.HttpStatusCode; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Random; + +import static no.nav.registre.testnorge.levendearbeidsforholdansettelse.entity.JobbParameterNavn.ANTALL_ORGANISASJONER; +import static no.nav.registre.testnorge.levendearbeidsforholdansettelse.entity.JobbParameterNavn.ANTALL_PERSONER; +import static no.nav.registre.testnorge.levendearbeidsforholdansettelse.entity.JobbParameterNavn.ARBEIDSFORHOLD_TYPE; +import static no.nav.registre.testnorge.levendearbeidsforholdansettelse.entity.JobbParameterNavn.STILLINGSPROSENT; + +@Slf4j +@Service +@RequiredArgsConstructor +public class AnsettelseService { + + private final PdlService pdlService; + private final TenorService tenorService; + private final ArbeidsforholdService arbeidsforholdService; + private final JobbService jobbService; + private final KodeverkService kodeverkService; + private final AnsettelseLoggService ansettelseLoggService; + + public void runAnsettelseService() { + Thread thread = new Thread(this::ansettelseService); + thread.start(); + try { + thread.join(3000000); //Timeout etter 3000 sekunder + if (thread.isAlive()) { + thread.interrupt(); + System.out.println("Timeout occurred"); + } + } catch (InterruptedException e) { + log.info("Timet ut"); + } + } + + public void ansettelseService() { + //Henter yrkeskoder for å gi tilfeldige yrker + List yrkeskoder = hentKodeverk(); + if (yrkeskoder.isEmpty()) { + return; + } + + //Initialiserer liste over alderspenn og liste med tidligste og seneste gyldig dato for ansttelse + AlderspennList alderspennList = new AlderspennList(); + List datoIntervaller = alderspennList.getDatoListe(); + + //Initialiserer aliasmetode for å benytte mer realistiske alderspenn i ansettelsene + List sannsynlighetFordeling = alderspennList.sannsynlighetFordeling; + AliasMethod alias = new AliasMethod(sannsynlighetFordeling); + + //Henter parametere fra db + Map parametere = hentParametere(); + + //Henter organisasjoner fra Tenor + List organisasjoner = hentOrganisasjoner(Integer.parseInt(parametere.get(ANTALL_ORGANISASJONER.value))); + if (organisasjoner.isEmpty()) { + return; + } + + //Regner ut hvor mange som skal ansettes per org + int antallPersPerOrg; + try { + antallPersPerOrg = getAntallAnsettelserHverOrg(Integer.parseInt(parametere.get(ANTALL_PERSONER.value)), Integer.parseInt(parametere.get(ANTALL_ORGANISASJONER.value))); + } catch (NumberFormatException e) { + log.error("Feil format på verdiene fra db"); + return; + } + + int finalAntallPersPerOrg = antallPersPerOrg; + //Kjører ansettelse per org + organisasjoner.forEach( + organisasjon -> { + if (tenorService.hentOrgPostnummer(organisasjon.getOrganisasjonsnummer()) == null) { + organisasjon = hentOrganisasjoner(1).getFirst(); + } + String postnr = konverterPostnr(tenorService.hentOrgPostnummer(organisasjon.getOrganisasjonsnummer())); + + //Trekker alderspenn fra alias for hver pers som skal ansettes + List aldersspennIndekser = new ArrayList<>(); + for (int i = 0; i < finalAntallPersPerOrg; i++) { + aldersspennIndekser.add(alias.aliasDraw()); + } + + Iterator aldersspennIterator = aldersspennIndekser.iterator(); + int iteratorElement = aldersspennIterator.next(); + + //Henter mulige personer per alderspenn basert på postnummer fra org + Map> muligePersonerMap = new HashMap<>(); + aldersspennIndekser.forEach( + indeks -> { + if (!muligePersonerMap.containsKey(indeks)) { + muligePersonerMap.put(indeks, hentPersoner(datoIntervaller.get(indeks).getFrom().toString(), datoIntervaller.get(indeks).getTom().toString(), postnr)); + } + }); + + List ansattePersoner = new ArrayList<>(); + + //Ansetter personer + while (ansattePersoner.size() < finalAntallPersPerOrg) { + try { + List muligePersoner = muligePersonerMap.get(iteratorElement); + + var tilfeldigIndex = tilfeldigTall(muligePersoner.size()); + var tilfeldigPerson = muligePersoner.get(tilfeldigIndex); + + var stillingsprosent = Double.parseDouble(parametere.get(STILLINGSPROSENT.value)); + var arbeidsforholdList = arbeidsforholdService.hentArbeidsforhold(tilfeldigPerson.getIdent()); + + if(kanAnsettes(stillingsprosent, arbeidsforholdList) ) { + var tilfeldigYrke = hentTilfeldigYrkeskode(yrkeskoder); + + //Try-catch fordi vi møtte på problemer der noen org ikke fikk suksessfulle ansettelser + try { + var ansettSporring = ansettPerson(tilfeldigPerson.getIdent(), + organisasjon.getOrganisasjonsnummer(), + tilfeldigYrke, + parametere.get(JobbParameterNavn.STILLINGSPROSENT.value)); + if (ansettSporring.isPresent() && ansettSporring.get().is2xxSuccessful()) { + ansattePersoner.add(tilfeldigPerson); + + if (aldersspennIterator.hasNext()) { + iteratorElement = aldersspennIterator.next(); + } + } + }catch (WebClientResponseException e){ + log.error(e.toString()); + //Løsningen var å hente en ny tilfeldig organisasjon, da ingen personer fikk + //vellykket ansettelse uansett hvor mange vi prøvde å hente + organisasjon = hentOrganisasjoner(1).getFirst(); + continue; + } + } + muligePersoner.remove(tilfeldigIndex); + + } catch (NullPointerException e) { + log.error(e.toString()); + //Henter ny liste med mulige personer dersom den forrige blir tom uten at man fikk ansatt nok + muligePersonerMap.replace(iteratorElement, hentPersoner(datoIntervaller.get(iteratorElement).getFrom().toString(), + datoIntervaller.get(iteratorElement).getTom().toString(), postnr)); + } catch (Exception e) { + log.error(e.toString()); + break; + } + } + //Logging til db + for (Ident person: ansattePersoner){ + ansettelseLoggService.lagreAnsettelse(person, organisasjon, Double.parseDouble(parametere.get(STILLINGSPROSENT.value)), parametere.get(ARBEIDSFORHOLD_TYPE.value)); + } + } + ); + } + + private Map hentParametere() { + return jobbService.hentParameterMap(); + } + + private List hentOrganisasjoner(int antall) { + return tenorService.hentOrganisasjoner(antall); + } + + private List hentPersoner(String tidligsteFoedselsdato, String senesteFoedselsdato, String postnr) { + pdlService.setFrom(tidligsteFoedselsdato); + pdlService.setTo(senesteFoedselsdato); + pdlService.setPostnr(postnr); + return pdlService.getPersoner(); + } + + private boolean kanAnsettes(Double stillingsprosent, List arbeidsforholdList) { + + if (!arbeidsforholdList.isEmpty()) { + for (var arbeidsforhold : arbeidsforholdList) { + for (var arbeidsavtale : arbeidsforhold.getArbeidsavtaler()) { + if (arbeidsavtale.getBruksperiode().getTom() == null) { + stillingsprosent += arbeidsavtale.getStillingsprosent(); + if (stillingsprosent > 100) return false; + } + } + } + } + return true; + } + + private Optional ansettPerson(String ident, String orgnummer, String yrke, String stillingsprosent) { + return arbeidsforholdService.opprettArbeidsforhold(ident, orgnummer, yrke, stillingsprosent); + } + + private int getAntallAnsettelserHverOrg(int antallPers, int antallOrg) { + //Kan implementere mer tilfeldig fordelig, foreløpig får alle organisasjonene like mange folk + return antallPers/antallOrg; + } + + private int tilfeldigTall(int max) { + Random random = new Random(); + return random.nextInt(max); + } + + private List hentKodeverk() { + return kodeverkService.hentKodeverkValues(KodeverkNavn.YRKER.value); + } + + private String hentTilfeldigYrkeskode(List yrkeskoder) { + return yrkeskoder.get(tilfeldigTall(yrkeskoder.size())); + } + + private String konverterPostnr(String postnr) { + return postnr.charAt(0) + "???"; + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/ArbeidsforholdService.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/ArbeidsforholdService.java new file mode 100644 index 00000000000..927c788d739 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/ArbeidsforholdService.java @@ -0,0 +1,100 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.AaregConsumer; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Ansettelsesperiode; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Arbeidsforhold; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.OrdinaerArbeidsavtale; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Organisasjon; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Periode; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Person; +import org.springframework.http.HttpStatusCode; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicInteger; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ArbeidsforholdService { + private final AaregConsumer aaregConsumer; + private final String arbeidstakerType = "Person"; + private final String arbeidsgiverType = "Organisasjon"; + private final String arbeidsforholdType = "ordinaertArbeidsforhold"; //#TODO KAN BLI HENTET FRA DB + private final String arbeidstidsordning = "ikkeSkift"; + private final String ansettelsesform = "fast"; + private final double TIMER_HUNDRE_PROSENT = 37.5; + private final int HUNDRE_PROSENT = 100; + + + /** + * @param ident Identnummeret til personen det skal hentes arbeidsforhold for + * @return Liste med arbeidsforhold + */ + public List hentArbeidsforhold(String ident) { + return aaregConsumer.hentArbeidsforhold(ident); + } + + /** + * Oppretter arbeidsforhold via aaregConsumer + * + * @param ident Identnummeret til personen det skal opprettes arbeidsforhold for + * @param orgnummer Organisasjonsnummeret til organisasjonen personen skal ansettes i + * @param yrke Yrkeskoden til yrket personen skal ansettes med + * @param stillingsprosent Stillinsprosenten arbeidsforholdet skal ha + * @return HttpStatusCode basert på resultatet av spørringen + */ + public Optional opprettArbeidsforhold(String ident, String orgnummer, String yrke, String stillingsprosent) { + return aaregConsumer.opprettArbeidsforhold(lagArbeidsforhold(ident, orgnummer, yrke, stillingsprosent)); + } + + + /** + * Bygger et rbeidsforhold-objekt basert på parameterene + * + * @param ident Identnummeret til personen det skal opprettes arbeidsforhold for + * @param orgnummer Organisasjonsnummeret til organisasjonen personen skal ansettes i + * @param yrke Yrkeskoden til yrket personen skal ansettes med + * @param prosent Stillinsprosenten arbeidsforholdet skal ha + * @return Et Arbeidsforhold-objekt basert på parameterene + */ + private Arbeidsforhold lagArbeidsforhold(String ident, String orgnummer, String yrke, String prosent) { + + var arbeidsforholdList = hentArbeidsforhold(ident); + var stillingsprosent = Double.parseDouble(prosent); + var antallTimerPrUke = BigDecimal.valueOf(TIMER_HUNDRE_PROSENT*stillingsprosent/HUNDRE_PROSENT).setScale(1, RoundingMode.HALF_UP).doubleValue(); + var arbeidsforholdId = new AtomicInteger(arbeidsforholdList.size()); + + return Arbeidsforhold.builder() + .arbeidsforholdId(Integer.toString(arbeidsforholdId.incrementAndGet())) + .arbeidstaker(Person.builder() + .offentligIdent(ident) + .type(arbeidstakerType) + .build()) + .arbeidsgiver(Organisasjon.builder() + .organisasjonsnummer(orgnummer) + .type(arbeidsgiverType) + .build()) + .type(arbeidsforholdType) + .ansettelsesperiode(Ansettelsesperiode.builder() + .periode(Periode.builder() + .fom(LocalDate.now()) + .build()) + .build()) + .arbeidsavtaler(List.of(OrdinaerArbeidsavtale.builder() + .antallTimerPrUke(antallTimerPrUke) + .arbeidstidsordning(arbeidstidsordning) + .stillingsprosent(stillingsprosent) + .yrke(yrke) + .ansettelsesform(ansettelsesform) + .sistStillingsendring(LocalDate.now()) + .build())) + .build(); + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/JobbService.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/JobbService.java new file mode 100644 index 00000000000..f9f7e90cce4 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/JobbService.java @@ -0,0 +1,62 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.entity.JobbParameter; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.repository.JobberRepository; +import org.springframework.stereotype.Service; + +import java.util.*; + +/** + * Service klassen til jobberRepository + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class JobbService { + + private final JobberRepository jobberRepository; + + /** + * Henter alle parameterne i jobb_porameter db. + * @return Returnerer en liste av JobbParameterObjektene til alle parameterne + */ + public List hentAlleParametere(){ + return jobberRepository.findAll(); + + } + + /** + * Hente en spesifikk parameter i db + * @param navn Navnet til parameteren man skal hente + * @return JobbParameter objektet til parameteren. + */ + public JobbParameter hentJobbParameter(String navn){ + return jobberRepository.findByNavn(navn); + } + + /** + * Funksjon for å lage ett map av navnet og verdien til parameterne for å gjøre det lettere å bruke. + * @return ett map av JobbParameter navnet og verdier + */ + public Map hentParameterMap() { + List jobbParametere = hentAlleParametere(); + Map parameterMap = new HashMap<>(); + for (JobbParameter jobbParameterEntity : jobbParametere) { + parameterMap.put(jobbParameterEntity.getNavn(), jobbParameterEntity.getVerdi()); + } + return parameterMap; + } + + /** + * Funksjon for å oppdatere en verdi i db. + * @param jobbParameterEntity Objektet som skal oppdateres i + * @return + */ + public JobbParameter updateVerdi(JobbParameter jobbParameterEntity) { + return jobberRepository.save(jobbParameterEntity); + + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/KodeverkService.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/KodeverkService.java new file mode 100644 index 00000000000..b63754dbab8 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/KodeverkService.java @@ -0,0 +1,28 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.KodeverkServiceConsumer; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * Klasse for å hente koder fra kodeverk-service + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class KodeverkService { + private final KodeverkServiceConsumer kodeverkServiceConsumer; + + /** + * Henter koder for ett gitt kodeverk. + * @param kodeverk String som er navnet på kodeverket. + * @return En liste av String som er kodene. + */ + public List hentKodeverkValues(String kodeverk){ + return kodeverkServiceConsumer.hentKodeverk(kodeverk); + } + +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/PdlService.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/PdlService.java new file mode 100644 index 00000000000..063eccf13aa --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/PdlService.java @@ -0,0 +1,153 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.service; + +import com.fasterxml.jackson.databind.JsonNode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.PdlConsumer; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.TagsConsumer; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.TagsDTO; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl.Ident; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.pdl.SokPersonVariables; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.provider.PdlMiljoer; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +@Slf4j +@Service +@Getter +@Setter +@RequiredArgsConstructor +public class PdlService { + private final PdlConsumer pdlConsumer; + private int resultsPerPage = 100; + private String from; + private String to; + private String postnr; + private final TagsConsumer tagsConsumer; + + /** + * Lager SokPersonVariabler som matcher filterene man vil basere søket på, og henter personer fra PDL som + * oppfyller kravene. I tillegg filtreres vekk personer som er i bruk andre steder enn Testnorge + * + * @return En liste med identer for personene som matcher søk-variablene + */ + public List getPersoner() { + + var sokPersonVariables = lagSokPersonVariables( + tilfeldigPageNumber(getSokPersonPages()), + resultsPerPage, + from, + to, + postnr); + + var node = pdlConsumer.getSokPerson(sokPersonVariables.lagSokPersonPaging(), + sokPersonVariables.lagSokPersonCriteria(), + PdlMiljoer.Q2) + .block(); + + var identer = new ArrayList(); + + assert node != null; + node.get("data").get("sokPerson").findValues("identer").forEach( + hit -> hit.forEach( + ident -> { + if (ident.get("gruppe").asText().equals("FOLKEREGISTERIDENT")) { + identer.add(new Ident(ident.get("ident").asText(), ident.get("gruppe").asText())); + } + } + ) + ); + return harBareTestnorgeTags(identer); + } + + /** + * Sjekker om personene kun brukes i Testnorge + * + * @param personer Ident-liste med personer man vil sjekke + * @return En liste med Ident-objekter som oppfyller kravet + */ + private List harBareTestnorgeTags(List personer) { + + var identer = new ArrayList(); + personer.forEach(person -> identer.add(person.getIdent())); + var tagsDTO = hentTags(identer); + + for (var id : tagsDTO.getPersonerTags().entrySet()) { + List value = id.getValue(); + if (!(value.size() == 1 && value.getFirst().contains("TESTNORGE"))) { + String iden = id.getKey(); + personer.removeIf(ide -> ide.getIdent().equals(iden)); + } + } + return personer; + } + + /** + * Henter ut antall sider med ett treff per side fra PDL slik at man + * kan hente et tilfeldig sidetall å hente personer fra + * + * @return Antallet sider med kun ett treff per side fra PDL + */ + private int getSokPersonPages() { + + SokPersonVariables sokPersonVariablesEnPage = SokPersonVariables + .builder() + .pageNumber(1) + .resultsPerPage(1) + .from(from) + .to(to) + .postnr(postnr) + .build(); + JsonNode node = pdlConsumer.getSokPersonPages(sokPersonVariablesEnPage.lagSokPersonPaging(), + sokPersonVariablesEnPage.lagSokPersonCriteria(), + PdlMiljoer.Q2) + .block(); + + assert node != null; + int pages = node.get("data").get("sokPerson").findValues("totalPages").getFirst().asInt() / resultsPerPage; + return (pages == 0) ? 1 : pages; + } + + /** + * @param totalPages Maks-antall + * @return Et tilfeldig tall mellom 1 og opgitt maks-antall + */ + private int tilfeldigPageNumber(int totalPages) { + Random random = new Random(); + return random.nextInt(totalPages); + } + + /** + * Bygger et SokPersonVariables-objekt med de oppgitte parameterene som brukes til å filtrere spørringen mot PDl + * + * @param pageNumber Sidetallet resultatene skal hentes fra + * @param resultsPerPage Antall treff per side + * @param from Tidligste dato for alders-intervallet det skal søkes på + * @param to Seneste dato for alders-intervallet det skal søkes på + * @param postnr Postnummer det skal søkes på + * @return SokPersonVariables-objekt basert på parameterene + */ + private SokPersonVariables lagSokPersonVariables(int pageNumber, int resultsPerPage, String from, String to, String postnr) { + return SokPersonVariables + .builder() + .pageNumber(pageNumber) + .resultsPerPage(resultsPerPage) + .from(from) + .to(to) + .postnr(postnr) + .build(); + } + + /** + * @param identer Liste med identnummere + * @return TagsDTO for hver ident i identer-listen + */ + private TagsDTO hentTags(List identer) { + return tagsConsumer.hentTags(identer); + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/TenorService.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/TenorService.java new file mode 100644 index 00000000000..782e4138423 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/TenorService.java @@ -0,0 +1,121 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.service; + +import com.fasterxml.jackson.databind.JsonNode; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.consumers.TenorConsumer; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.dto.AdresseDTO; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.dto.OrganisasjonDTO; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.dto.OrganisasjonDetaljerDTO; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor.TenorOrganisasjonRequest; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor.TenorOversiktOrganisasjonResponse; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +import static no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.tenor.TenorOrganisasjonSelectOptions.OrganisasjonForm.BEDR; + +@Slf4j +@Service +@RequiredArgsConstructor +public class TenorService { + private final TenorConsumer tenorConsumer; + + /** + * Henter organisasjon- og postnummere fra Tenor, og bygger et OrganisasjonDTO-objekt + * med orgnummer og postnummer per organisasjon som hentes + * + * @param antall Antall organisasjoner man vil hente + * @return Returnerer en liste med OrganisasjonDTO-objekter + */ + public List hentOrganisasjoner(int antall) { + List orgNummere = hentOrgNummere(antall); + List organisasjoner = new ArrayList<>(); + orgNummere.forEach( + orgNummer -> organisasjoner.add(OrganisasjonDTO.builder() + .organisasjonsnummer(orgNummer) + .organisasjonDetaljer(OrganisasjonDetaljerDTO.builder() + .forretningsadresser(List.of(AdresseDTO.builder() + .postnummer(hentOrgPostnummer(orgNummer)) + .build())) + .build()) + .build()) + ); + return organisasjoner; + } + + /** + * + * @return TenorOrganisasjonRequest-objekt med organisasjonsform-koden "BEDR" + * for å kun hente organisasjoner som kan ha ansettelser + */ + private TenorOrganisasjonRequest lagOrganisasjonOversiktRequest() { + return TenorOrganisasjonRequest.builder() + .organisasjonsform(TenorOrganisasjonRequest.Organisasjonsform.builder() + .kode(BEDR) + .build()) + .build(); + } + + /** + * Lager et TenorOrganisasjonRequest-objekt som skal sendes til Tenor for å hente brregKildedata + * + * @param organisasjonsnummer Organisasjonsnummeret til den organisasjonen det skal lages request for + * @return TenorOrganisasjonRequest-objekt med det innsendte organisasjonsnummeret + */ + private TenorOrganisasjonRequest lagOrganisasjonRequest(String organisasjonsnummer) { + return TenorOrganisasjonRequest.builder() + .organisasjonsnummer(organisasjonsnummer) + .build(); + } + + /** + * Henter tilfeldige organisasjoner fra Tenor + * + * @param antall Antall organisasjoner som skal hentes + * @return TenorOversiktOrganisasjonResponse-objekt med tilfeldige organisasjoner fra Tenor + */ + private TenorOversiktOrganisasjonResponse hentOrganisasjonerOversikt(int antall) { + return tenorConsumer.hentOrganisasjonerOversikt(lagOrganisasjonOversiktRequest(), String.valueOf(antall)); + } + + /** + * Omgjør listen med response-objekter fra Tenor til en liste med kun de tilsvarende organisasjonsnummerne + * + * @param antall Antall organisasjoner som skal hentes + * @return Liste med organisasjonsnummere for det gitte antallet organisasjoner + */ + private List hentOrgNummere(int antall) { + List organisasjoner = hentOrganisasjonerOversikt(antall).getData().getOrganisasjoner(); + List orgNummere = new ArrayList<>(); + organisasjoner.forEach( + org -> orgNummere.add(org.getOrganisasjonsnummer()) + ); + return orgNummere; + } + + /** + * Henter all organisasjonsdata for det oppgitte organisasjonsnummeret fra Tenor, + * slik at man får tak i postnummer fra brregKildedata + * + * @param organisasjonsnummer Organisasjonsnummeret til organisasjonen man vil hente data for + * @return TenorOversiktOrganisasjonResponse-objekt med all informasjon + */ + private TenorOversiktOrganisasjonResponse hentOrganisasjon(String organisasjonsnummer) { + return tenorConsumer.hentOrganisasjon(lagOrganisasjonRequest(organisasjonsnummer)); + } + + /** + * @param organisasjonsnummer Organisasjonsnummeret til organisasjonen man vil hente postnummer for + * @return Postnummeret til organisasjonen i String-format eller null dersom brregKildedata er null + */ + public String hentOrgPostnummer(String organisasjonsnummer) { + TenorOversiktOrganisasjonResponse orgResponse = hentOrganisasjon(organisasjonsnummer); + JsonNode brregKildedata = orgResponse.getData().getOrganisasjoner().getFirst().getBrregKildedata(); + if (!brregKildedata.isNull()) { + return brregKildedata.get("forretningsadresse").get("postnummer").toString().replace("\"", ""); + } + return null; + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/util/AlderspennList.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/util/AlderspennList.java new file mode 100644 index 00000000000..be6dbdaebaf --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/util/AlderspennList.java @@ -0,0 +1,38 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.service.util; + +import lombok.Getter; +import lombok.Setter; +import no.nav.registre.testnorge.levendearbeidsforholdansettelse.domain.DatoIntervall; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +/** + * Classe for å initialere alderspennlisten for sannsynlighetsfordelingen + */ +@Getter +@Setter +public class AlderspennList { + //Dette er tallene jeg fant fra: https://www.ssb.no/arbeid-og-lonn/sysselsetting/statistikk/antall-arbeidsforhold-og-lonn + // i tabell 1 + public final List sannsynlighetFordeling = List.of(434106.0, 1022448.0, 976833.0, 563804.0, 72363.0); + private static final List> alderListe = List.of( + List.of(18, 24), + List.of(25,39), + List.of(40, 54), + List.of(55, 66), + List.of(67, 72) + ); + + + public List getDatoListe(){ + List alderspennList = new ArrayList<>(); + for(List alderSpenn :alderListe){ + alderspennList.add(DatoIntervall.builder() + .tom(LocalDate.now().minusYears(alderSpenn.getFirst())) + .from(LocalDate.now().minusYears(alderSpenn.getLast())).build()); + } + return alderspennList; + } +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/util/AliasMethod.java b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/util/AliasMethod.java new file mode 100644 index 00000000000..f9ef32b53b1 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/service/util/AliasMethod.java @@ -0,0 +1,86 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse.service.util; + +import lombok.extern.slf4j.Slf4j; + +import java.util.*; + +/** + * Alias metode for å sette opp en alias tabell, for å gjøre utrekk fra en sannsynlighetsfordeling. + * les + */ +@Slf4j +public class AliasMethod { + List sannsynlighet; + List q; + List J; + Random random; + + /** + * Metoden for å sette opp alias tabellen. + * @param prob Er listen av tall som utgjør en sannsynlighetsfordeling. Denne behøver ikke å være normalisert + */ + public AliasMethod(List prob) { + //Finne summen av sannsynlighetsfordeling for så normalisere sannsynligheten + Double sum = prob.stream().mapToDouble(i -> i).sum(); + sannsynlighet = new ArrayList<>(); + for(Double i: prob){ + sannsynlighet.add(i/sum); + } + + int size = prob.size(); + + this.q = new ArrayList<>(); + this.J = new ArrayList<>(); + + //initialisere q og j + // # TODO gjøre dette bedre + for(int i=0; i mindre = new ArrayList<>(); + List storre = new ArrayList<>(); + + //Legge til i mindre hvis q[i] er mindre enn 1 og i større hvis ikke + for (int i = 0; i < sannsynlighet.size(); i++) { + q.set(i, sannsynlighet.size() * sannsynlighet.get(i)); + if (q.get(i) < 1.0) + mindre.add(i); + else + storre.add(i); + } + while (!mindre.isEmpty() && !storre.isEmpty()) { + Integer liten = mindre.removeLast(); + Integer stor = storre.removeLast(); + + J.set(liten, stor); + q.set(stor, q.get(stor) - (1.0 - q.get(liten))); + + if (q.get(stor) < 1.0) + mindre.add(stor); + else + storre.add(stor); + + } + } + + /** + * Metode for å gjøre selve trekkingen fra alias tabellen. + * @return Returnerer indeksen fra sannsynlighetsfordelingen som har blitt trukket. + */ + public int aliasDraw() { + int k = J.size(); + int nextInt = random.nextInt(k); + + double sjekk = random.nextDouble(); + if (sjekk < q.get(nextInt)) + return nextInt; + else + return J.get(nextInt); + } +} + diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/ArbeidKodeverk b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/ArbeidKodeverk new file mode 100644 index 00000000000..01b41b6f1c8 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/ArbeidKodeverk @@ -0,0 +1,28 @@ +export enum ArbeidKodeverk { + Yrker = 'Yrker', + Arbeidstidsordninger = 'Arbeidstidsordninger', + Arbeidsforholdstyper = 'Arbeidsforholdstyper', + Avloenningstyper = 'Avlønningstyper', + PermisjonsOgPermitteringsBeskrivelse = 'PermisjonsOgPermitteringsBeskrivelse', + SluttaarsakAareg = 'SluttårsakAareg', + AnsettelsesformAareg = 'AnsettelsesformAareg', + Skipsregistre = 'Skipsregistre', + Skipstyper = 'Skipstyper', + Fartsomraader = 'Fartsområder', + Valutaer = 'Valutaer', +}nais login + +gcp: + sqlInstances: + - type: POSTGRES_14 + name: testnav-levende-arbeidsforhold-ansettelse + databases: + - name: ansettelse-jobber + autoBackupHour: 3 #Lager backup av hele SQL instancen hver dag kl 03:00 + tier: db-f1-micro + diskAutoresize: true #Kanskje ikke nødvendig? + #collation: DESC + + url: jdbc:postgresql://${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_ANSETTELSE_LEVENDE_ARBEIDSFORHOLD_DB_HOST}:${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_ANSETTELSE_LEVENDE_ARBEIDSFORHOLD_DB_PORT}/${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_ANSETTELSE_LEVENDE_ARBEIDSFORHOLD_DB_DATABASE}?user=${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_ANSETTELSE_LEVENDE_ARBEIDSFORHOLD_DB_USERNAME}&password=${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_ANSETTELSE_LEVENDE_ARBEIDSFORHOLD_DB_PASSWORD}&sslcert=${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_ANSETTELSE_LEVENDE_ARBEIDSFORHOLD_DB_SSLCERT} + +{andreSkift=Andre skift, skift365=Skiftarbeid (36,5 t/u), ikkeSkift=Ikke skift, offshore336=Arbeid offshore (33,6 t/u), doegnkontinuerligSkiftOgTurnus355=Døgnkontinuerlig skiftarbeid og turnusarbeid (35,5 t/u), helkontinuerligSkiftOgAndreOrdninger336=Helkontinuerlig skiftarbeid og andre ordninger med 33,6 t/u} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application-dev.yml b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application-dev.yml new file mode 100644 index 00000000000..22ca8e75f10 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application-dev.yml @@ -0,0 +1,45 @@ + +spring: + flyway: + enabled: true + datasource: + url: ${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_ANSETTELSE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_DB_JDBC_URL} + driverClassName: org.postgresql.Driver + hikari: + maximum-pool-size: 3 + minimum-idle: 0 + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect +consumers: + testnav-aareg-proxy: + name: testnav-aareg-proxy + namespace: dolly + url: https://testnav-aareg-proxy.dev-fss-pub.nais.io + cluster: dev-fss + testnav-ereg-proxy: + url: https://testnav-ereg-proxy.dev-fss-pub.nais.io + name: testnav-ereg-proxy + cluster: dev-fss + namespace: dolly + pdl-proxy: + url: https://testnav-pdl-proxy.dev-fss-pub.nais.io + cluster: dev-fss + namespace: dolly + name: testnav-pdl-proxy + testnav-organisasjon-faste-data-service: + url: https://testnav-organisasjon-faste-data-service.intern.dev.nav.no + name: testnav-organisasjon-faste-data-service + cluster: dev-gcp + namespace: dolly + testnav-kodeverk-service: + url: https://testnav-kodeverk-service.intern.dev.nav.no + name: testnav-kodeverk-service + cluster: dev-gcp + namespace: dolly + testnav-tenor-search-service: + url: https://testnav-tenor-search-service.intern.dev.nav.no + name: testnav-tenor-search-service + cluster: dev-gcp + namespace: dolly \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application-prod.yml b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application-prod.yml new file mode 100644 index 00000000000..63225e2440d --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application-prod.yml @@ -0,0 +1,15 @@ +spring: + datasource: + url: ${NAIS_DATABASE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_ANSETTELSE_TESTNAV_LEVENDE_ARBEIDSFORHOLD_DB_JDBC_URL} + driverClassName: org.postgresql.Driver + hikari: + maximum-pool-size: 3 + minimum-idle: 0 + flyway: + locations: classpath:db/migration + enabled: true + jpa: + database: POSTGRESQL + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application.yml b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application.yml new file mode 100644 index 00000000000..631358d959a --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/application.yml @@ -0,0 +1,66 @@ +AAD_ISSUER_URI: https://login.microsoftonline.com/62366534-1ec3-4962-8869-9b5535279d0b + +spring: + main: + banner-mode: off + application: + name: testnav-levende-arbeidsforhold-ansettelse + version: application.version.todo #TODO Finn ut hvordan denne kan settes fra Gradle + description: App for å ansette personer i en organisasjon + security: + oauth2: + resourceserver: + aad: + issuer-uri: ${AAD_ISSUER_URI}/v2.0 + jwk-set-uri: ${AAD_ISSUER_URI}/discovery/v2.0/keys + accepted-audience: ${azure.app.client.id}, api://${azure.app.client.id} + cloud: + vault: + enabled: false +springdoc: + swagger-ui: + disable-swagger-default-url: true + url: /v3/api-docs + +management: + endpoints: + enabled-by-default: true + web: + base-path: /internal + exposure.include: prometheus,heapdump,health + path-mapping: + prometheus: metrics + endpoint: + prometheus.enabled: true + heapdump.enabled: true + prometheus: + metrics: + export: + enabled: true +server: + servlet: + encoding: + charset: UTF-8 + error: + include-message: always +consumers: + testnav-aareg-proxy: + name: testnav-aareg-proxy + namespace: dolly + url: https://testnav-aareg-proxy.dev-fss-pub.nais.io + cluster: dev-fss + pdl-proxy: + url: https://testnav-pdl-proxy.dev-fss-pub.nais.io + cluster: dev-fss + namespace: dolly + name: testnav-pdl-proxy + testnav-kodeverk-service: + url: http://testnav-kodeverk-service.dolly.svc.cluster.local + name: testnav-kodeverk-service + cluster: dev-gcp + namespace: dolly + testnav-tenor-search-service: + url: http://testnav-tenor-search-service.dolly.svc.cluster.local + name: testnav-tenor-search-service + cluster: dev-gcp + namespace: dolly diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/db/migration/V1.0.0_CreateTables.sql b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/db/migration/V1.0.0_CreateTables.sql new file mode 100644 index 00000000000..1e187553273 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/db/migration/V1.0.0_CreateTables.sql @@ -0,0 +1,19 @@ +------------------------------- +-- C R E A T E T A B L E S -- +------------------------------- +DO +$$ +BEGIN + grant all privileges on table jobb_parameter to cloudsqliamuser; + grant all privileges on table verdier to cloudsqliamuser; + grant all privileges on table jobb_parameter to "testnav-levende-arbeidsforhold-ansettelse"; + grant all privileges on table verdier to "testnav-levende-arbeidsforhold-ansettelse"; +END +$$; + +CREATE TABLE IF NOT EXISTS jobb_parameter ( + navn VARCHAR(255) NOT NULL PRIMARY KEY , + tekst VARCHAR(255) NOT NULL, + verdi VARCHAR(255), + verdier text[] +); \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/logback-spring.xml b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/logback-spring.xml new file mode 100644 index 00000000000..9583ff2d427 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/logback-spring.xml @@ -0,0 +1,40 @@ + + + + + + + true + 256 + 10280 + 20 + ^sun\.reflect\..*\.invoke + ^net\.sf\.cglib\.proxy\.MethodProxy\.invoke + java\.util\.concurrent\..* + org\.apache\.catalina\..* + org\.apache\.coyote\..* + org\.apache\.tomcat\..* + + + + + + + + + + + + + %d{HH:mm:ss.SSS} | %5p | %logger{25} | %m%n + + utf8 + + + + + + + + + \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/graphql.config.yml b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/graphql.config.yml new file mode 100644 index 00000000000..1f9a7cdf2a6 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/graphql.config.yml @@ -0,0 +1,8 @@ +schema: pdl-api-schema.graphql +extensions: + endpoints: + PDL GraphQL Endpoint: + url: https://pdl-api.dev.intern.nav.no/graphql + headers: + user-agent: '' + introspect: false diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/pdl-api-schema.graphql b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/pdl-api-schema.graphql new file mode 100644 index 00000000000..d0209854938 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/pdl-api-schema.graphql @@ -0,0 +1,943 @@ +# This file was generated. Do not edit manually. + +schema { + query: Query +} + +"Indicates an Input Object is a OneOf Input Object." +directive @oneOf on INPUT_OBJECT + +type AdresseCompletionResult { + addressFound: CompletionAdresse + suggestions: [String!]! +} + +type AdresseSearchHit { + matrikkeladresse: MatrikkeladresseResult + score: Float + vegadresse: VegadresseResult +} + +type AdresseSearchResult { + hits: [AdresseSearchHit!]! + pageNumber: Int + totalHits: Int + totalPages: Int +} + +type Adressebeskyttelse { + folkeregistermetadata: Folkeregistermetadata + gradering: AdressebeskyttelseGradering! + metadata: Metadata! +} + +type Bostedsadresse { + angittFlyttedato: Date + coAdressenavn: String + folkeregistermetadata: Folkeregistermetadata + gyldigFraOgMed: DateTime + gyldigTilOgMed: DateTime + matrikkeladresse: Matrikkeladresse + metadata: Metadata! + ukjentBosted: UkjentBosted + utenlandskAdresse: UtenlandskAdresse + vegadresse: Vegadresse +} + +type CompletionAdresse { + matrikkeladresse: MatrikkeladresseResult + vegadresse: VegadresseResult +} + +type DeltBosted { + coAdressenavn: String + folkeregistermetadata: Folkeregistermetadata! + matrikkeladresse: Matrikkeladresse + metadata: Metadata! + sluttdatoForKontrakt: Date + startdatoForKontrakt: Date! + ukjentBosted: UkjentBosted + utenlandskAdresse: UtenlandskAdresse + vegadresse: Vegadresse +} + +type DoedfoedtBarn { + dato: Date + folkeregistermetadata: Folkeregistermetadata! + metadata: Metadata! +} + +type Doedsfall { + doedsdato: Date + folkeregistermetadata: Folkeregistermetadata + metadata: Metadata! +} + +" Endring som har blitt utført på opplysningen. F.eks: Opprett -> Korriger -> Korriger" +type Endring { + hendelseId: String! + """ + + Opphavet til informasjonen. I NAV blir dette satt i forbindelse med registrering (f.eks: Sykehuskassan). + Fra Folkeregisteret får vi opphaven til dems opplysning, altså NAV, UDI, Politiet, Skatteetaten o.l.. Fra Folkeregisteret kan det også være tekniske navn som: DSF_MIGRERING, m.m.. + """ + kilde: String! + " Tidspunktet for registrering." + registrert: DateTime! + " Hvem endringen har blitt utført av, ofte saksbehandler (f.eks Z990200), men kan også være system (f.eks srvXXXX). Denne blir satt til \"Folkeregisteret\" for det vi får fra dem." + registrertAv: String! + " Hvilke system endringen har kommet fra (f.eks srvXXX). Denne blir satt til \"FREG\" for det vi får fra Folkeregisteret." + systemkilde: String! + " Hvilke type endring som har blitt utført." + type: Endringstype! +} + +type FalskIdentitet { + erFalsk: Boolean! + folkeregistermetadata: Folkeregistermetadata + metadata: Metadata! + rettIdentitetErUkjent: Boolean + rettIdentitetVedIdentifikasjonsnummer: String + rettIdentitetVedOpplysninger: FalskIdentitetIdentifiserendeInformasjon +} + +type FalskIdentitetIdentifiserendeInformasjon { + foedselsdato: Date + kjoenn: KjoennType + personnavn: Personnavn! + statsborgerskap: [String!]! +} + +type Foedested { + foedekommune: String + foedeland: String + foedested: String + folkeregistermetadata: Folkeregistermetadata + metadata: Metadata! +} + +type Foedsel { + foedekommune: String + foedeland: String + foedested: String + foedselsaar: Int + foedselsdato: Date + folkeregistermetadata: Folkeregistermetadata + metadata: Metadata! +} + +type Foedselsdato { + foedselsaar: Int + foedselsdato: Date + folkeregistermetadata: Folkeregistermetadata + metadata: Metadata! +} + +type Folkeregisteridentifikator { + folkeregistermetadata: Folkeregistermetadata! + identifikasjonsnummer: String! + metadata: Metadata! + status: String! + type: String! +} + +type Folkeregistermetadata { + aarsak: String + ajourholdstidspunkt: DateTime + gyldighetstidspunkt: DateTime + kilde: String + opphoerstidspunkt: DateTime + sekvens: Int +} + +type Folkeregisterpersonstatus { + folkeregistermetadata: Folkeregistermetadata! + forenkletStatus: String! + metadata: Metadata! + status: String! +} + +type ForelderBarnRelasjon { + folkeregistermetadata: Folkeregistermetadata + metadata: Metadata! + minRolleForPerson: ForelderBarnRelasjonRolle + relatertPersonUtenFolkeregisteridentifikator: RelatertBiPerson + relatertPersonsIdent: String + relatertPersonsRolle: ForelderBarnRelasjonRolle! +} + +type Foreldreansvar { + ansvar: String + ansvarlig: String + ansvarligUtenIdentifikator: RelatertBiPerson + ansvarssubjekt: String + folkeregistermetadata: Folkeregistermetadata + metadata: Metadata! +} + +type Fullmakt { + gyldigFraOgMed: Date! + gyldigTilOgMed: Date! + metadata: Metadata! + motpartsPersonident: String! + motpartsRolle: FullmaktsRolle! + omraader: [String!]! +} + +type GeografiskTilknytning { + gtBydel: String + gtKommune: String + gtLand: String + gtType: GtType! + regel: String! +} + +type HentIdenterBolkResult { + code: String! + ident: String! + identer: [IdentInformasjon!] +} + +type HentPersonBolkResult { + code: String! + ident: String! + person: Person +} + +type IdentInformasjon { + gruppe: IdentGruppe! + historisk: Boolean! + ident: String! +} + +type IdentifiserendeInformasjon { + foedselsdato: Date + kjoenn: String + navn: Personnavn + statsborgerskap: [String!] +} + +type Identitetsgrunnlag { + folkeregistermetadata: Folkeregistermetadata! + metadata: Metadata! + status: Identitetsgrunnlagsstatus! +} + +type Identliste { + identer: [IdentInformasjon!]! +} + +type InnflyttingTilNorge { + folkeregistermetadata: Folkeregistermetadata + fraflyttingsland: String + fraflyttingsstedIUtlandet: String + metadata: Metadata! +} + +type KartverketAdresse { + id: Long! + matrikkeladresse: KartverketMatrikkeladresse + vegadresse: KartverketVegadresse +} + +type KartverketBydel { + bydelsnavn: String + bydelsnummer: String +} + +type KartverketFylke { + navn: String + nummer: String +} + +type KartverketGrunnkrets { + grunnkretsnavn: String + grunnkretsnummer: String +} + +type KartverketKommune { + fylke: KartverketFylke + navn: String + nummer: String +} + +type KartverketMatrikkeladresse { + adressetilleggsnavn: String + bydel: KartverketBydel + grunnkrets: KartverketGrunnkrets + kortnavn: String + matrikkelnummer: KartverketMatrikkelnummer + postnummeromraade: KartverketPostnummeromraade + representasjonspunkt: KartverketRepresentasjonspunkt + undernummer: Int +} + +type KartverketMatrikkelnummer { + bruksnummer: Int + festenummer: Int + gaardsnummer: Int + kommunenummer: String + seksjonsnummer: Int +} + +type KartverketPostnummeromraade { + postnummer: String + poststed: String +} + +type KartverketRepresentasjonspunkt { + posisjonskvalitet: Int + x: Float + y: Float + z: Float +} + +type KartverketVeg { + adressekode: Int + adressenavn: String + kommune: KartverketKommune + kortnavn: String + stedsnummer: String +} + +type KartverketVegadresse { + adressetilleggsnavn: String + bokstav: String + bydel: KartverketBydel + grunnkrets: KartverketGrunnkrets + kortnavn: String + nummer: Int + postnummeromraade: KartverketPostnummeromraade + representasjonspunkt: KartverketRepresentasjonspunkt + veg: KartverketVeg +} + +type Kjoenn { + folkeregistermetadata: Folkeregistermetadata + kjoenn: KjoennType + metadata: Metadata! +} + +type Kontaktadresse { + coAdressenavn: String + folkeregistermetadata: Folkeregistermetadata + gyldigFraOgMed: DateTime + gyldigTilOgMed: DateTime + metadata: Metadata! + postadresseIFrittFormat: PostadresseIFrittFormat + postboksadresse: Postboksadresse + type: KontaktadresseType! + utenlandskAdresse: UtenlandskAdresse + utenlandskAdresseIFrittFormat: UtenlandskAdresseIFrittFormat + vegadresse: Vegadresse +} + +type KontaktinformasjonForDoedsbo { + adresse: KontaktinformasjonForDoedsboAdresse! + advokatSomKontakt: KontaktinformasjonForDoedsboAdvokatSomKontakt + attestutstedelsesdato: Date! + folkeregistermetadata: Folkeregistermetadata! + metadata: Metadata! + organisasjonSomKontakt: KontaktinformasjonForDoedsboOrganisasjonSomKontakt + personSomKontakt: KontaktinformasjonForDoedsboPersonSomKontakt + skifteform: KontaktinformasjonForDoedsboSkifteform! +} + +type KontaktinformasjonForDoedsboAdresse { + adresselinje1: String! + adresselinje2: String + landkode: String + postnummer: String! + poststedsnavn: String! +} + +type KontaktinformasjonForDoedsboAdvokatSomKontakt { + organisasjonsnavn: String + organisasjonsnummer: String + personnavn: Personnavn! +} + +type KontaktinformasjonForDoedsboOrganisasjonSomKontakt { + kontaktperson: Personnavn + organisasjonsnavn: String! + organisasjonsnummer: String +} + +type KontaktinformasjonForDoedsboPersonSomKontakt { + foedselsdato: Date + identifikasjonsnummer: String + personnavn: Personnavn +} + +type Koordinater { + kvalitet: Int + x: Float + y: Float + z: Float +} + +type Matrikkeladresse { + bruksenhetsnummer: String + kommunenummer: String + koordinater: Koordinater + matrikkelId: Long + postnummer: String + tilleggsnavn: String +} + +type MatrikkeladresseResult { + bruksnummer: String + gaardsnummer: String + kommunenummer: String + matrikkelId: String + postnummer: String + poststed: String + tilleggsnavn: String +} + +type Metadata { + """ + + En liste over alle endringer som har blitt utført over tid. + Vær obs på at denne kan endre seg og man burde takle at det finnes flere korrigeringer i listen, så dersom man ønsker å kun vise den siste, så må man selv filtrere ut dette. + Det kan også ved svært få tilfeller skje at opprett blir fjernet. F.eks ved splitt tilfeller av identer. Dette skal skje i svært få tilfeller. Dersom man ønsker å presentere opprettet tidspunktet, så blir det tidspunktet på den første endringen. + """ + endringer: [Endring!]! + """ + + Feltet betegner hvorvidt dette er en funksjonelt historisk opplysning, for eksempel en tidligere fraflyttet adresse eller et foreldreansvar som er utløpt fordi barnet har fylt 18 år. + I de fleste tilfeller kan dette utledes ved å se på de andre feltene i opplysningen. Dette er imidlertid ikke alltid tilfellet, blant annet for foreldreansvar. + Feltet bør brukes av konsumenter som henter informasjon fra GraphQL med historikk, men som også trenger å utlede gjeldende informasjon. + """ + historisk: Boolean! + " Master refererer til hvem som eier opplysningen, f.eks så har PDL en kopi av Folkeregisteret, da vil master være FREG og eventuelle endringer på dette må gå via Folkeregisteret (API mot dem eller andre rutiner)." + master: String! + """ + + I PDL så får alle forekomster av en opplysning en ID som representerer dens unike forekomst. + F.eks, så vil en Opprett ha ID X, korriger ID Y (der hvor den spesifiserer at den korrigerer X). + Dersom en opplysning ikke er lagret i PDL, så vil denne verdien ikke være utfylt. + """ + opplysningsId: String +} + +type Navn { + etternavn: String! + folkeregistermetadata: Folkeregistermetadata + forkortetNavn: String @deprecated(reason: "No longer supported") + fornavn: String! + gyldigFraOgMed: Date + mellomnavn: String + metadata: Metadata! + originaltNavn: OriginaltNavn +} + +type Opphold { + folkeregistermetadata: Folkeregistermetadata! + metadata: Metadata! + oppholdFra: Date + oppholdTil: Date + type: Oppholdstillatelse! +} + +type Oppholdsadresse { + coAdressenavn: String + folkeregistermetadata: Folkeregistermetadata + gyldigFraOgMed: DateTime + gyldigTilOgMed: DateTime + matrikkeladresse: Matrikkeladresse + metadata: Metadata! + oppholdAnnetSted: String + utenlandskAdresse: UtenlandskAdresse + vegadresse: Vegadresse +} + +type OriginaltNavn { + etternavn: String + fornavn: String + mellomnavn: String +} + +type Person { + adressebeskyttelse(historikk: Boolean = false): [Adressebeskyttelse!]! + bostedsadresse(historikk: Boolean = false): [Bostedsadresse!]! + deltBosted(historikk: Boolean = false): [DeltBosted!]! + doedfoedtBarn: [DoedfoedtBarn!]! + doedsfall: [Doedsfall!]! + falskIdentitet: FalskIdentitet + foedested: [Foedested!]! + foedsel: [Foedsel!]! @deprecated(reason: "Erstattet av foedselsdato & foedested") + foedselsdato: [Foedselsdato!]! + folkeregisteridentifikator(historikk: Boolean = false): [Folkeregisteridentifikator!]! + folkeregisterpersonstatus(historikk: Boolean = false): [Folkeregisterpersonstatus!]! + forelderBarnRelasjon: [ForelderBarnRelasjon!]! + foreldreansvar(historikk: Boolean = false): [Foreldreansvar!]! + fullmakt(historikk: Boolean = false): [Fullmakt!]! + identitetsgrunnlag(historikk: Boolean = false): [Identitetsgrunnlag!]! + innflyttingTilNorge: [InnflyttingTilNorge!]! + kjoenn(historikk: Boolean = false): [Kjoenn!]! + kontaktadresse(historikk: Boolean = false): [Kontaktadresse!]! + kontaktinformasjonForDoedsbo(historikk: Boolean = false): [KontaktinformasjonForDoedsbo!]! + navn(historikk: Boolean = false): [Navn!]! + opphold(historikk: Boolean = false): [Opphold!]! + oppholdsadresse(historikk: Boolean = false): [Oppholdsadresse!]! + rettsligHandleevne(historikk: Boolean = false): [RettsligHandleevne!]! + sikkerhetstiltak: [Sikkerhetstiltak!]! + sivilstand(historikk: Boolean = false): [Sivilstand!]! + statsborgerskap(historikk: Boolean = false): [Statsborgerskap!]! + telefonnummer(historikk: Boolean = false): [Telefonnummer!]! + tilrettelagtKommunikasjon: [TilrettelagtKommunikasjon!]! + utenlandskIdentifikasjonsnummer(historikk: Boolean = false): [UtenlandskIdentifikasjonsnummer!]! + utflyttingFraNorge: [UtflyttingFraNorge!]! + vergemaalEllerFremtidsfullmakt(historikk: Boolean = false): [VergemaalEllerFremtidsfullmakt!]! +} + +type PersonSearchHighlight { + " Forteller hvorvidt opplysningen som ga treff er markert som historisk." + historisk: Boolean + """ + + liste med feltene og verdiene som ga treff. + Merk at for fritekst søk så vil disse kunne referere til hjelpe felter som ikke er synelig i resultatene. + """ + matches: [SearchMatch] + """ + + Navn/Sti til opplysningen som ga treff. Merk at dette ikke er feltet som ga treff men opplysningen. + F.eks. hvis du søker på person.navn.fornavn så vil opplysingen være person.navn. + """ + opplysning: String + """ + + Gitt att opplysningen som ga treff har en opplysningsId så vil den returneres her. + alle søk under person skal ha opplysningsId, men søk i identer vil kunne returnere treff uten opplysningsId. + """ + opplysningsId: String +} + +type PersonSearchHit { + " Infromasjon om hva som ga treff i søke resultatet." + highlights: [PersonSearchHighlight] + " forespurte data" + identer(historikk: Boolean = false): [IdentInformasjon!]! + " forespurte data" + person: Person + " Poengsummen elasticsearch har gitt dette resultatet (brukt til feilsøking, og tuning av søk)" + score: Float +} + +type PersonSearchResult { + " treff liste" + hits: [PersonSearchHit!]! + " Side nummer for siden som vises" + pageNumber: Int + " Totalt antall treff (øvre grense er satt til 10 000)" + totalHits: Int + " Totalt antall sider" + totalPages: Int +} + +type Personnavn { + etternavn: String! + fornavn: String! + mellomnavn: String +} + +type PostadresseIFrittFormat { + adresselinje1: String + adresselinje2: String + adresselinje3: String + postnummer: String +} + +type Postboksadresse { + postboks: String! + postbokseier: String + postnummer: String +} + +type Query { + forslagAdresse(parameters: CompletionParameters): AdresseCompletionResult + hentAdresse(matrikkelId: ID!): KartverketAdresse + hentGeografiskTilknytning(ident: ID!): GeografiskTilknytning + hentGeografiskTilknytningBolk(identer: [ID!]!): [hentGeografiskTilknytningBolkResult!]! + hentIdenter(grupper: [IdentGruppe!], historikk: Boolean = false, ident: ID!): Identliste + hentIdenterBolk(grupper: [IdentGruppe!], historikk: Boolean = false, identer: [ID!]!): [HentIdenterBolkResult!]! + hentPerson(ident: ID!): Person + hentPersonBolk(identer: [ID!]!): [HentPersonBolkResult!]! + sokAdresse(criteria: [Criterion], paging: Paging): AdresseSearchResult + sokPerson(criteria: [Criterion], paging: Paging): PersonSearchResult +} + +type RelatertBiPerson { + foedselsdato: Date + kjoenn: KjoennType + navn: Personnavn + statsborgerskap: String +} + +type RettsligHandleevne { + folkeregistermetadata: Folkeregistermetadata + metadata: Metadata! + rettsligHandleevneomfang: String +} + +type SearchMatch { + " feltnavn med sti til feltet so ga treff." + field: String! + " Verdien som ga treff" + fragments: [String] + type: String +} + +type Sikkerhetstiltak { + beskrivelse: String! + gyldigFraOgMed: Date! + gyldigTilOgMed: Date! + kontaktperson: SikkerhetstiltakKontaktperson + metadata: Metadata! + tiltakstype: String! +} + +type SikkerhetstiltakKontaktperson { + enhet: String! + personident: String! +} + +type Sivilstand { + bekreftelsesdato: Date + folkeregistermetadata: Folkeregistermetadata + gyldigFraOgMed: Date + metadata: Metadata! + relatertVedSivilstand: String + type: Sivilstandstype! +} + +type Statsborgerskap { + bekreftelsesdato: Date + folkeregistermetadata: Folkeregistermetadata + gyldigFraOgMed: Date + gyldigTilOgMed: Date + land: String! + metadata: Metadata! +} + +type Telefonnummer { + landskode: String! + metadata: Metadata! + nummer: String! + prioritet: Int! +} + +type TilrettelagtKommunikasjon { + metadata: Metadata! + talespraaktolk: Tolk + tegnspraaktolk: Tolk +} + +type Tjenesteomraade { + tjenesteoppgave: String + tjenestevirksomhet: String +} + +type Tolk { + spraak: String +} + +type UkjentBosted { + bostedskommune: String +} + +type UtenlandskAdresse { + adressenavnNummer: String + bySted: String + bygningEtasjeLeilighet: String + landkode: String! + postboksNummerNavn: String + postkode: String + regionDistriktOmraade: String +} + +type UtenlandskAdresseIFrittFormat { + adresselinje1: String + adresselinje2: String + adresselinje3: String + byEllerStedsnavn: String + landkode: String! + postkode: String +} + +type UtenlandskIdentifikasjonsnummer { + folkeregistermetadata: Folkeregistermetadata + identifikasjonsnummer: String! + metadata: Metadata! + opphoert: Boolean! + utstederland: String! +} + +type UtflyttingFraNorge { + folkeregistermetadata: Folkeregistermetadata + metadata: Metadata! + tilflyttingsland: String + tilflyttingsstedIUtlandet: String + utflyttingsdato: Date +} + +type Vegadresse { + adressenavn: String + bruksenhetsnummer: String + bydelsnummer: String + husbokstav: String + husnummer: String + kommunenummer: String + koordinater: Koordinater + matrikkelId: Long + postnummer: String + tilleggsnavn: String +} + +type VegadresseResult { + adressekode: String + adressenavn: String + bydelsnavn: String + bydelsnummer: String + fylkesnavn: String + fylkesnummer: String + husbokstav: String + husnummer: Int + kommunenavn: String + kommunenummer: String + matrikkelId: String + postnummer: String + poststed: String + tilleggsnavn: String +} + +type VergeEllerFullmektig { + identifiserendeInformasjon: IdentifiserendeInformasjon + motpartsPersonident: String + navn: Personnavn @deprecated(reason: "Erstattes av navn iidentifiserendeInformasjon") + omfang: String + omfangetErInnenPersonligOmraade: Boolean + tjenesteomraade: [Tjenesteomraade!] +} + +type VergemaalEllerFremtidsfullmakt { + embete: String + folkeregistermetadata: Folkeregistermetadata + metadata: Metadata! + type: String + vergeEllerFullmektig: VergeEllerFullmektig! +} + +type hentGeografiskTilknytningBolkResult { + code: String! + geografiskTilknytning: GeografiskTilknytning + ident: String! +} + +enum AdressebeskyttelseGradering { + FORTROLIG + STRENGT_FORTROLIG + STRENGT_FORTROLIG_UTLAND + UGRADERT +} + +enum Direction { + ASC + DESC +} + +enum Endringstype { + KORRIGER + OPPHOER + OPPRETT +} + +enum Familierelasjonsrolle { + BARN + FAR + MEDMOR + MOR +} + +enum ForelderBarnRelasjonRolle { + BARN + FAR + MEDMOR + MOR +} + +enum FullmaktsRolle { + FULLMAKTSGIVER + FULLMEKTIG +} + +enum GtType { + BYDEL + KOMMUNE + UDEFINERT + UTLAND +} + +enum IdentGruppe { + AKTORID + FOLKEREGISTERIDENT + NPID +} + +enum Identitetsgrunnlagsstatus { + IKKE_KONTROLLERT + INGEN_STATUS + KONTROLLERT +} + +enum KjoennType { + KVINNE + MANN + UKJENT +} + +enum KontaktadresseType { + Innland + Utland +} + +enum KontaktinformasjonForDoedsboSkifteform { + ANNET + OFFENTLIG +} + +enum Oppholdstillatelse { + MIDLERTIDIG + OPPLYSNING_MANGLER + PERMANENT +} + +enum Sivilstandstype { + ENKE_ELLER_ENKEMANN + GIFT + GJENLEVENDE_PARTNER + REGISTRERT_PARTNER + SEPARERT + SEPARERT_PARTNER + SKILT + SKILT_PARTNER + UGIFT + UOPPGITT +} + +"Format: YYYY-MM-DD (ISO-8601), example: 2017-11-24" +scalar Date + +"Format: YYYY-MM-DDTHH:mm:SS (ISO-8601), example: 2011-12-03T10:15:30" +scalar DateTime + +"A 64-bit signed integer" +scalar Long + +input CompletionFieldValue { + fieldName: String! + fieldValue: String +} + +input CompletionParameters { + completionField: String! + fieldValues: [CompletionFieldValue]! + maxSuggestions: Int +} + +input Criterion { + and: [Criterion] + " Feltnavn inkludert sti til ønsket felt (Eksempel: person.navn.fornavn)" + fieldName: String + not: [Criterion] + or: [Criterion] + """ + + Søk i historiske data + true = søker kun i historiske data. + false = søker kun i gjeldende data. + null = søke i både historiske og gjeldende data. + """ + searchHistorical: Boolean + searchRule: SearchRule +} + +input Paging { + " Hvilken side i resultatsettet man ønsker vist." + pageNumber: Int = 1 + " antall treff per side (maks 100)" + resultsPerPage: Int = 10 + """ + + Liste over felter man ønsker resultatene sortert etter + Standard er "score". Score er poengsummen Elasticsearch tildeler hvert resultat. + """ + sortBy: [SearchSorting] +} + +input SearchRule { + " Brukes til søke etter datoer som kommer etter opgitt dato." + after: String + " Brukes til søke etter datoer som kommer før opgitt dato." + before: String + " Boost brukes til å gi ett søkekriterie høyere eller lavere vektlegging en de andre søke kriteriene." + boost: Float + " [Flag] Kan brukes til å overstyre standard oppførsellen for søk i felter (standard er case insensitive)" + caseSensitive: Boolean + " Gir treff når opgitt felt inneholder en eller flere ord fra input verdien." + contains: String + " [Flag] Brukes til å deaktivere fonetisk søk feltene som har dette som standard (Navn)" + disablePhonetic: Boolean + " Begrenser treff til kun de hvor felt har input verdi" + equals: String + " Sjekker om feltet finnes / at det ikke har en null verdi." + exists: String + """ + + Søk fra og med (se fromExcluding for bare fra men ikke med) + kan benyttes på tall og dato + """ + from: String + """ + + Søk fra men ikke med oppgitt verdi + kan benyttes på tall og dato + """ + fromExcluding: String + " Søk som gir treff også for små variasjoner i skrivemåte" + fuzzy: String + " Brukes til å søke i tall og finner verdier som er størren en input verdi." + greaterThan: String + " Brukes til å søke i tall og finner verdier som er mindre en input verdi." + lessThan: String + " Filtrerer bort treff hvor felt inneholder input verdi" + notEquals: String + " Søk som gir tilfeldig poengsum til hvert treff (kun ment til generering av testdata)" + random: String + " Regex søk for spesielle situasjoner (Dette er en treg opprasjon og bør ikke brukes)" + regex: String + " Gir treff når opgitt feltstarter med opgitt verdi." + startsWith: String + """ + + Søk til og med (se toExcluding for bare til men ikke med) + kan benyttes på tall og dato + """ + to: String + """ + + Søk til men ikke med oppgitt verdi + kan benyttes på tall og dato + """ + toExcluding: String + " Bruk \"?\" som wildcard for enkelt tegn, og \"*\" som wildcard for 0 eller flere tegn." + wildcard: String +} + +input SearchSorting { + direction: Direction! + " Feltnavn ikludert sti til ønsket felt (eksepmel: person.navn.fornavn)" + fieldName: String! +} diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/sokPerson.graphql b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/sokPerson.graphql new file mode 100644 index 00000000000..180aa5b1af7 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/sokPerson.graphql @@ -0,0 +1,38 @@ +query($paging: Paging, $criteria: [Criterion]) { + sokPerson(paging: $paging, criteria: $criteria) { + hits { + identer { + ident + gruppe + } + person { + navn(historikk: false) { + fornavn + etternavn + mellomnavn + } + foedselsdato { + foedselsaar + } + bostedsadresse { + vegadresse{ + matrikkelId + adressenavn + husnummer + husbokstav + postnummer + } + } + oppholdsadresse{ + vegadresse{ + matrikkelId + adressenavn + husnummer + husbokstav + postnummer + } + } + } + } + } +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/sokPersonPages.graphql b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/sokPersonPages.graphql new file mode 100644 index 00000000000..f22e299e8ea --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/main/resources/pdl/sokPersonPages.graphql @@ -0,0 +1,11 @@ +query($paging: Paging, $criteria: [Criterion]) { + sokPerson(paging: $paging, criteria: $criteria) { + totalPages + hits { + identer { + ident + gruppe + } + } + } +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-ansettelse/src/test/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/LevendeArbeidsforholdAnsettelseApplicationTests.java b/apps/levende-arbeidsforhold-ansettelse/src/test/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/LevendeArbeidsforholdAnsettelseApplicationTests.java new file mode 100644 index 00000000000..e92f6371d26 --- /dev/null +++ b/apps/levende-arbeidsforhold-ansettelse/src/test/java/no/nav/registre/testnorge/levendearbeidsforholdansettelse/LevendeArbeidsforholdAnsettelseApplicationTests.java @@ -0,0 +1,19 @@ +package no.nav.registre.testnorge.levendearbeidsforholdansettelse; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder; + +@SpringBootTest +class LevendeArbeidsforholdAnsettelseApplicationTests { + + @MockBean + public ReactiveJwtDecoder jwtDecoder; + + @Test + @SuppressWarnings("java:S2699") + void load_app_context() { + } + +} diff --git a/apps/levende-arbeidsforhold-scheduler/.gitignore b/apps/levende-arbeidsforhold-scheduler/.gitignore new file mode 100644 index 00000000000..c2065bc2620 --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/.gitignore @@ -0,0 +1,37 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ diff --git a/apps/levende-arbeidsforhold-scheduler/Dockerfile b/apps/levende-arbeidsforhold-scheduler/Dockerfile new file mode 100644 index 00000000000..4a36f93546f --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/Dockerfile @@ -0,0 +1,8 @@ +FROM ghcr.io/navikt/baseimages/temurin:21 +LABEL maintainer="Team Dolly" + +ENV JAVA_OPTS="-Dspring.profiles.active=prod" + +ADD /build/libs/app.jar /app/app.jar + +EXPOSE 8080 diff --git a/apps/levende-arbeidsforhold-scheduler/build.gradle b/apps/levende-arbeidsforhold-scheduler/build.gradle new file mode 100644 index 00000000000..816d6d2667a --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/build.gradle @@ -0,0 +1,87 @@ +plugins { + id 'java' + id "org.sonarqube" version "5.0.0.4638" + id 'org.springframework.boot' version "3.2.6" + id 'io.spring.dependency-management' version "1.1.5" + id "jacoco" +} + +test { + useJUnitPlatform() +} + +sonarqube { + properties { + property "sonar.dynamicAnalysis", "reuseReports" + property "sonar.host.url", "https://sonarcloud.io" + property "sonar.java.coveragePlugin", "jacoco" + property "sonar.language", "java" + property "sonar.token", System.getenv("SONAR_TOKEN") + property "sonar.organization", "navikt" + property "sonar.project.monorepo.enabled", true + property "sonar.projectKey", "testnav-levende-arbeidsforhold-scheduler" + property "sonar.projectName", "testnav-levende-arbeidsforhold-scheduler" + property "sonar.sourceEncoding", "UTF-8" + } +} +bootJar { + archiveFileName = "app.jar" +} + +dependencyManagement { + applyMavenExclusions = false + imports { + mavenBom 'org.springframework.cloud:spring-cloud-dependencies:2023.0.1' + } +} + +repositories { + mavenCentral() + mavenLocal() + maven { + url = uri('https://packages.confluent.io/maven/') + } +} + +dependencies { + implementation 'no.nav.testnav.libs:security-core' + implementation 'no.nav.testnav.libs:servlet-core' + implementation 'no.nav.testnav.libs:data-transfer-objects' + implementation 'no.nav.testnav.libs:servlet-security' + implementation 'no.nav.testnav.libs:servlet-insecure-security' + + + implementation 'org.springframework.boot:spring-boot-starter-webflux' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-quartz' + implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' + implementation 'org.springframework.boot:spring-boot-starter-security' + + implementation 'org.springframework.cloud:spring-cloud-starter-vault-config' + implementation 'org.springframework.boot:spring-boot-starter-actuator' + + implementation 'io.micrometer:micrometer-registry-prometheus' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0' + implementation 'io.swagger.core.v3:swagger-annotations-jakarta:2.2.21' + + implementation 'net.logstash.logback:logstash-logback-encoder:7.4' + implementation 'org.hibernate.validator:hibernate-validator' + + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.cloud:spring-cloud-contract-wiremock' + + implementation 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + testAnnotationProcessor 'org.projectlombok:lombok' + + //Dependencies av dependencies som må ha spesifisert versjon for å ikke forårsake sikkerthets-sårbarheter + implementation 'org.apache.tomcat.embed:tomcat-embed-core:10.1.25' + implementation 'org.bouncycastle:bcprov-jdk18on:1.78' + implementation 'com.nimbusds:nimbus-jose-jwt:9.37.2' + +} +java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } +} diff --git a/apps/levende-arbeidsforhold-scheduler/config.yml b/apps/levende-arbeidsforhold-scheduler/config.yml new file mode 100644 index 00000000000..bd5d6ca759b --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/config.yml @@ -0,0 +1,47 @@ +apiVersion: nais.io/v1alpha1 +kind: Application +metadata: + name: testnav-levende-arbeidsforhold-scheduler + namespace: dolly + labels: + team: dolly +spec: + image: "{{image}}" + port: 8080 + accessPolicy: + inbound: + rules: + - application: dolly-frontend + - application: testnav-levende-arbeidsforhold-ansettelse + outbound: + rules: + - application: testnav-levende-arbeidsforhold-ansettelse + azure: + application: + allowAllUsers: true + enabled: true + tenant: nav.no + liveness: + path: /internal/isAlive + initialDelay: 4 + periodSeconds: 5 + failureThreshold: 500 + readiness: + path: /internal/isReady + initialDelay: 4 + periodSeconds: 5 + failureThreshold: 500 + prometheus: + enabled: true + path: /internal/metrics + replicas: + min: 1 + max: 1 + resources: + requests: + cpu: 200m + memory: 1024Mi + limits: + memory: 2048Mi + ingresses: + - "https://testnav-levende-arbeidsforhold-scheduler.intern.dev.nav.no" \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-scheduler/gradle/wrapper/gradle-wrapper.jar b/apps/levende-arbeidsforhold-scheduler/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..e6441136f3d4ba8a0da8d277868979cfbc8ad796 GIT binary patch literal 43453 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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
NnX)EH+Nua)3Y(c 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 '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/apps/levende-arbeidsforhold-scheduler/gradlew.bat b/apps/levende-arbeidsforhold-scheduler/gradlew.bat new file mode 100644 index 00000000000..7101f8e4676 --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/apps/levende-arbeidsforhold-scheduler/settings.gradle b/apps/levende-arbeidsforhold-scheduler/settings.gradle new file mode 100644 index 00000000000..2639ddf73a9 --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/settings.gradle @@ -0,0 +1,21 @@ +plugins { + id "com.gradle.develocity" version "3.17.4" +} + +rootProject.name = 'levende-arbeidsforhold-scheduler' + +includeBuild '../../libs/security-core' +includeBuild '../../libs/servlet-core' +includeBuild '../../libs/data-transfer-objects' +includeBuild '../../libs/servlet-security' +includeBuild '../../libs/servlet-insecure-security' +includeBuild '../../libs/testing' +includeBuild '../../.github/workflows' + + +develocity { + buildScan { + termsOfUseUrl = "https://gradle.com/terms-of-service" + termsOfUseAgree = "yes" + } +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/LevendeArbeidsforholdSchedulerApplication.java b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/LevendeArbeidsforholdSchedulerApplication.java new file mode 100644 index 00000000000..7b9e0c26026 --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/LevendeArbeidsforholdSchedulerApplication.java @@ -0,0 +1,13 @@ +package no.nav.testnav.levendearbeidsforholdscheduler; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class LevendeArbeidsforholdSchedulerApplication { + + public static void main(String[] args) { + SpringApplication.run(LevendeArbeidsforholdSchedulerApplication.class, args); + } + +} diff --git a/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/ApplicationConfig.java b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/ApplicationConfig.java new file mode 100644 index 00000000000..b97c25a3d2e --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/ApplicationConfig.java @@ -0,0 +1,17 @@ +package no.nav.testnav.levendearbeidsforholdscheduler.config; + +import no.nav.testnav.libs.servletcore.config.ApplicationCoreConfig; +import no.nav.testnav.libs.servletsecurity.config.SecureOAuth2ServerToServerConfiguration; +import no.nav.testnav.libs.standalone.servletsecurity.config.InsecureJwtServerToServerConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@Import({ + ApplicationCoreConfig.class, + InsecureJwtServerToServerConfiguration.class, + SecureOAuth2ServerToServerConfiguration.class +}) +public class ApplicationConfig { + +} diff --git a/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/Consumers.java b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/Consumers.java new file mode 100644 index 00000000000..ad7a2cd359c --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/Consumers.java @@ -0,0 +1,29 @@ +package no.nav.testnav.levendearbeidsforholdscheduler.config; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import no.nav.testnav.libs.securitycore.domain.ServerProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import static lombok.AccessLevel.PACKAGE; + +/** + * Samler alle placeholders for ulike {@code consumers.*}-konfigurasjon her, dvs. subklasser av {@code ServerProperties}. + *

+ * Husk at Spring Boot bruker
relaxed binding + * mellom configuration properties og field names. + * + * @see ServerProperties + */ +@Configuration +@ConfigurationProperties(prefix = "consumers") +@NoArgsConstructor(access = PACKAGE) +@Getter +@Setter(PACKAGE) +public class Consumers { + + private ServerProperties levendeArbeidsforholdAnsettelse; + +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/DevConfig.java b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/DevConfig.java similarity index 95% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/DevConfig.java rename to apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/DevConfig.java index a5b2cad3c88..91cb01e9e00 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/DevConfig.java +++ b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/DevConfig.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.config; +package no.nav.testnav.levendearbeidsforholdscheduler.config; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/OpenApiConfig.java b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/OpenApiConfig.java similarity index 97% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/OpenApiConfig.java rename to apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/OpenApiConfig.java index d2dc2940c31..f4bb9db4016 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/OpenApiConfig.java +++ b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/OpenApiConfig.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.config; +package no.nav.testnav.levendearbeidsforholdscheduler.config; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; @@ -7,6 +7,7 @@ import io.swagger.v3.oas.models.info.License; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; +import no.nav.testnav.libs.servletcore.config.ApplicationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; @@ -14,8 +15,6 @@ import java.util.Arrays; -import no.nav.testnav.libs.servletcore.config.ApplicationProperties; - @Configuration public class OpenApiConfig implements WebMvcConfigurer { diff --git a/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/SchedulerConfig.java b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/SchedulerConfig.java new file mode 100644 index 00000000000..b4bfb674296 --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/SchedulerConfig.java @@ -0,0 +1,16 @@ +package no.nav.testnav.levendearbeidsforholdscheduler.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; + +@Configuration +public class SchedulerConfig { + + @Bean + public ScheduledExecutorService taskScheduler() { + return Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors()); + } +} diff --git a/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/SecurityConfig.java b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/SecurityConfig.java new file mode 100644 index 00000000000..c8c0edb588f --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/config/SecurityConfig.java @@ -0,0 +1,37 @@ +package no.nav.testnav.levendearbeidsforholdscheduler.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; + +@EnableWebSecurity +@Configuration +public class SecurityConfig { + + @Bean + @SuppressWarnings("java:S4502") + public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { + + httpSecurity.sessionManagement(sessionConfig -> sessionConfig.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .csrf(AbstractHttpConfigurer::disable) + .authorizeHttpRequests(authorizeConfig -> authorizeConfig.requestMatchers( + "/internal/**", + "/webjars/**", + "/swagger-resources/**", + "/v3/api-docs/**", + "/swagger-ui/**", + "/swagger", + "/error", + "/swagger-ui.html" + ).permitAll().requestMatchers("/scheduler/**").fullyAuthenticated()) + .oauth2ResourceServer(oauth2RSConfig -> oauth2RSConfig.jwt(Customizer.withDefaults())); + + return httpSecurity.build(); + } +} + diff --git a/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/consumer/AnsettelseConsumer.java b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/consumer/AnsettelseConsumer.java new file mode 100644 index 00000000000..045b50aecf2 --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/consumer/AnsettelseConsumer.java @@ -0,0 +1,33 @@ +package no.nav.testnav.levendearbeidsforholdscheduler.consumer; + +import no.nav.testnav.levendearbeidsforholdscheduler.config.Consumers; +import no.nav.testnav.levendearbeidsforholdscheduler.consumer.command.AnsettelsesCommand; +import no.nav.testnav.libs.securitycore.domain.ServerProperties; +import no.nav.testnav.libs.standalone.servletsecurity.exchange.TokenExchange; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClient; + +@Component +public class AnsettelseConsumer { + private final WebClient webClient; + private final ServerProperties serverProperties; + private final TokenExchange tokenExchange; + + public AnsettelseConsumer(Consumers consumers, + TokenExchange tokenExchange) { + this.serverProperties = consumers.getLevendeArbeidsforholdAnsettelse(); + this.tokenExchange = tokenExchange; + + this.webClient = WebClient + .builder() + .baseUrl(serverProperties.getUrl()) + .build(); + } + + public void hentFraAnsettelse() { + + tokenExchange.exchange(serverProperties) + .flatMap(token -> new AnsettelsesCommand(webClient, token.getTokenValue()).call()) + .block(); + } +} diff --git a/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/consumer/command/AnsettelsesCommand.java b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/consumer/command/AnsettelsesCommand.java new file mode 100644 index 00000000000..cbe66a0e822 --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/consumer/command/AnsettelsesCommand.java @@ -0,0 +1,26 @@ +package no.nav.testnav.levendearbeidsforholdscheduler.consumer.command; + +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpHeaders; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.util.concurrent.Callable; + +@RequiredArgsConstructor +public class AnsettelsesCommand implements Callable> { + + private final WebClient webClient; + private final String token; + + @Override + public Mono call() { + + return webClient.get().uri( + builder -> builder.path("/api/ansettelse-jobb") + .build()) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + token) + .retrieve() + .bodyToMono(String.class); + } +} diff --git a/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/controller/JobbController.java b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/controller/JobbController.java new file mode 100644 index 00000000000..36f3f4e3e41 --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/controller/JobbController.java @@ -0,0 +1,98 @@ +package no.nav.testnav.levendearbeidsforholdscheduler.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import no.nav.testnav.levendearbeidsforholdscheduler.domain.StatusRespons; +import no.nav.testnav.levendearbeidsforholdscheduler.scheduler.JobbScheduler; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Optional; + +import static no.nav.testnav.levendearbeidsforholdscheduler.utils.Utils.sifferTilHeltall; + +@Slf4j +@RestController +@RequestMapping("/scheduler") +@RequiredArgsConstructor +public class JobbController { + + private final JobbScheduler jobbScheduler; + + /** + * Request handler funksjon for å restarte scheduler + * @param intervall positivt heltall for å representere times-intervall + * @return respons til klienten for den tilsvarende spørringen + */ + @GetMapping(value = {"", "/start"}) + @Operation(description = "Starter scheduleren med en forsinkelse av et gitt intervall på x antall timer") + public ResponseEntity reschedule(@Schema(description = "Positivt heltall for å representere times-intervall") @RequestParam String intervall) { + + if (intervall == null) { + return ResponseEntity.badRequest().body("intervall er ikke spesifisert"); + } + + var resultat = sifferTilHeltall(intervall); + + if (resultat.isPresent()){ + if (jobbScheduler.startScheduler(resultat.get())){ + return ResponseEntity.ok("Aktivering av scheduler var vellykket med intervall: " + intervall); + } else { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); + } + } else { + return ResponseEntity.badRequest().body("Intervall er ikke gyldig heltall"); + } + } + + /** + * Request handler funksjon som returnerer status på om scheduler kjører for øyeblikket og eventuelt tidspunktet + * for neste gang scheduleren skal kjøre ansettelses-jobben + * @return 200 OK, med status- og tidspunkt data på JSON format i response body + */ + @GetMapping(value = "/status", produces = "application/json") + @Operation(description = "Henter statusen på om scheduleren er aktiv eller ikke. Dersom den er aktiv, vil den også returnere tidspunktet for neste gang scheduleren skal kjøre ansettelse jobben") + public ResponseEntity status() { + + var tidspunkt = Optional.of(""); + + var status = jobbScheduler.hentStatusKjorer(); + + var statusRespons = new StatusRespons(); + + statusRespons.setStatus(status); + + if (status){ + tidspunkt = jobbScheduler.hentTidspunktNesteKjoring(); + if (tidspunkt.isEmpty()) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); + } + } + + statusRespons.setNesteKjoring(tidspunkt.get()); + + return ResponseEntity.ok(statusRespons); + } + + /** + * Request handler funksjon for å stoppe scheduleren + * @return true hvis kanselleringen var vellykket + */ + @GetMapping(value = "/stopp") + @Operation(description = "Stopper scheduleren dersom den er aktiv") + public ResponseEntity stopp() { + + if (!jobbScheduler.stoppScheduler()){ + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); + } else { + return ResponseEntity.ok("Deaktivering av scheduler var vellykket"); + } + } +} + diff --git a/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/domain/StatusRespons.java b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/domain/StatusRespons.java new file mode 100644 index 00000000000..e956c75f211 --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/domain/StatusRespons.java @@ -0,0 +1,14 @@ +package no.nav.testnav.levendearbeidsforholdscheduler.domain; + +import lombok.Getter; +import lombok.Setter; + + + +@Setter +@Getter +public class StatusRespons { + + private boolean status; + private String nesteKjoring; +} diff --git a/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/scheduler/AnsettelsesService.java b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/scheduler/AnsettelsesService.java new file mode 100644 index 00000000000..fbd168de3d2 --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/scheduler/AnsettelsesService.java @@ -0,0 +1,16 @@ +package no.nav.testnav.levendearbeidsforholdscheduler.scheduler; + +import lombok.RequiredArgsConstructor; +import no.nav.testnav.levendearbeidsforholdscheduler.consumer.AnsettelseConsumer; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class AnsettelsesService { + + private final AnsettelseConsumer ansettelseConsumer; + + public void hent(){ + ansettelseConsumer.hentFraAnsettelse(); + } +} diff --git a/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/scheduler/JobbScheduler.java b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/scheduler/JobbScheduler.java new file mode 100644 index 00000000000..249a36c6ee3 --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/scheduler/JobbScheduler.java @@ -0,0 +1,168 @@ +package no.nav.testnav.levendearbeidsforholdscheduler.scheduler; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.stereotype.Component; + +import java.util.Calendar; +import java.util.Date; +import java.util.Optional; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import static no.nav.testnav.levendearbeidsforholdscheduler.utils.Utils.beregnEkstraDelayNaa; +import static no.nav.testnav.levendearbeidsforholdscheduler.utils.Utils.hentKalender; + +@Slf4j +@Component +@EnableScheduling +@RequiredArgsConstructor +public class JobbScheduler { + + private final AnsettelsesService ansettelsesService; + private final ScheduledExecutorService taskScheduler; + + private ScheduledFuture scheduledFuture; + + private static final int START_KLOKKESLETT = 6; + private static final int START_DAG = 1; + + private static final int SLUTT_KLOKKESLETT = 12; + private static final int SLUTT_DAG = 6; + + private static final long INITIELL_FORSINKELSE = 0; + + /** + * Funksjon som brukes for å sjekke om scheduleren kjører for øyeblikket + * @return true hvis scheduler kjører for øyeblikket + */ + public boolean hentStatusKjorer(){ + if (scheduledFuture != null) { + + return !(scheduledFuture.state() == Future.State.CANCELLED); + } else { + return false; + } + } + + /** + * Henter ut dato og tid for neste gang scheduleren skal kjøre en jobb + * @return tidspunktet, då lenge det er en scheduler som er aktiv for øyeblikket + */ + public Optional hentTidspunktNesteKjoring(){ + + if (scheduledFuture != null) { + long delayIMillisekunder = scheduledFuture.getDelay(TimeUnit.MILLISECONDS); + long nesteKjoringMillisekunder = beregnNesteKjoring(delayIMillisekunder); + + Date datoForNesteKjoring = new Date(nesteKjoringMillisekunder); + return Optional.of(datoForNesteKjoring.toString()); + } else { + return Optional.empty(); + } + + } + + /** + * Avslutter eventuelt nåværende schedule og starter en ny med det nye intervallet. + * @param intervall Positivt heltall som representerer times-intervall for scheduler + * @return true hvis aktivering av scheduler med ansettelse-jobb var vellykket + */ + public boolean startScheduler(long intervall){ + + if (scheduledFuture != null) { + scheduledFuture.cancel(true); + } + + scheduledFuture = taskScheduler.scheduleAtFixedRate(new AnsettelseJobb(), INITIELL_FORSINKELSE, intervall, TimeUnit.HOURS); + + return scheduledFuture.state() == Future.State.RUNNING; + } + + + /** + * Funksjon som stopper den nåværende/kjørende jobben + * @return true hvis jobben ble stoppet vellykket + */ + public boolean stoppScheduler(){ + if (scheduledFuture != null) { + scheduledFuture.cancel(true); + + return scheduledFuture.isCancelled(); + } + return true; + } + + /** + * Funksjon som validerer om angitt tidspunkt er innenfor et gitt tidsrom for en vilkårlig uke. + * Brukes i forbindelse med å ikke kjøre AnsettelseJobb-klassen på gitte-tidspunkter i helgen for eksempel. + * @param startKlokka Tall som representerer timen i en 24-timers klokke for klokkeslett på start for gyldig tidsrom + * @param startDag Tall som representerer dag i uken fra 1-7 (man-søn) for start på gyldig tidsrom + * @param sluttKlokka Tall som representerer timen i en 24-timers klokke for klokkeslett på start for gyldig tidsrom + * @param sluttDag Tall som representerer dag i uken fra 1-7 (man-søn) for start på gyldig tidsrom + * @param klokkeslett Tall som representerer timen i en 24-timers klokke for nåværende tidspunkt + * @param idag Tall som representerer dagen i uken i en 24-timers klokke + * @return true hvis angitt dag og klokkeslett er innenfor det gitte tidsrommet i en vilkårlig uke + */ + public static boolean sjekkGyldigTidsrom(int startKlokka, int startDag, int sluttKlokka, int sluttDag, int klokkeslett, int idag){ + return (startDag > sluttDag && (idag > startDag || idag < sluttDag)) //Ved ukes-skifte + || (idag > startDag && idag < sluttDag) //Innad i samme uke + || ((idag == startDag && klokkeslett >= startKlokka) //Samme dag, startdag + || (idag == sluttDag && klokkeslett < sluttKlokka)); //Samme dag, sluttdag + } + + + /** + * Funksjon som sjekker om nåværende tidspunkt med klokke-time og dag er innenfor gyldig tidsrom + * @param startKlokka Tall som representerer timen i en 24-timers klokke for klokkeslett på start for gyldig tidsrom + * @param startDag Tall som representerer dag i uken fra 1-7 (man-søn) for start på gyldig tidsrom + * @param sluttKlokka Tall som representerer timen i en 24-timers klokke for klokkeslett på start for gyldig tidsrom + * @param sluttDag Tall som representerer dag i uken fra 1-7 (man-søn) for start på gyldig tidsrom + * @return true hvis nåværende dag og klokkeslett er innenfor det gitte tidsrommet i en vilkårlig uke + */ + public boolean sjekkOmGyldigTidsromNaa(int startKlokka, int startDag, int sluttKlokka, int sluttDag){ + + Calendar kalender = hentKalender(); + int klokkeslett = kalender.get(Calendar.HOUR_OF_DAY); //06:00 = 6, 13:00 = 13, 23:00 = 23 + int dag = ((kalender.get(Calendar.DAY_OF_WEEK) + 6) % 7); //Mandag = 1, Tirsag = 2 ... Søndag = 7 + + return sjekkGyldigTidsrom(startKlokka, startDag, sluttKlokka, sluttDag, klokkeslett, dag); + } + + /** + * Funksjon som beregner timestamp/tidspunkt (med millisekunder som tidsenhet) for neste kjøring av nåværende + * jobb + * @param schedulerDelay Delay/forsinkelse scheduler har for kjøring av jobb + * @return positivt heltall som representerer tidspunktet for neste kjøring i millisekunder + */ + public long beregnNesteKjoring(long schedulerDelay){ + long nesteKjoringMillisekunder = System.currentTimeMillis() + schedulerDelay; + + if (!sjekkOmGyldigTidsromNaa(START_KLOKKESLETT, START_DAG, SLUTT_KLOKKESLETT, SLUTT_DAG)){ + nesteKjoringMillisekunder = System.currentTimeMillis() + beregnEkstraDelayNaa(START_DAG, START_KLOKKESLETT); + } + return nesteKjoringMillisekunder; + } + + /** + * Klasse for jobben som skal kjøres av scheduler + */ + private class AnsettelseJobb implements Runnable { + + /** + * Funksjon som automatisk blir kalt på av en task-scheduler og kjører ansettelsesservice innenfor gyldig + * tidsrom + */ + @Override + public void run() { + if(sjekkOmGyldigTidsromNaa(START_KLOKKESLETT, START_DAG, SLUTT_KLOKKESLETT, SLUTT_DAG)){ + ansettelsesService.hent(); + } + + } + } + +} diff --git a/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/utils/Utils.java b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/utils/Utils.java new file mode 100644 index 00000000000..d8fdac8c791 --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/main/java/no/nav/testnav/levendearbeidsforholdscheduler/utils/Utils.java @@ -0,0 +1,82 @@ +package no.nav.testnav.levendearbeidsforholdscheduler.utils; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Optional; + +import static java.lang.Math.abs; + +public class Utils { + + private static final int DAGER_I_UKA = 7; + + /** + * Funksjon som validerer om intervall er et positivt heltall + * @param intervall Tekst med siffer som representerer antall timer forsinkelse for job-scheduleren + * @return intervallet som heltall dersom det er et gyldig heltall + */ + public static Optional sifferTilHeltall(String intervall) { + + try { + long tall = Integer.parseInt(intervall); + return Optional.of(tall); + } catch (NumberFormatException e) { + return Optional.empty(); + } + } + + public static Calendar hentKalender(){ + Date dato = new Date(); + Calendar kalender = GregorianCalendar.getInstance(); + kalender.setTime(dato); + return kalender; + } + + public static long timerTilMillisek(long antTimer){ + return antTimer * 60 * 60 * 1000; + } + + public static long dagerTilMillisek(long antDager){ + return antDager * timerTilMillisek(24); + } + + /** + * Henter ekstra forsinkelse for uthenting av tidspunkt for neste kjøring av scheduler for nåværende tidspunkt. + * Brukes når status på scheduler hentes i ugyldig tidsrom + * @param startdag Positivt heltall fra 1-7 som representerer første dag i uka for gyldig tidsrom + * @param startklokkeslett Positivt heltall fra 0-23 som representerer start-klokkeslett for gyldig tidsrom + * @return Delay i antall millisekunder for nåværende tidspunkt + */ + public static long beregnEkstraDelayNaa(int startdag, int startklokkeslett){ + Calendar kalender = hentKalender(); + int klokkeslett = kalender.get(Calendar.HOUR_OF_DAY); //06:00 = 6, 13:00 = 13, 23:00 = 23 + int dag = ((kalender.get(Calendar.DAY_OF_WEEK) + 6) % 7); //Mandag = 1, Tirsag = 2 ... Søndag = 7 + + return beregnEkstraDelay(startdag, startklokkeslett, klokkeslett, dag); + } + + /** + * Henter ekstra forsinkelse for uthenting av tidspunkt for neste kjøring av scheduler. + * @param startdag Positivt heltall fra 1-7 som representerer første dag i uka for gyldig tidsrom + * @param startklokkeslett Positivt heltall fra 0-23 som representerer start-klokkeslett for gyldig tidsrom + * @param klokkeslett Positivt heltall fra 0-23 som representerer nåværende klokkeslett + * @param dag Positivt heltall fra 1-7 som representerer dag i uka for nåværende tidspunkt + * @return Delay i antall millisekunder + */ + public static long beregnEkstraDelay(int startdag, int startklokkeslett, int klokkeslett, int dag){ + int antallDagerTilKjoring = 0; + if(startdag < dag){ + antallDagerTilKjoring = DAGER_I_UKA - abs(startdag - dag); + } else { + antallDagerTilKjoring = startdag - dag; + } + + int antallTimer = startklokkeslett - klokkeslett; + + long milliSekunderTimer = timerTilMillisek(antallTimer); + long milliSekunderDager = dagerTilMillisek(antallDagerTilKjoring); + + return milliSekunderTimer + milliSekunderDager; + } +} diff --git a/apps/levende-arbeidsforhold-scheduler/src/main/resources/application-dev.yml b/apps/levende-arbeidsforhold-scheduler/src/main/resources/application-dev.yml new file mode 100644 index 00000000000..92a5a9b44c8 --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/main/resources/application-dev.yml @@ -0,0 +1,4 @@ + +consumers: + levende-arbeidsforhold-ansettelse: + url: https://testnav-levende-arbeidsforhold-ansettelse.intern.dev.nav.no diff --git a/apps/levende-arbeidsforhold-scheduler/src/main/resources/application.yml b/apps/levende-arbeidsforhold-scheduler/src/main/resources/application.yml new file mode 100644 index 00000000000..ff834c50235 --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/main/resources/application.yml @@ -0,0 +1,52 @@ +AAD_ISSUER_URI: https://login.microsoftonline.com/62366534-1ec3-4962-8869-9b5535279d0b + +spring: + main: + banner-mode: off + application: + name: testnav-levende-arbeidsforhold-scheduler + version: application.version.todo #TODO Finn ut hvordan denne kan settes fra Gradle + description: App for å ansette personer i en organisasjon + security: + oauth2: + resourceserver: + aad: + issuer-uri: ${AAD_ISSUER_URI}/v2.0 + jwk-set-uri: ${AAD_ISSUER_URI}/discovery/v2.0/keys + accepted-audience: ${azure.app.client.id}, api://${azure.app.client.id} + cloud: + vault: + enabled: false +springdoc: + swagger-ui: + disable-swagger-default-url: true + url: /v3/api-docs + +management: + endpoints: + enabled-by-default: true + web: + base-path: /internal + exposure.include: prometheus,heapdump,health + path-mapping: + prometheus: metrics + endpoint: + prometheus.enabled: true + heapdump.enabled: true + prometheus: + metrics: + export: + enabled: true +server: + port: 8080 + servlet: + encoding: + charset: UTF-8 + error: + include-message: always +consumers: + levende-arbeidsforhold-ansettelse: + name: testnav-levende-arbeidsforhold-ansettelse + namespace: dolly + url: http://testnav-levende-arbeidsforhold-ansettelse.dolly.svc.cluster.local + cluster: dev-gcp \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-scheduler/src/test/java/no/nav/testnav/levendearbeidsforholdscheduler/LevendeArbeidsforholdSchedulerApplicationTests.java b/apps/levende-arbeidsforhold-scheduler/src/test/java/no/nav/testnav/levendearbeidsforholdscheduler/LevendeArbeidsforholdSchedulerApplicationTests.java new file mode 100644 index 00000000000..a2119dfcd3c --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/test/java/no/nav/testnav/levendearbeidsforholdscheduler/LevendeArbeidsforholdSchedulerApplicationTests.java @@ -0,0 +1,13 @@ +package no.nav.testnav.levendearbeidsforholdscheduler; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class LevendeArbeidsforholdSchedulerApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/apps/levende-arbeidsforhold-scheduler/src/test/java/no/nav/testnav/levendearbeidsforholdscheduler/scheduler/JobbSchedulerTest.java b/apps/levende-arbeidsforhold-scheduler/src/test/java/no/nav/testnav/levendearbeidsforholdscheduler/scheduler/JobbSchedulerTest.java new file mode 100644 index 00000000000..7d347b262fc --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/test/java/no/nav/testnav/levendearbeidsforholdscheduler/scheduler/JobbSchedulerTest.java @@ -0,0 +1,44 @@ +package no.nav.testnav.levendearbeidsforholdscheduler.scheduler; + +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; + +import static no.nav.testnav.levendearbeidsforholdscheduler.scheduler.JobbScheduler.sjekkGyldigTidsrom; + +@Slf4j +class JobbSchedulerTest { + + @Test + public void testGyldigTidsrom(){ + + //Test for dag - Skal bli true + assert sjekkGyldigTidsrom(12, 6, 16, 2, 13, 7); + + //Test for dag - Skal bli false + assert !sjekkGyldigTidsrom(12, 6, 16, 2, 13, 3); + + //Test for klokkeslett startdag - Skal bli true + assert sjekkGyldigTidsrom(12, 6, 16, 2, 13, 6); + + //Test for klokkeslett sluttdag - Skal bli true + assert sjekkGyldigTidsrom(12, 6, 16, 2, 13, 2); + + //Test for klokkeslett sluttdag - Skal bli false + assert !sjekkGyldigTidsrom(12, 6, 16, 2, 16, 2); + + //Test for klokkeslett startdag - Skal bli false + assert !sjekkGyldigTidsrom(12, 6, 16, 2, 11, 6); + + //Test for dag - Skal bli false + assert !sjekkGyldigTidsrom(12, 3, 16, 1, 13, 2); + + //Test for dag - Skal bli false + assert !sjekkGyldigTidsrom(12, 5, 16, 7, 13, 4); + + //Test for dag - Skal bli false + assert !sjekkGyldigTidsrom(12, 4, 16, 4, 13, 5); + + //Test for dag - Skal bli true + assert sjekkGyldigTidsrom(12, 5, 16, 5, 13, 5); + } +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-scheduler/src/test/java/no/nav/testnav/levendearbeidsforholdscheduler/utils/UtilsTest.java b/apps/levende-arbeidsforhold-scheduler/src/test/java/no/nav/testnav/levendearbeidsforholdscheduler/utils/UtilsTest.java new file mode 100644 index 00000000000..5ce1f8a4c51 --- /dev/null +++ b/apps/levende-arbeidsforhold-scheduler/src/test/java/no/nav/testnav/levendearbeidsforholdscheduler/utils/UtilsTest.java @@ -0,0 +1,15 @@ +package no.nav.testnav.levendearbeidsforholdscheduler.utils; + +import org.junit.jupiter.api.Test; + +import static no.nav.testnav.levendearbeidsforholdscheduler.utils.Utils.beregnEkstraDelay; + +class UtilsTest { + + @Test + public void testBeregnEkstraDelay(){ + assert beregnEkstraDelay(2, 3, 3, 5) == 345600000; + assert beregnEkstraDelay(2, 3, 6, 5) == 334800000; + assert beregnEkstraDelay(5, 10, 23, 3) == 126000000; + } +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-service/build.gradle b/apps/levende-arbeidsforhold-service/build.gradle index 18246d51a1e..42454499acc 100644 --- a/apps/levende-arbeidsforhold-service/build.gradle +++ b/apps/levende-arbeidsforhold-service/build.gradle @@ -50,6 +50,7 @@ dependencies { implementation 'no.nav.testnav.libs:servlet-insecure-security' implementation 'no.nav.testnav.libs:servlet-core' implementation 'no.nav.testnav.libs:reactive-core' + implementation 'no.nav.testnav.libs:data-transfer-objects' implementation 'org.springframework.boot:spring-boot-starter-webflux' implementation 'org.springframework.boot:spring-boot-starter-web' diff --git a/apps/levende-arbeidsforhold-service/settings.gradle b/apps/levende-arbeidsforhold-service/settings.gradle index b8c8778a068..b20e80d0ce7 100644 --- a/apps/levende-arbeidsforhold-service/settings.gradle +++ b/apps/levende-arbeidsforhold-service/settings.gradle @@ -10,6 +10,7 @@ includeBuild '../../libs/security-core' includeBuild '../../libs/servlet-core' includeBuild '../../libs/reactive-core' includeBuild '../../libs/servlet-insecure-security' +includeBuild '../../libs/data-transfer-objects' includeBuild '../../.github/workflows' develocity { diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/consumers/AaregConsumer.java b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/consumers/AaregConsumer.java deleted file mode 100644 index 9b3f46be9a2..00000000000 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/consumers/AaregConsumer.java +++ /dev/null @@ -1,77 +0,0 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.consumers; - -import lombok.extern.slf4j.Slf4j; - -import no.nav.registre.testnorge.levendearbeidsforhold.consumers.command.EndreArbeidsforholdCommand; -import no.nav.registre.testnorge.levendearbeidsforhold.consumers.command.HentArbeidsforholdCommand; -import no.nav.registre.testnorge.levendearbeidsforhold.domain.v1.Arbeidsforhold; -import no.nav.registre.testnorge.levendearbeidsforhold.config.Consumers; -import no.nav.testnav.libs.securitycore.domain.ServerProperties; -import no.nav.testnav.libs.standalone.servletsecurity.exchange.TokenExchange; - -import org.springframework.http.MediaType; -import org.springframework.http.codec.json.Jackson2JsonDecoder; -import org.springframework.http.codec.json.Jackson2JsonEncoder; -import org.springframework.stereotype.Component; -import org.springframework.web.reactive.function.client.ExchangeStrategies; -import org.springframework.web.reactive.function.client.WebClient; - -import java.util.ArrayList; -import java.util.List; - -import static java.util.Objects.nonNull; - -import com.fasterxml.jackson.databind.ObjectMapper; - -@Slf4j -@Component -public class AaregConsumer { - - private final WebClient webClient; - private final ServerProperties serverProperties; - private final TokenExchange tokenExchange; - - public AaregConsumer( - Consumers consumers, - TokenExchange tokenExchange, - ObjectMapper objectMapper) { - - this.serverProperties = consumers.getTestnavAaregProxy(); - this.tokenExchange = tokenExchange; - - ExchangeStrategies jacksonStrategy = ExchangeStrategies - .builder() - .codecs( - config -> { - config - .defaultCodecs() - .jackson2JsonEncoder(new Jackson2JsonEncoder(objectMapper, MediaType.APPLICATION_JSON)); - config - .defaultCodecs() - .jackson2JsonDecoder(new Jackson2JsonDecoder(objectMapper, MediaType.APPLICATION_JSON)); - }) - .build(); - - this.webClient = WebClient - .builder() - .exchangeStrategies(jacksonStrategy) - .baseUrl(serverProperties.getUrl()) - .build(); - } - - public List hentArbeidsforhold(String ident) { - var token = tokenExchange.exchange(serverProperties).block(); - if (nonNull(token)) { - return new HentArbeidsforholdCommand(webClient, token.getTokenValue(), ident).call(); - } - return new ArrayList<>(); - } - - public void endreArbeidsforhold(Arbeidsforhold requests) { - var token = tokenExchange.exchange(serverProperties).block(); - if (nonNull(token)) { - new EndreArbeidsforholdCommand(webClient, requests, token.getTokenValue()).call(); - } - } -} - diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Persontype.java b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Persontype.java deleted file mode 100644 index 516b09ee60f..00000000000 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Persontype.java +++ /dev/null @@ -1,6 +0,0 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; - -public interface Persontype { - - String getType(); -} diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/LevendeArbeidsforholdServiceApplicationStarter.java b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/LevendeArbeidsforholdServiceApplicationStarter.java similarity index 86% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/LevendeArbeidsforholdServiceApplicationStarter.java rename to apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/LevendeArbeidsforholdServiceApplicationStarter.java index 4c1bc1f8bd4..ffcd5657565 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/LevendeArbeidsforholdServiceApplicationStarter.java +++ b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/LevendeArbeidsforholdServiceApplicationStarter.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold; +package no.nav.testnav.levendearbeidsforholdservice; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/ApplicationConfig.java b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/ApplicationConfig.java similarity index 87% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/ApplicationConfig.java rename to apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/ApplicationConfig.java index 80a0da22609..3e2d766f0b5 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/ApplicationConfig.java +++ b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/ApplicationConfig.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.config; +package no.nav.testnav.levendearbeidsforholdservice.config; import no.nav.testnav.libs.servletcore.config.ApplicationCoreConfig; import no.nav.testnav.libs.standalone.servletsecurity.config.InsecureJwtServerToServerConfiguration; diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/Consumers.java b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/Consumers.java similarity index 93% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/Consumers.java rename to apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/Consumers.java index c5654aff14d..5feb1c52d45 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/Consumers.java +++ b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/Consumers.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.config; +package no.nav.testnav.levendearbeidsforholdservice.config; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/DevConfig.java b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/DevConfig.java new file mode 100644 index 00000000000..7d72c0cabd5 --- /dev/null +++ b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/DevConfig.java @@ -0,0 +1,36 @@ +package no.nav.testnav.levendearbeidsforholdservice.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.vault.annotation.VaultPropertySource; +import org.springframework.vault.authentication.ClientAuthentication; +import org.springframework.vault.authentication.TokenAuthentication; +import org.springframework.vault.client.VaultEndpoint; +import org.springframework.vault.config.AbstractVaultConfiguration; + +import static io.micrometer.common.util.StringUtils.isBlank; + +@Configuration +@Profile("dev") +@VaultPropertySource(value = "secret/dolly/lokal", ignoreSecretNotFound = false) +public class DevConfig extends AbstractVaultConfiguration { + + private static final String VAULT_TOKEN = "spring.cloud.vault.token"; + + @Override + public VaultEndpoint vaultEndpoint() { + return VaultEndpoint.create("vault.adeo.no", 443); + } + + @Override + public ClientAuthentication clientAuthentication() { + if (System.getenv().containsKey("VAULT_TOKEN")) { + System.setProperty(VAULT_TOKEN, System.getenv("VAULT_TOKEN")); + } + var token = System.getProperty(VAULT_TOKEN); + if (isBlank(token)) { + throw new IllegalArgumentException("Påkrevet property 'spring.cloud.vault.token' er ikke satt."); + } + return new TokenAuthentication(System.getProperty(VAULT_TOKEN)); + } +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/KafkaConfig.java b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/KafkaConfig.java similarity index 98% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/KafkaConfig.java rename to apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/KafkaConfig.java index 5fab1fac11f..3b7204a5401 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/KafkaConfig.java +++ b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/KafkaConfig.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.config; +package no.nav.testnav.levendearbeidsforholdservice.config; import io.confluent.kafka.serializers.AbstractKafkaSchemaSerDeConfig; diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/OpenApiConfig.java b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/OpenApiConfig.java new file mode 100644 index 00000000000..cce1719b2b4 --- /dev/null +++ b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/OpenApiConfig.java @@ -0,0 +1,54 @@ +package no.nav.testnav.levendearbeidsforholdservice.config; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Contact; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import no.nav.testnav.libs.servletcore.config.ApplicationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.util.Arrays; + +@Configuration +public class OpenApiConfig implements WebMvcConfigurer { + + @Bean + public OpenAPI openApi(ApplicationProperties applicationProperties) { + return new OpenAPI() + .components(new Components().addSecuritySchemes("bearer-jwt", new SecurityScheme() + .type(SecurityScheme.Type.HTTP) + .scheme("bearer") + .bearerFormat("JWT") + .in(SecurityScheme.In.HEADER) + .name("Authorization") + )) + .addSecurityItem( + new SecurityRequirement().addList("bearer-jwt", Arrays.asList("read", "write"))) + .info(new Info() + .title(applicationProperties.getName()) + .version(applicationProperties.getVersion()) + .description(applicationProperties.getDescription()) + .termsOfService("https://nav.no") + .contact(new Contact() + .url("https://nav-it.slack.com/archives/CA3P9NGA2") + .email("dolly@nav.no") + .name("Team Dolly") + ) + .license(new License() + .name("MIT License") + .url("https://opensource.org/licenses/MIT") + ) + ); + } + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/swagger").setViewName("redirect:/swagger-ui.html"); + } +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/SecurityConfig.java b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/SecurityConfig.java similarity index 96% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/SecurityConfig.java rename to apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/SecurityConfig.java index ae501af8a05..c92ac8fa6b2 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/config/SecurityConfig.java +++ b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/config/SecurityConfig.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.config; +package no.nav.testnav.levendearbeidsforholdservice.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/consumers/AaregConsumer.java b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/consumers/AaregConsumer.java new file mode 100644 index 00000000000..c295c2c2f26 --- /dev/null +++ b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/consumers/AaregConsumer.java @@ -0,0 +1,51 @@ +package no.nav.testnav.levendearbeidsforholdservice.consumers; + +import lombok.extern.slf4j.Slf4j; +import no.nav.testnav.levendearbeidsforholdservice.config.Consumers; +import no.nav.testnav.levendearbeidsforholdservice.consumers.command.EndreArbeidsforholdCommand; +import no.nav.testnav.levendearbeidsforholdservice.consumers.command.HentArbeidsforholdCommand; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Arbeidsforhold; +import no.nav.testnav.libs.securitycore.domain.ServerProperties; +import no.nav.testnav.libs.standalone.servletsecurity.exchange.TokenExchange; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClient; + +import java.util.List; + +@Slf4j +@Component +public class AaregConsumer { + + private final WebClient webClient; + private final ServerProperties serverProperties; + private final TokenExchange tokenExchange; + + public AaregConsumer( + Consumers consumers, + TokenExchange tokenExchange) { + + this.serverProperties = consumers.getTestnavAaregProxy(); + this.tokenExchange = tokenExchange; + + this.webClient = WebClient + .builder() + .baseUrl(serverProperties.getUrl()) + .build(); + } + + public List hentArbeidsforhold(String ident) { + + return tokenExchange.exchange(serverProperties) + .flatMapMany(token -> new HentArbeidsforholdCommand(webClient, token.getTokenValue(), ident).call()) + .collectList() + .block(); + } + + public void endreArbeidsforhold(Arbeidsforhold requests) { + + tokenExchange.exchange(serverProperties) + .flatMap(token -> new EndreArbeidsforholdCommand(webClient, requests, token.getTokenValue()).call()) + .doOnNext(status -> log.info("Status fra endre arbeidsforhold:", status)) + .block(); + } +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/consumers/command/EndreArbeidsforholdCommand.java b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/consumers/command/EndreArbeidsforholdCommand.java similarity index 70% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/consumers/command/EndreArbeidsforholdCommand.java rename to apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/consumers/command/EndreArbeidsforholdCommand.java index 60aceb2f3f7..60c4a2b6d71 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/consumers/command/EndreArbeidsforholdCommand.java +++ b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/consumers/command/EndreArbeidsforholdCommand.java @@ -1,13 +1,13 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.consumers.command; +package no.nav.testnav.levendearbeidsforholdservice.consumers.command; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import no.nav.registre.testnorge.levendearbeidsforhold.domain.v1.Arbeidsforhold; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Arbeidsforhold; import no.nav.testnav.libs.reactivecore.utils.WebClientFilter; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; -import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.http.ResponseEntity; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; import reactor.util.retry.Retry; @@ -19,7 +19,7 @@ @Slf4j @RequiredArgsConstructor -public class EndreArbeidsforholdCommand implements Callable> { +public class EndreArbeidsforholdCommand implements Callable>> { private static final String navArbeidsforholdKilde = "Dolly-doedsfall-hendelse" ; private static final String miljoe = "q2"; @@ -30,26 +30,21 @@ public class EndreArbeidsforholdCommand implements Callable @SneakyThrows @Override - public Mono call() { + public Mono> call() { - Mono request = webClient - .put() + return webClient.put() .uri(builder -> builder.path("/{miljoe}/api/v1/arbeidsforhold/{navArbeidsforholdId}") .build(miljoe, requests.getNavArbeidsforholdId())) .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .header(HttpHeaders.AUTHORIZATION, "Bearer " + token) .header("Nav-Arbeidsforhold-Kildereferanse", navArbeidsforholdKilde) .header("Nav-Arbeidsforhold-Periode", LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"))) - .body(BodyInserters.fromValue(requests)) + .bodyValue(requests) .retrieve() - .bodyToMono(Arbeidsforhold.class) + .toBodilessEntity() .retryWhen(Retry.backoff(3, Duration.ofSeconds(5)) .filter(WebClientFilter::is5xxException)) - .map(arbeidsforhold1 -> Arbeidsforhold.builder().build()); - - request.subscribe(response -> {}, error -> log.error("Feil ved endring av arbeidsforhold: {}", error.getMessage())); - - return request; + .doOnError(WebClientFilter::logErrorMessage); } } diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/consumers/command/HentArbeidsforholdCommand.java b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/consumers/command/HentArbeidsforholdCommand.java similarity index 66% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/consumers/command/HentArbeidsforholdCommand.java rename to apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/consumers/command/HentArbeidsforholdCommand.java index cf84f0f4848..e0a0d9585c7 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/consumers/command/HentArbeidsforholdCommand.java +++ b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/consumers/command/HentArbeidsforholdCommand.java @@ -1,30 +1,27 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.consumers.command; +package no.nav.testnav.levendearbeidsforholdservice.consumers.command; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import no.nav.registre.testnorge.levendearbeidsforhold.domain.v1.Arbeidsforhold; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Arbeidsforhold; import no.nav.testnav.libs.reactivecore.utils.WebClientFilter; import no.nav.testnav.libs.servletcore.headers.NavHeaders; import org.springframework.http.HttpHeaders; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClientResponseException; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; import reactor.util.retry.Retry; import java.time.Duration; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; import java.util.UUID; import java.util.concurrent.Callable; -import java.util.stream.Collectors; import static java.lang.String.format; - @Slf4j @RequiredArgsConstructor -public class HentArbeidsforholdCommand implements Callable> { +public class HentArbeidsforholdCommand implements Callable> { private static final String miljoe = "q2"; private static final String NAV_PERSON_IDENT = "Nav-Personident"; private static final String CONSUMER = "Dolly"; @@ -39,11 +36,8 @@ private static String getNavCallId() { @SneakyThrows @Override - public List call(){ - - try { - var arbeidsforhold = webClient - .get() + public Flux call() { + return webClient.get() .uri(builder -> builder .path("/{miljoe}/api/v1/arbeidstaker/arbeidsforhold") .queryParam("arbeidsforholdtype", "forenkletOppgjoersordning", @@ -55,21 +49,12 @@ public List call(){ .header(NavHeaders.NAV_CONSUMER_ID, CONSUMER) .header(NavHeaders.NAV_CALL_ID, getNavCallId()) .retrieve() - .bodyToMono(Arbeidsforhold[].class) + .bodyToFlux(Arbeidsforhold.class) .retryWhen(Retry .backoff(3, Duration.ofSeconds(5)) .filter(WebClientFilter::is5xxException)) - .block(); - - return Arrays.stream(arbeidsforhold).collect(Collectors.toList()); - } catch (WebClientResponseException.NotFound e) { - return Collections.emptyList(); - } catch (WebClientResponseException e) { - log.error( - "Klarer ikke å hente arbeidsforhold. Feilmelding: {}.", - e.getResponseBodyAsString() - ); - throw e; - } + .doOnError(WebClientFilter::logErrorMessage) + .onErrorResume(WebClientResponseException.NotFound.class, error -> Mono.empty()) + .onErrorResume(WebClientResponseException.class, error -> Mono.empty()); } } diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/listener/DoedsfallListener.java b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/listener/DoedsfallListener.java similarity index 91% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/listener/DoedsfallListener.java rename to apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/listener/DoedsfallListener.java index fa123f50c6f..cc811c15151 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/listener/DoedsfallListener.java +++ b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/listener/DoedsfallListener.java @@ -1,9 +1,9 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.listener; +package no.nav.testnav.levendearbeidsforholdservice.listener; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import no.nav.person.pdl.leesah.Personhendelse; -import no.nav.registre.testnorge.levendearbeidsforhold.service.ArbeidsforholdService; +import no.nav.testnav.levendearbeidsforholdservice.service.ArbeidsforholdService; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/service/ArbeidsforholdService.java b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/service/ArbeidsforholdService.java similarity index 56% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/service/ArbeidsforholdService.java rename to apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/service/ArbeidsforholdService.java index 4822569213e..d0dd6845787 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/service/ArbeidsforholdService.java +++ b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/service/ArbeidsforholdService.java @@ -1,44 +1,42 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.service; +package no.nav.testnav.levendearbeidsforholdservice.service; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; - -import no.nav.registre.testnorge.levendearbeidsforhold.consumers.AaregConsumer; -import no.nav.registre.testnorge.levendearbeidsforhold.domain.v1.Arbeidsforhold; - +import no.nav.testnav.levendearbeidsforholdservice.consumers.AaregConsumer; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.Arbeidsforhold; import org.springframework.stereotype.Service; import java.time.LocalDate; import java.util.List; +import static java.util.Objects.isNull; + @Slf4j @Service @RequiredArgsConstructor public class ArbeidsforholdService { + private static final String sluttAarsaksKode = "arbeidstakerHarSagtOppSelv"; + private static final String varslingsKode = "NAVEND"; + private final AaregConsumer aaregConsumer; - private final String sluttAarsaksKode = "arbeidstakerHarSagtOppSelv"; - private final String varslingsKode = "NAVEND"; public void arbeidsforholdService(String aktoerId) { - List arbeidsforholdListe = hentArbeidsforhold(aktoerId); - if (!arbeidsforholdListe.isEmpty()) { - arbeidsforholdListe.forEach( - arbeidsforhold -> { - if (arbeidsforhold.getAnsettelsesperiode().getPeriode().getTom() == null){ - endreArbeidsforhold(arbeidsforhold); - } + + hentArbeidsforhold(aktoerId) + .forEach(arbeidsforhold -> { + if (isNull(arbeidsforhold.getAnsettelsesperiode().getPeriode().getTom())) { + endreArbeidsforhold(arbeidsforhold); } - ); - } + }); } public List hentArbeidsforhold(String ident) { return aaregConsumer.hentArbeidsforhold(ident); } - public void endreArbeidsforhold(Arbeidsforhold arbeidsforhold){ + public void endreArbeidsforhold(Arbeidsforhold arbeidsforhold) { arbeidsforhold.getAnsettelsesperiode().getPeriode().setTom(LocalDate.now()); arbeidsforhold.getAnsettelsesperiode().setSluttaarsak(sluttAarsaksKode); diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/utility/CallIdUtil.java b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/utility/CallIdUtil.java new file mode 100644 index 00000000000..4bf11a881a4 --- /dev/null +++ b/apps/levende-arbeidsforhold-service/src/main/java/no/nav/testnav/levendearbeidsforholdservice/utility/CallIdUtil.java @@ -0,0 +1,17 @@ +package no.nav.testnav.levendearbeidsforholdservice.utility; + +import lombok.experimental.UtilityClass; + +import java.util.UUID; + +import static java.lang.String.format; + +@UtilityClass +public final class CallIdUtil { + public static final String HEADER_NAV_CONSUMER_ID = "Nav-Consumer-Id"; + public static final String HEADER_NAV_CALL_ID = "Nav-Call-Id"; + public static final String CONSUMER = "Dolly"; + public static String generateCallId() { + return format("%s-%s", CONSUMER, UUID.randomUUID()); + } +} \ No newline at end of file diff --git a/apps/levende-arbeidsforhold-service/src/test/java/no/nav/registre/testnorge/levendearbeidsforhold/ApplicationContextTest.java b/apps/levende-arbeidsforhold-service/src/test/java/no/nav/testnav/levendearbeidsforholdservice/ApplicationContextTest.java similarity index 89% rename from apps/levende-arbeidsforhold-service/src/test/java/no/nav/registre/testnorge/levendearbeidsforhold/ApplicationContextTest.java rename to apps/levende-arbeidsforhold-service/src/test/java/no/nav/testnav/levendearbeidsforholdservice/ApplicationContextTest.java index 4c6f896873e..8f3a5ea5356 100644 --- a/apps/levende-arbeidsforhold-service/src/test/java/no/nav/registre/testnorge/levendearbeidsforhold/ApplicationContextTest.java +++ b/apps/levende-arbeidsforhold-service/src/test/java/no/nav/testnav/levendearbeidsforholdservice/ApplicationContextTest.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold; +package no.nav.testnav.levendearbeidsforholdservice; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; diff --git a/apps/organisasjon-faste-data-service/config.yml b/apps/organisasjon-faste-data-service/config.yml index 6a9d8c71079..2355acdee86 100644 --- a/apps/organisasjon-faste-data-service/config.yml +++ b/apps/organisasjon-faste-data-service/config.yml @@ -32,6 +32,8 @@ spec: - application: testnav-synt-vedtakshistorikk-service - application: testnorge-statisk-data-forvalter cluster: dev-fss + - application: testnav-levende-arbeidsforhold-ansettelse + cluster: dev-gcp outbound: rules: - application: organisasjon-bestilling-service diff --git a/apps/oversikt-frontend/config.yml b/apps/oversikt-frontend/config.yml index 190e7b6cbb5..30c209b1c56 100644 --- a/apps/oversikt-frontend/config.yml +++ b/apps/oversikt-frontend/config.yml @@ -83,6 +83,9 @@ spec: - application: testnorge-profil-api - application: testnorge-profil-api-dev - application: testnorge-tilbakemelding-api + - application: testnav-levende-arbeidsforhold-ansettelse + - application: testnav-levende-arbeidsforhold-service + - application: testnav-levende-arbeidsforhold-scheduler liveness: path: /internal/isAlive initialDelay: 4 diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Ansettelsesperiode.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Ansettelsesperiode.java similarity index 88% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Ansettelsesperiode.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Ansettelsesperiode.java index b2580aa002b..d3c9d77d765 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Ansettelsesperiode.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Ansettelsesperiode.java @@ -1,17 +1,21 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; -import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; -@Data +@Getter +@Setter @NoArgsConstructor @AllArgsConstructor @Builder +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonPropertyOrder({ "periode", diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/AntallTimerForTimeloennet.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/AntallTimerForTimeloennet.java similarity index 79% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/AntallTimerForTimeloennet.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/AntallTimerForTimeloennet.java index 9f3dc79cfba..0f4c522ff2b 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/AntallTimerForTimeloennet.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/AntallTimerForTimeloennet.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; @@ -7,16 +7,20 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; -import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; -import no.nav.registre.testnorge.levendearbeidsforhold.util.JavaTimeUtil; +import lombok.Setter; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.util.TimeUtil; import java.time.YearMonth; -@Data +@Getter +@Setter @NoArgsConstructor @AllArgsConstructor @Builder +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonPropertyOrder({ "periode", @@ -44,11 +48,11 @@ public YearMonth getRapporteringsperiode() { @JsonProperty("rapporteringsperiode") @Schema(description = "Rapporteringsperiode for antall timer med timelønn, format (ISO-8601): yyyy-MM", example = "2018-05") public String getRapporteringsperiodeAsString() { - return JavaTimeUtil.toString(rapporteringsperiode); + return TimeUtil.toString(rapporteringsperiode); } @JsonProperty("rapporteringsperiode") public void setRapporteringsperiodeAsString(String rapporteringsperiode) { - this.rapporteringsperiode = JavaTimeUtil.toYearMonth(rapporteringsperiode); + this.rapporteringsperiode = TimeUtil.toYearMonth(rapporteringsperiode); } } diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Arbeidsavtale.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Arbeidsavtale.java similarity index 87% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Arbeidsavtale.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Arbeidsavtale.java index c9855e0b2e0..daa89c68d32 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Arbeidsavtale.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Arbeidsavtale.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; @@ -7,16 +7,22 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; import io.swagger.v3.oas.annotations.media.DiscriminatorMapping; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; import lombok.experimental.SuperBuilder; -import no.nav.registre.testnorge.levendearbeidsforhold.util.JavaTimeUtil; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.util.TimeUtil; import java.time.LocalDate; -@Data +@Getter +@Setter @NoArgsConstructor @SuperBuilder +@EqualsAndHashCode +@ToString @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, @@ -81,21 +87,21 @@ public LocalDate getSistStillingsendring() { @JsonProperty("sistLoennsendring") public String getSistLoennsendringAsString() { - return JavaTimeUtil.toString(sistLoennsendring); + return TimeUtil.toString(sistLoennsendring); } @JsonProperty("sistLoennsendring") public void setSistLoennsendringAsString(String sistLoennsendring) { - this.sistLoennsendring = JavaTimeUtil.toLocalDate(sistLoennsendring); + this.sistLoennsendring = TimeUtil.toLocalDate(sistLoennsendring); } @JsonProperty("sistStillingsendring") public String getSistStillingsendringAsString() { - return JavaTimeUtil.toString(sistStillingsendring); + return TimeUtil.toString(sistStillingsendring); } @JsonProperty("sistStillingsendring") public void setSistStillingsendringAsString(String sistStillingsendring) { - this.sistStillingsendring = JavaTimeUtil.toLocalDate(sistStillingsendring); + this.sistStillingsendring = TimeUtil.toLocalDate(sistStillingsendring); } } diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Arbeidsavtaletype.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Arbeidsavtaletype.java similarity index 77% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Arbeidsavtaletype.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Arbeidsavtaletype.java index 8192cf72ad5..c71645d2993 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Arbeidsavtaletype.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Arbeidsavtaletype.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Arbeidsforhold.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Arbeidsforhold.java similarity index 88% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Arbeidsforhold.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Arbeidsforhold.java index a340d6fdf1f..47c562156ee 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Arbeidsforhold.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Arbeidsforhold.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; @@ -7,17 +7,21 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; -import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; -import no.nav.registre.testnorge.levendearbeidsforhold.util.JavaTimeUtil; +import lombok.Setter; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.util.TimeUtil; import java.time.LocalDateTime; import java.util.List; -@Data +@Getter +@Setter @NoArgsConstructor @AllArgsConstructor @Builder +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonPropertyOrder({ "navArbeidsforholdId", @@ -90,12 +94,12 @@ public LocalDateTime getRegistrert() { @JsonProperty("registrert") @Schema(description = "Tidspunkt for registrering av arbeidsforhold, format (ISO-8601): yyyy-MM-dd'T'HH:mm[:ss[.SSSSSSSSS]]", example = "2018-09-18T11:12:29") public String getRegistrertAsString() { - return JavaTimeUtil.toString(registrert); + return TimeUtil.toString(registrert); } @JsonProperty("registrert") public void setRegistrertAsString(String registrert) { - this.registrert = JavaTimeUtil.toLocalDateTime(registrert); + this.registrert = TimeUtil.toLocalDateTime(registrert); } @JsonIgnore @@ -106,12 +110,12 @@ public LocalDateTime getSistBekreftet() { @JsonProperty("sistBekreftet") @Schema(description = "Tidspunkt for siste bekreftelse av arbeidsforhold, format (ISO-8601): yyyy-MM-dd'T'HH:mm[:ss[.SSSSSSSSS]]", example = "2018-09-19T12:10:31") public String getSistBekreftetAsString() { - return JavaTimeUtil.toString(sistBekreftet); + return TimeUtil.toString(sistBekreftet); } @JsonProperty("sistBekreftet") public void setSistBekreftetAsString(String sistBekreftet) { - this.sistBekreftet = JavaTimeUtil.toLocalDateTime(sistBekreftet); + this.sistBekreftet = TimeUtil.toLocalDateTime(sistBekreftet); } @Override diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Arbeidsforholdoversikt.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Arbeidsforholdoversikt.java similarity index 89% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Arbeidsforholdoversikt.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Arbeidsforholdoversikt.java index eb51335d943..cc89b0f2eea 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Arbeidsforholdoversikt.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Arbeidsforholdoversikt.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; @@ -7,18 +7,22 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; -import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; -import no.nav.registre.testnorge.levendearbeidsforhold.util.JavaTimeUtil; +import lombok.Setter; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.util.TimeUtil; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; -@Data +@Getter +@Setter @NoArgsConstructor @AllArgsConstructor @Builder +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonPropertyOrder({ "navArbeidsforholdId", @@ -80,7 +84,7 @@ public LocalDate getAnsattFom() { @JsonProperty("ansattFom") @Schema(description = "Fra-og-med-dato for ansettelsesperiode, format (ISO-8601): yyyy-MM-dd", example = "2014-07-01") public String getAnsattFomAsString() { - return JavaTimeUtil.toString(ansattFom); + return TimeUtil.toString(ansattFom); } @JsonIgnore @@ -91,7 +95,7 @@ public LocalDate getAnsattTom() { @JsonProperty("ansattTom") @Schema(description = "Til-og-med-dato for ansettelsesperiode, format (ISO-8601): yyyy-MM-dd", example = "2015-12-31") public String getAnsattTomAsString() { - return JavaTimeUtil.toString(ansattTom); + return TimeUtil.toString(ansattTom); } @JsonIgnore @@ -102,6 +106,6 @@ public LocalDateTime getSistBekreftet() { @JsonProperty("sistBekreftet") @Schema(description = "Tidspunkt for siste bekreftelse av arbeidsforhold, format (ISO-8601): yyyy-MM-dd'T'HH:mm[:ss[.SSSSSSSSS]]", example = "2018-09-19T12:10:31") public String getSistBekreftetAsString() { - return JavaTimeUtil.toString(sistBekreftet); + return TimeUtil.toString(sistBekreftet); } } diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/ArbeidsgiverArbeidsforholdoversikter.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/ArbeidsgiverArbeidsforholdoversikter.java similarity index 89% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/ArbeidsgiverArbeidsforholdoversikter.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/ArbeidsgiverArbeidsforholdoversikter.java index 674475f7258..d0ec96db3e9 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/ArbeidsgiverArbeidsforholdoversikter.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/ArbeidsgiverArbeidsforholdoversikter.java @@ -1,19 +1,23 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; -import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import java.util.List; -@Data +@Getter +@Setter @NoArgsConstructor @AllArgsConstructor @Builder +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "arbeidsforholdoversikter", diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Arbeidsgiveroversikt.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Arbeidsgiveroversikt.java similarity index 84% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Arbeidsgiveroversikt.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Arbeidsgiveroversikt.java index f1be4637bbf..9bd5b9e7a78 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Arbeidsgiveroversikt.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Arbeidsgiveroversikt.java @@ -1,17 +1,21 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; -import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; -@Data +@Getter +@Setter @NoArgsConstructor @AllArgsConstructor @Builder +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ "arbeidsgiver", diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Bruksperiode.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Bruksperiode.java similarity index 81% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Bruksperiode.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Bruksperiode.java index fd3fcb620ee..ac909083fdb 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Bruksperiode.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Bruksperiode.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; @@ -7,16 +7,20 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; -import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; -import no.nav.registre.testnorge.levendearbeidsforhold.util.JavaTimeUtil; +import lombok.Setter; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.util.TimeUtil; import java.time.LocalDateTime; -@Data +@Getter +@Setter @NoArgsConstructor @AllArgsConstructor @Builder +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonPropertyOrder({ "fom", @@ -42,23 +46,23 @@ public LocalDateTime getTom() { @JsonProperty("fom") @Schema(description = "Fra-tidsstempel for bruksperiode, format (ISO-8601): yyyy-MM-dd'T'HH:mm[:ss[.SSSSSSSSS]]", example = "2015-01-06T21:44:04.748") public String getFomAsString() { - return JavaTimeUtil.toString(fom); + return TimeUtil.toString(fom); } @JsonProperty("fom") public void setFomAsString(String fom) { - this.fom = JavaTimeUtil.toLocalDateTime(fom); + this.fom = TimeUtil.toLocalDateTime(fom); } @JsonProperty("tom") @Schema(description = "Til-tidsstempel for bruksperiode, format (ISO-8601): yyyy-MM-dd'T'HH:mm[:ss[.SSSSSSSSS]]", example = "2015-12-06T19:45:04") public String getTomAsString() { - return JavaTimeUtil.toString(tom); + return TimeUtil.toString(tom); } @JsonProperty("tom") public void setTomAsString(String tom) { - this.tom = JavaTimeUtil.toLocalDateTime(tom); + this.tom = TimeUtil.toLocalDateTime(tom); } @Override diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/ForenkletOppgjoersordningArbeidsavtale.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/ForenkletOppgjoersordningArbeidsavtale.java similarity index 91% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/ForenkletOppgjoersordningArbeidsavtale.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/ForenkletOppgjoersordningArbeidsavtale.java index 2cfa5113756..09f434d8516 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/ForenkletOppgjoersordningArbeidsavtale.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/ForenkletOppgjoersordningArbeidsavtale.java @@ -1,15 +1,13 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.ToString; import lombok.experimental.SuperBuilder; -@Data @NoArgsConstructor @SuperBuilder @EqualsAndHashCode(callSuper = true) diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/FrilanserArbeidsavtale.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/FrilanserArbeidsavtale.java similarity index 91% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/FrilanserArbeidsavtale.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/FrilanserArbeidsavtale.java index db5a22093c9..559c112c41d 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/FrilanserArbeidsavtale.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/FrilanserArbeidsavtale.java @@ -1,15 +1,13 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.ToString; import lombok.experimental.SuperBuilder; -@Data @NoArgsConstructor @SuperBuilder @EqualsAndHashCode(callSuper = true) diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Gyldighetsperiode.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Gyldighetsperiode.java similarity index 87% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Gyldighetsperiode.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Gyldighetsperiode.java index 35a6cd3690f..285d57696d2 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Gyldighetsperiode.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Gyldighetsperiode.java @@ -1,12 +1,10 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonInclude; -import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; -@Data @NoArgsConstructor @SuperBuilder @EqualsAndHashCode(callSuper = true) diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/MaritimArbeidsavtale.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/MaritimArbeidsavtale.java similarity index 90% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/MaritimArbeidsavtale.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/MaritimArbeidsavtale.java index 4f1a78bcf12..7d2981b3ea2 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/MaritimArbeidsavtale.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/MaritimArbeidsavtale.java @@ -1,18 +1,18 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import lombok.ToString; import lombok.experimental.SuperBuilder; -@Data +@Getter +@Setter @NoArgsConstructor -@AllArgsConstructor @SuperBuilder @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/OpplysningspliktigArbeidsgiver.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/OpplysningspliktigArbeidsgiver.java similarity index 79% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/OpplysningspliktigArbeidsgiver.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/OpplysningspliktigArbeidsgiver.java index b565cae50b8..83e85d2c7b3 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/OpplysningspliktigArbeidsgiver.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/OpplysningspliktigArbeidsgiver.java @@ -1,16 +1,12 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.experimental.SuperBuilder; +import lombok.EqualsAndHashCode; -@Data -@NoArgsConstructor -@SuperBuilder +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/OpplysningspliktigArbeidsgiverType.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/OpplysningspliktigArbeidsgiverType.java similarity index 54% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/OpplysningspliktigArbeidsgiverType.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/OpplysningspliktigArbeidsgiverType.java index 5c97c433b06..3ef561fee66 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/OpplysningspliktigArbeidsgiverType.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/OpplysningspliktigArbeidsgiverType.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; public interface OpplysningspliktigArbeidsgiverType { diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/OrdinaerArbeidsavtale.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/OrdinaerArbeidsavtale.java similarity index 91% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/OrdinaerArbeidsavtale.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/OrdinaerArbeidsavtale.java index 42cd8b828d9..b223f483ada 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/OrdinaerArbeidsavtale.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/OrdinaerArbeidsavtale.java @@ -1,15 +1,13 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.ToString; import lombok.experimental.SuperBuilder; -@Data @NoArgsConstructor @SuperBuilder @EqualsAndHashCode(callSuper = true) diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Organisasjon.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Organisasjon.java similarity index 87% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Organisasjon.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Organisasjon.java index 440607caed7..d895873e0d1 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Organisasjon.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Organisasjon.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; @@ -6,11 +6,13 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; -import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; -@Data +@Getter +@Setter @NoArgsConstructor @AllArgsConstructor @Builder @@ -26,6 +28,8 @@ public class Organisasjon extends OpplysningspliktigArbeidsgiver implements Oppl @Schema(description = "Organisasjonsnummer fra Enhetsregisteret", example = "987654321") private String organisasjonsnummer; + private String type; + @Override @JsonIgnore public String getType() { diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Periode.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Periode.java similarity index 77% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Periode.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Periode.java index 087f903a9e8..2de0a566023 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Periode.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Periode.java @@ -1,20 +1,26 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import lombok.experimental.SuperBuilder; -import no.nav.registre.testnorge.levendearbeidsforhold.util.JavaTimeUtil; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.util.TimeUtil; import java.time.LocalDate; -@Data +@Getter +@Setter @NoArgsConstructor +@AllArgsConstructor @SuperBuilder +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonPropertyOrder({ "fom", @@ -40,23 +46,23 @@ public LocalDate getTom() { @JsonProperty("fom") @Schema(description = "Fra-og-med-dato for periode, format (ISO-8601): yyyy-MM-dd", example = "2014-07-01") public String getFomAsString() { - return JavaTimeUtil.toString(fom); + return TimeUtil.toString(fom); } @JsonProperty("fom") public void setFomAsString(String fom) { - this.fom = JavaTimeUtil.toLocalDate(fom); + this.fom = TimeUtil.toLocalDate(fom); } @JsonProperty("tom") @Schema(description = "Til-og-med-dato for periode, format (ISO-8601): yyyy-MM-dd", example = "2015-12-31") public String getTomAsString() { - return JavaTimeUtil.toString(tom); + return TimeUtil.toString(tom); } @JsonProperty("tom") public void setTomAsString(String tom) { - this.tom = JavaTimeUtil.toLocalDate(tom); + this.tom = TimeUtil.toLocalDate(tom); } @Override diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/PermisjonPermittering.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/PermisjonPermittering.java similarity index 88% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/PermisjonPermittering.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/PermisjonPermittering.java index 93f4898e9f6..cb93d85b0af 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/PermisjonPermittering.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/PermisjonPermittering.java @@ -1,17 +1,21 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; -import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; -@Data +@Getter +@Setter @NoArgsConstructor @AllArgsConstructor @Builder +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonPropertyOrder({ "permisjonPermitteringId", diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Person.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Person.java similarity index 80% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Person.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Person.java index bc79a98d9a8..ca0fcf41f2d 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Person.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Person.java @@ -1,17 +1,21 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; -import lombok.experimental.SuperBuilder; +import lombok.Setter; -@Data +@Getter +@Setter @NoArgsConstructor -@SuperBuilder +@AllArgsConstructor +@Builder @EqualsAndHashCode(callSuper = true) @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonPropertyOrder({ @@ -28,6 +32,8 @@ public class Person extends OpplysningspliktigArbeidsgiver implements Persontype @Schema(description = "Aktør-id", example = "1234567890") private String aktoerId; + private String type; + @Override @JsonIgnore public String getType() { diff --git a/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Persontype.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Persontype.java new file mode 100644 index 00000000000..6d374f95421 --- /dev/null +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Persontype.java @@ -0,0 +1,6 @@ +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; + +public interface Persontype { + + String getType(); +} diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/README.md b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/README.md similarity index 100% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/README.md rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/README.md diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Sporingsinformasjon.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Sporingsinformasjon.java similarity index 83% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Sporingsinformasjon.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Sporingsinformasjon.java index a5f3dc789eb..80c92b41c17 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Sporingsinformasjon.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Sporingsinformasjon.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; @@ -7,16 +7,20 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; -import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; -import no.nav.registre.testnorge.levendearbeidsforhold.util.JavaTimeUtil; +import lombok.Setter; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.util.TimeUtil; import java.time.LocalDateTime; -@Data +@Getter +@Setter @NoArgsConstructor @AllArgsConstructor @Builder +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonPropertyOrder({ "opprettetTidspunkt", @@ -66,22 +70,22 @@ public LocalDateTime getEndretTidspunkt() { @JsonProperty("opprettetTidspunkt") @Schema(description = "Tidspunkt for opprettelse, format (ISO-8601): yyyy-MM-dd'T'HH:mm[:ss[.SSSSSSSSS]]", example = "2018-09-19T12:10:58.059") public String getOpprettetTidspunktAsString() { - return JavaTimeUtil.toString(opprettetTidspunkt); + return TimeUtil.toString(opprettetTidspunkt); } @JsonProperty("opprettetTidspunkt") public void setOpprettetTidspunktAsString(String opprettetTidspunkt) { - this.opprettetTidspunkt = JavaTimeUtil.toLocalDateTime(opprettetTidspunkt); + this.opprettetTidspunkt = TimeUtil.toLocalDateTime(opprettetTidspunkt); } @JsonProperty("endretTidspunkt") @Schema(description = "Tidspunkt for endring, format (ISO-8601): yyyy-MM-dd'T'HH:mm[:ss[.SSSSSSSSS]]", example = "2018-09-19T12:11:20.79") public String getEndretTidspunktAsString() { - return JavaTimeUtil.toString(endretTidspunkt); + return TimeUtil.toString(endretTidspunkt); } @JsonProperty("endretTidspunkt") public void setEndretTidspunktAsString(String endretTidspunkt) { - this.endretTidspunkt = JavaTimeUtil.toLocalDateTime(endretTidspunkt); + this.endretTidspunkt = TimeUtil.toLocalDateTime(endretTidspunkt); } } diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Utenlandsopphold.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Utenlandsopphold.java similarity index 80% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Utenlandsopphold.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Utenlandsopphold.java index a6d61508b40..d9753c97084 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Utenlandsopphold.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Utenlandsopphold.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; @@ -7,16 +7,20 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; -import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; -import no.nav.registre.testnorge.levendearbeidsforhold.util.JavaTimeUtil; +import lombok.Setter; +import no.nav.testnav.libs.dto.levendearbeidsforhold.v1.util.TimeUtil; import java.time.YearMonth; -@Data +@Getter +@Setter @NoArgsConstructor @AllArgsConstructor @Builder +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonPropertyOrder({ "periode", @@ -46,11 +50,11 @@ public YearMonth getRapporteringsperiode() { @JsonProperty("rapporteringsperiode") @Schema(description = "Rapporteringsperiode for utenlandsopphold, format (ISO-8601): yyyy-MM", example = "2017-12") public String getRapporteringsperiodeAsString() { - return JavaTimeUtil.toString(rapporteringsperiode); + return TimeUtil.toString(rapporteringsperiode); } @JsonProperty("rapporteringsperiode") public void setRapporteringsperiodeAsString(String rapporteringsperiode) { - this.rapporteringsperiode = JavaTimeUtil.toYearMonth(rapporteringsperiode); + this.rapporteringsperiode = TimeUtil.toYearMonth(rapporteringsperiode); } } diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Varsel.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Varsel.java similarity index 80% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Varsel.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Varsel.java index a7df47d6b06..579744cd847 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Varsel.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Varsel.java @@ -1,17 +1,21 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; -import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; -@Data +@Getter +@Setter @NoArgsConstructor @AllArgsConstructor @Builder +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonPropertyOrder({ "entitet", diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Varselentitet.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Varselentitet.java similarity index 74% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Varselentitet.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Varselentitet.java index 73abecce19e..dcba495e835 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/domain/v1/Varselentitet.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/Varselentitet.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.domain.v1; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/util/JavaTimeUtil.java b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/util/TimeUtil.java similarity index 93% rename from apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/util/JavaTimeUtil.java rename to libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/util/TimeUtil.java index 589b1396fc6..0920347626f 100644 --- a/apps/levende-arbeidsforhold-service/src/main/java/no/nav/registre/testnorge/levendearbeidsforhold/util/JavaTimeUtil.java +++ b/libs/data-transfer-objects/src/main/java/no/nav/testnav/libs/dto/levendearbeidsforhold/v1/util/TimeUtil.java @@ -1,4 +1,4 @@ -package no.nav.registre.testnorge.levendearbeidsforhold.util; +package no.nav.testnav.libs.dto.levendearbeidsforhold.v1.util; import java.time.LocalDate; import java.time.LocalDateTime; @@ -8,7 +8,7 @@ import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE; import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME; -public class JavaTimeUtil { +public class TimeUtil { private static final String YEAR_MONTH_PATTERN = "yyyy-MM"; diff --git a/proxies/ereg-proxy/config.yml b/proxies/ereg-proxy/config.yml index 64719a9a3e5..6703ff2de68 100644 --- a/proxies/ereg-proxy/config.yml +++ b/proxies/ereg-proxy/config.yml @@ -25,6 +25,8 @@ spec: cluster: dev-gcp - application: testnav-organisasjon-service cluster: dev-gcp + - application: testnav-levende-arbeidsforhold-ansettelse + cluster: dev-gcp liveness: path: /internal/isAlive initialDelay: 4 diff --git a/settings.gradle b/settings.gradle index 17a285fbdea..7b7aac1a8d6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -95,6 +95,8 @@ includeBuild './apps/inntektsmelding-service' includeBuild './apps/jenkins-batch-status-service' includeBuild './apps/joark-dokument-service' includeBuild './apps/kodeverk-service' +includeBuild './apps/levende-arbeidsforhold-ansettelse' +includeBuild './apps/levende-arbeidsforhold-scheduler' includeBuild './apps/levende-arbeidsforhold-service' includeBuild './apps/miljoer-service' includeBuild './apps/oppsummeringsdokument-service' @@ -124,6 +126,8 @@ includeBuild './apps/tilbakemelding-api' includeBuild './apps/tps-messaging-service' includeBuild './apps/udi-stub' includeBuild './apps/varslinger-service' +includeBuild './apps/dollystatus' +includeBuild './apps/skattekort-service' includeBuild './xsd/arbeidsforhold-xsd' @@ -132,6 +136,8 @@ includeBuild './examples/reactive-rest-example' includeBuild './mocks/tokendings-mock' includeBuild './mocks/maskinporten-mock' + + include(':proxies') include(':navikt') include(':apps')