diff --git a/package-lock.json b/package-lock.json index c15975704..68f168848 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,8 +33,8 @@ "@graphql-codegen/typescript": "^4.1.3", "@graphql-codegen/typescript-operations": "^4.4.1", "@graphql-codegen/typescript-react-apollo": "^4.3.2", - "@testing-library/jest-dom": "^6.4.6", - "@testing-library/react": "^16.0.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.2.0", "@types/jest-axe": "^3.5.9", "@types/node": "^22.13.1", "@types/react": "18.3.3", @@ -57,7 +57,7 @@ "vite": "^6.0.11", "vite-plugin-graphql-loader": "^4.0.4", "vite-tsconfig-paths": "^5.1.4", - "vitest": "^3.0.4" + "vitest": "^3.0.5" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -6726,14 +6726,14 @@ } }, "node_modules/@vitest/expect": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.4.tgz", - "integrity": "sha512-Nm5kJmYw6P2BxhJPkO3eKKhGYKRsnqJqf+r0yOGRKpEP+bSCBDsjXgiu1/5QFrnPMEgzfC38ZEjvCFgaNBC0Eg==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.5.tgz", + "integrity": "sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.4", - "@vitest/utils": "3.0.4", + "@vitest/spy": "3.0.5", + "@vitest/utils": "3.0.5", "chai": "^5.1.2", "tinyrainbow": "^2.0.0" }, @@ -6742,9 +6742,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.4.tgz", - "integrity": "sha512-ts0fba+dEhK2aC9PFuZ9LTpULHpY/nd6jhAQ5IMU7Gaj7crPCTdCFfgvXxruRBLFS+MLraicCuFXxISEq8C93g==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.5.tgz", + "integrity": "sha512-CjUtdmpOcm4RVtB+up8r2vVDLR16Mgm/bYdkGFe3Yj/scRfCpbSi2W/BDSDcFK7ohw8UXvjMbOp9H4fByd/cOA==", "dev": true, "license": "MIT", "dependencies": { @@ -6755,13 +6755,13 @@ } }, "node_modules/@vitest/runner": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.4.tgz", - "integrity": "sha512-dKHzTQ7n9sExAcWH/0sh1elVgwc7OJ2lMOBrAm73J7AH6Pf9T12Zh3lNE1TETZaqrWFXtLlx3NVrLRb5hCK+iw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.5.tgz", + "integrity": "sha512-BAiZFityFexZQi2yN4OX3OkJC6scwRo8EhRB0Z5HIGGgd2q+Nq29LgHU/+ovCtd0fOfXj5ZI6pwdlUmC5bpi8A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.0.4", + "@vitest/utils": "3.0.5", "pathe": "^2.0.2" }, "funding": { @@ -6769,13 +6769,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.4.tgz", - "integrity": "sha512-+p5knMLwIk7lTQkM3NonZ9zBewzVp9EVkVpvNta0/PlFWpiqLaRcF4+33L1it3uRUCh0BGLOaXPPGEjNKfWb4w==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.5.tgz", + "integrity": "sha512-GJPZYcd7v8QNUJ7vRvLDmRwl+a1fGg4T/54lZXe+UOGy47F9yUfE18hRCtXL5aHN/AONu29NGzIXSVFh9K0feA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.4", + "@vitest/pretty-format": "3.0.5", "magic-string": "^0.30.17", "pathe": "^2.0.2" }, @@ -6784,9 +6784,9 @@ } }, "node_modules/@vitest/spy": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.4.tgz", - "integrity": "sha512-sXIMF0oauYyUy2hN49VFTYodzEAu744MmGcPR3ZBsPM20G+1/cSW/n1U+3Yu/zHxX2bIDe1oJASOkml+osTU6Q==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.5.tgz", + "integrity": "sha512-5fOzHj0WbUNqPK6blI/8VzZdkBlQLnT25knX0r4dbZI9qoZDf3qAdjoMmDcLG5A83W6oUUFJgUd0EYBc2P5xqg==", "dev": true, "license": "MIT", "dependencies": { @@ -6797,13 +6797,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.4.tgz", - "integrity": "sha512-8BqC1ksYsHtbWH+DfpOAKrFw3jl3Uf9J7yeFh85Pz52IWuh1hBBtyfEbRNNZNjl8H8A5yMLH9/t+k7HIKzQcZQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.5.tgz", + "integrity": "sha512-N9AX0NUoUtVwKwy21JtwzaqR5L5R5A99GAbrHfCCXK1lp593i/3AZAXhSP43wRQuxYsflrdzEfXZFo1reR1Nkg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.4", + "@vitest/pretty-format": "3.0.5", "loupe": "^3.1.2", "tinyrainbow": "^2.0.0" }, @@ -15691,9 +15691,9 @@ } }, "node_modules/vite-node": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.4.tgz", - "integrity": "sha512-7JZKEzcYV2Nx3u6rlvN8qdo3QV7Fxyt6hx+CCKz9fbWxdX5IvUOmTWEAxMrWxaiSf7CKGLJQ5rFu8prb/jBjOA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.5.tgz", + "integrity": "sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A==", "dev": true, "license": "MIT", "dependencies": { @@ -15771,19 +15771,19 @@ } }, "node_modules/vitest": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.4.tgz", - "integrity": "sha512-6XG8oTKy2gnJIFTHP6LD7ExFeNLxiTkK3CfMvT7IfR8IN+BYICCf0lXUQmX7i7JoxUP8QmeP4mTnWXgflu4yjw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.5.tgz", + "integrity": "sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.0.4", - "@vitest/mocker": "3.0.4", - "@vitest/pretty-format": "^3.0.4", - "@vitest/runner": "3.0.4", - "@vitest/snapshot": "3.0.4", - "@vitest/spy": "3.0.4", - "@vitest/utils": "3.0.4", + "@vitest/expect": "3.0.5", + "@vitest/mocker": "3.0.5", + "@vitest/pretty-format": "^3.0.5", + "@vitest/runner": "3.0.5", + "@vitest/snapshot": "3.0.5", + "@vitest/spy": "3.0.5", + "@vitest/utils": "3.0.5", "chai": "^5.1.2", "debug": "^4.4.0", "expect-type": "^1.1.0", @@ -15795,7 +15795,7 @@ "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.0.4", + "vite-node": "3.0.5", "why-is-node-running": "^2.3.0" }, "bin": { @@ -15811,8 +15811,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.0.4", - "@vitest/ui": "3.0.4", + "@vitest/browser": "3.0.5", + "@vitest/ui": "3.0.5", "happy-dom": "*", "jsdom": "*" }, @@ -15935,13 +15935,13 @@ } }, "node_modules/vitest/node_modules/@vitest/mocker": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.4.tgz", - "integrity": "sha512-gEef35vKafJlfQbnyOXZ0Gcr9IBUsMTyTLXsEQwuyYAerpHqvXhzdBnDFuHLpFqth3F7b6BaFr4qV/Cs1ULx5A==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.5.tgz", + "integrity": "sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.4", + "@vitest/spy": "3.0.5", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, diff --git a/package.json b/package.json index b5fc43db1..49742bc21 100644 --- a/package.json +++ b/package.json @@ -29,8 +29,8 @@ "@graphql-codegen/typescript": "^4.1.3", "@graphql-codegen/typescript-operations": "^4.4.1", "@graphql-codegen/typescript-react-apollo": "^4.3.2", - "@testing-library/jest-dom": "^6.4.6", - "@testing-library/react": "^16.0.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.2.0", "@types/jest-axe": "^3.5.9", "@types/node": "^22.13.1", "@types/react": "18.3.3", @@ -53,7 +53,7 @@ "vite": "^6.0.11", "vite-plugin-graphql-loader": "^4.0.4", "vite-tsconfig-paths": "^5.1.4", - "vitest": "^3.0.4" + "vitest": "^3.0.5" }, "scripts": { "gql:cp_schema": "cp ../arbeidsgiver-notifikasjon-produsent-api/app/src/main/resources/bruker.graphql ./bruker.graphql", diff --git a/src/Pages/OrganisasjonerOgTilgangerContext.test.tsx b/src/Pages/OrganisasjonerOgTilgangerContext.test.tsx new file mode 100644 index 000000000..b22c74ee4 --- /dev/null +++ b/src/Pages/OrganisasjonerOgTilgangerContext.test.tsx @@ -0,0 +1,142 @@ +import { expect } from 'vitest'; +import { setupServer } from 'msw/node'; +import { http, HttpResponse } from 'msw'; +import { useBeregnOrganisasjonstre } from './OrganisasjonerOgTilgangerContext'; +import { act, renderHook } from '@testing-library/react'; +import React, { ReactNode } from 'react'; +import { SWRConfig } from 'swr'; +import { AlertsProvider } from './Alerts'; +import { OrganisasjonerOgTilgangerProvider } from './OrganisasjonerOgTilgangerProvider'; + +describe('OrganisasjonerOgTilgangerContext', () => { + beforeAll(() => server.listen({ onUnhandledRequest: 'warn' })); + afterEach(() => server.resetHandlers()); + afterAll(() => server.close()); + + it('useBeregnOrganisasjonstre fletter altinn og digisyfo tilganger riktig', async () => { + server.use( + http.get(`${__BASE_PATH__}/api/userInfo/v3`, () => + HttpResponse.json({ + organisasjoner: [ + { + orgnr: '1', + navn: '1', + organisasjonsform: 'AS', + underenheter: [ + { + orgnr: '1.1', + navn: '1.1', + organisasjonsform: 'ORGL', + underenheter: [ + { + orgnr: '1.1.1', + navn: '1.1.1', + organisasjonsform: 'BEDR', + underenheter: [], + }, + ], + }, + ], + }, + ], + digisyfoOrganisasjoner: [ + { + orgnr: '1', + navn: '1', + organisasjonsform: 'AS', + antallSykmeldte: 0, + underenheter: [ + { + orgnr: '1.2', + navn: '1.2', + organisasjonsform: 'ORGL', + antallSykmeldte: 0, + underenheter: [ + { + orgnr: '1.2.1', + navn: '1.2.1', + organisasjonsform: 'BEDR', + antallSykmeldte: 0, + underenheter: [], + }, + ], + }, + ], + }, + ], + tilganger: {}, + altinnError: false, + digisyfoError: false, + refusjoner: [], + }) + ) + ); + vi.useFakeTimers(); + const { result } = renderHook(() => useBeregnOrganisasjonstre(), { + wrapper: ({ children }: { children: ReactNode }) => { + return ( + new Map(), + shouldRetryOnError: (err) => { + // liten hack for å tvinge evt. fetch error til å bli logget + // krever disableConsoleIntercept: true + console.error(err); + return false; + }, + }} + > + + + {children} + + + + ); + }, + }); + await act(async () => { + vi.runOnlyPendingTimers(); + vi.useRealTimers(); + }); + + expect(result.current?.organisasjonstre).toEqual([ + { + orgnr: '1', + navn: '1', + organisasjonsform: 'AS', + underenheter: [ + { + orgnr: '1.1', + navn: '1.1', + organisasjonsform: 'ORGL', + underenheter: [ + { + orgnr: '1.1.1', + navn: '1.1.1', + organisasjonsform: 'BEDR', + underenheter: [], + }, + ], + }, + { + orgnr: '1.2', + navn: '1.2', + organisasjonsform: 'ORGL', + underenheter: [ + { + orgnr: '1.2.1', + navn: '1.2.1', + organisasjonsform: 'BEDR', + underenheter: [], + }, + ], + }, + ], + }, + ]); + }); +}); + +const server = setupServer(); diff --git a/src/Pages/OrganisasjonerOgTilgangerContext.ts b/src/Pages/OrganisasjonerOgTilgangerContext.ts index 2ba7b243e..5e3b4c000 100644 --- a/src/Pages/OrganisasjonerOgTilgangerContext.ts +++ b/src/Pages/OrganisasjonerOgTilgangerContext.ts @@ -1,7 +1,14 @@ -import React, { useContext } from 'react'; +import React, { useContext, useEffect, useMemo } from 'react'; import * as Record from '../utils/Record'; -import { AltinntjenesteId } from '../altinn/tjenester'; -import Immutable from 'immutable'; +import { altinntjeneste, AltinntjenesteId } from '../altinn/tjenester'; +import Immutable, { Set } from 'immutable'; +import { AltinnTilgangssøknad, useAltinnTilgangssøknader } from '../altinn/tilganger'; +import { useUserInfo } from '../hooks/useUserInfo'; +import { AlertContext } from './Alerts'; +import amplitude from '../utils/amplitude'; +import { Identify } from '@amplitude/analytics-browser'; +import { alleOrganisasjonerFlatt, mapRecursive, mergeOrgTre } from '../utils/util'; +import { findRecursive } from '@navikt/virksomhetsvelger'; export type orgnr = string; @@ -35,8 +42,8 @@ export type OrganisasjonerOgTilgangerContext = { organisasjonstre: Organisasjon[]; organisasjonsInfo: Record; organisasjonerFlatt: Organisasjon[]; - parentMap: Immutable.Map; - childrenMap: Immutable.Map; + orgnrTilParentMap: Immutable.Map; + orgnrTilChildrenMap: Immutable.Map; altinnTilgangssøknad: Record>; }; @@ -52,3 +59,203 @@ export const useOrganisasjonerOgTilgangerContext = () => { } return organisasjonerOgTilgangerContext; }; + +export const useBeregnAltinnTilgangssøknad = (): + | Record> + | undefined => { + const altinnTilgangssøknader = useAltinnTilgangssøknader(); + const { userInfo } = useUserInfo(); + + return useMemo(() => { + if (userInfo === undefined) { + return undefined; + } + + return Record.fromEntries( + userInfo.organisasjoner.map((org) => { + return [ + org.orgnr, + Record.map( + altinntjeneste, + (_: AltinntjenesteId, { tjenestekode, tjenesteversjon }) => + sjekkTilgangssøknader( + org.orgnr, + tjenestekode, + tjenesteversjon, + altinnTilgangssøknader + ) + ), + ]; + }) + ); + }, [userInfo, altinnTilgangssøknader]); +}; + +export const sjekkTilgangssøknader = ( + orgnr: orgnr, + tjenestekode: string, + tjenesteversjon: string, + altinnTilgangssøknader: AltinnTilgangssøknad[] +): Søknadsstatus => { + const søknader = altinnTilgangssøknader.filter( + (s) => + s.orgnr === orgnr && + s.serviceCode === tjenestekode && + s.serviceEdition.toString() === tjenesteversjon + ); + + if (søknader.some((_) => _.status === 'Unopened')) { + return { tilgang: 'søkt' }; + } + + const søknad = søknader.find((_) => _.status === 'Created'); + if (søknad) { + return { tilgang: 'søknad opprettet', url: søknad.submitUrl }; + } + + if (søknader.some((_) => _.status === 'Accepted')) { + return { tilgang: 'godkjent' }; + } + return { tilgang: 'ikke søkt' }; +}; + +export const useBeregnOrganisasjonsInfo = (): + | { + organisasjonsInfo: undefined; + orgnrTilParentMap: undefined; + orgnrTilChildrenMap: undefined; + organisasjonerFlatt: undefined; + } + | { + organisasjonsInfo: Record; + orgnrTilParentMap: Immutable.Map; + orgnrTilChildrenMap: Immutable.Map; + organisasjonerFlatt: Organisasjon[]; + } => { + const { userInfo } = useUserInfo(); + const { setSystemAlert } = useContext(AlertContext); + + useEffect(() => { + setSystemAlert('UserInfoAltinn', userInfo?.altinnError ?? false); + setSystemAlert('UserInfoDigiSyfo', userInfo?.digisyfoError ?? false); + + if (userInfo !== undefined) { + amplitude.identify( + new Identify() + .set('syfotilgang', userInfo.digisyfoOrganisasjoner.length > 0) + .set('buildTimestamp', __BUILD_TIMESTAMP__) + ); + } + }, [userInfo]); + + return useMemo(() => { + if (userInfo === undefined) { + return { + organisasjonsInfo: undefined, + orgnrTilParentMap: undefined, + orgnrTilChildrenMap: undefined, + virksomheter: undefined, + }; + } + + const altinnOrganisasjonerFlatt = alleOrganisasjonerFlatt(userInfo.organisasjoner); + const digisyfoOrganisasjonerFlatt = alleOrganisasjonerFlatt( + userInfo.digisyfoOrganisasjoner + ); + const organisasjonerFlatt: Organisasjon[] = [ + ...altinnOrganisasjonerFlatt, + ...digisyfoOrganisasjonerFlatt, + ]; + + const orgnrTilParent = Immutable.Map( + organisasjonerFlatt.flatMap((org) => { + const parent = organisasjonerFlatt.find((it) => + it.underenheter.some((it) => it.orgnr === org.orgnr) + ); + if (parent === undefined) { + return []; + } + return [[org.orgnr, parent]]; + }) + ); + + const organisasjonsInfo = Record.fromEntries( + organisasjonerFlatt.map((org) => { + const refusjonstatus = userInfo.refusjoner.find( + ({ virksomhetsnummer }) => virksomhetsnummer === org.orgnr + ); + + const digisyfoOrganisasjon = findRecursive( + userInfo.digisyfoOrganisasjoner, + ({ orgnr }) => orgnr === org.orgnr + ); + return [ + org.orgnr, + { + øversteLedd: hentØversteLedd(org, orgnrTilParent), + parent: orgnrTilParent.get(org.orgnr), + organisasjon: org, + altinntilgang: Record.map( + userInfo.tilganger, + (_: AltinntjenesteId, orgnrMedTilgang: Set): boolean => + orgnrMedTilgang.has(org.orgnr) + ), + syfotilgang: digisyfoOrganisasjon !== undefined, + antallSykmeldte: digisyfoOrganisasjon?.antallSykmeldte ?? 0, + reporteetilgang: altinnOrganisasjonerFlatt.some( + ({ orgnr }) => orgnr === org.orgnr + ), + refusjonstatus: refusjonstatus?.statusoversikt ?? {}, + refusjonstatustilgang: refusjonstatus?.tilgang ?? false, + }, + ]; + }) + ); + + return { + organisasjonsInfo, + orgnrTilParentMap: orgnrTilParent.mapEntries(([key, value]) => [key, value.orgnr]), + orgnrTilChildrenMap: orgnrTilParent.reduce( + (acc, parent, child) => + acc.update(parent.orgnr, [], (value) => value.concat(child)), + Immutable.Map() + ), + organisasjonerFlatt, + }; + }, [userInfo]); +}; + +export const useBeregnOrganisasjonstre = (): { organisasjonstre: Organisasjon[] } => { + const { userInfo } = useUserInfo(); + + return useMemo(() => { + if (userInfo === undefined) { + return { organisasjonstre: [] }; + } + + // TODO: naive implementation, perhaps need to deep check for duplicates + const organisasjonstre: Organisasjon[] = mergeOrgTre( + userInfo.organisasjoner, + mapRecursive(userInfo.digisyfoOrganisasjoner, (org) => ({ + orgnr: org.orgnr, + navn: org.navn, + organisasjonsform: org.organisasjonsform, + underenheter: org.underenheter, + })) + ); + + return { organisasjonstre }; + }, [userInfo]); +}; + +export const hentØversteLedd = ( + org: Organisasjon | undefined, + underenhetTilParent: Immutable.Map +): Organisasjon | undefined => { + if (org === undefined) return undefined; + + const parentOrg = underenhetTilParent.get(org.orgnr); + if (parentOrg === undefined) return org; + + return hentØversteLedd(parentOrg, underenhetTilParent); +}; diff --git a/src/Pages/OrganisasjonerOgTilgangerProvider.tsx b/src/Pages/OrganisasjonerOgTilgangerProvider.tsx index 078fdf989..cfea14351 100644 --- a/src/Pages/OrganisasjonerOgTilgangerProvider.tsx +++ b/src/Pages/OrganisasjonerOgTilgangerProvider.tsx @@ -1,214 +1,17 @@ -import React, { FunctionComponent, PropsWithChildren, useContext, useEffect, useMemo } from 'react'; +import React, { FunctionComponent, PropsWithChildren } from 'react'; import * as Record from '../utils/Record'; -import { AltinnTilgangssøknad, useAltinnTilgangssøknader } from '../altinn/tilganger'; -import { altinntjeneste, AltinntjenesteId } from '../altinn/tjenester'; -import amplitude from '../utils/amplitude'; -import { AlertContext } from './Alerts'; -import Immutable, { Set } from 'immutable'; -import { useUserInfo } from '../hooks/useUserInfo'; import { ManglerTilganger } from './ManglerTilganger/ManglerTilganger'; import { SpinnerMedBanner } from './Banner'; -import { Identify } from '@amplitude/analytics-browser'; -import { flatUtTre } from '../utils/util'; -import { findRecursive } from '@navikt/virksomhetsvelger'; import { - Organisasjon, OrganisasjonerOgTilgangerContext, - OrganisasjonInfo, - orgnr, - Søknadsstatus, + useBeregnAltinnTilgangssøknad, + useBeregnOrganisasjonsInfo, + useBeregnOrganisasjonstre, } from './OrganisasjonerOgTilgangerContext'; -// @ts-ignore -const buildTimestamp = __BUILD_TIMESTAMP__; - -const useBeregnAltinnTilgangssøknad = (): - | Record> - | undefined => { - const altinnTilgangssøknader = useAltinnTilgangssøknader(); - const { userInfo } = useUserInfo(); - - return useMemo(() => { - if (userInfo === undefined) { - return undefined; - } - - return Record.fromEntries( - userInfo.organisasjoner.map((org) => { - return [ - org.orgnr, - Record.map( - altinntjeneste, - (_: AltinntjenesteId, { tjenestekode, tjenesteversjon }) => - sjekkTilgangssøknader( - org.orgnr, - tjenestekode, - tjenesteversjon, - altinnTilgangssøknader - ) - ), - ]; - }) - ); - }, [userInfo, altinnTilgangssøknader]); -}; - -const sjekkTilgangssøknader = ( - orgnr: orgnr, - tjenestekode: string, - tjenesteversjon: string, - altinnTilgangssøknader: AltinnTilgangssøknad[] -): Søknadsstatus => { - const søknader = altinnTilgangssøknader.filter( - (s) => - s.orgnr === orgnr && - s.serviceCode === tjenestekode && - s.serviceEdition.toString() === tjenesteversjon - ); - - if (søknader.some((_) => _.status === 'Unopened')) { - return { tilgang: 'søkt' }; - } - - const søknad = søknader.find((_) => _.status === 'Created'); - if (søknad) { - return { tilgang: 'søknad opprettet', url: søknad.submitUrl }; - } - - if (søknader.some((_) => _.status === 'Accepted')) { - return { tilgang: 'godkjent' }; - } - return { tilgang: 'ikke søkt' }; -}; - -const useBeregnOrganisasjonsInfo = (): - | { - organisasjonsInfo: undefined; - parentMap: undefined; - childrenMap: undefined; - organisasjonerFlatt: undefined; - } - | { - organisasjonsInfo: Record; - parentMap: Immutable.Map; - childrenMap: Immutable.Map; - organisasjonerFlatt: Organisasjon[]; - } => { - const { userInfo } = useUserInfo(); - const { setSystemAlert } = useContext(AlertContext); - - useEffect(() => { - setSystemAlert('UserInfoAltinn', userInfo?.altinnError ?? false); - setSystemAlert('UserInfoDigiSyfo', userInfo?.digisyfoError ?? false); - - if (userInfo !== undefined) { - amplitude.identify( - new Identify() - .set('syfotilgang', userInfo.digisyfoOrganisasjoner.length > 0) - .set('buildTimestamp', buildTimestamp) - ); - } - }, [userInfo]); - - return useMemo(() => { - if (userInfo === undefined) { - return { - organisasjonsInfo: undefined, - parentMap: undefined, - childrenMap: undefined, - virksomheter: undefined, - }; - } - - const organisasjonerFlatt: Organisasjon[] = [ - ...flatUtTre(userInfo.organisasjoner).flatMap((it) => [it, ...it.underenheter]), - ...flatUtTre(userInfo.digisyfoOrganisasjoner).flatMap((it: Organisasjon) => [ - it, - ...it.underenheter, - ]), - ]; - - const orgnrTilParent = Immutable.Map( - organisasjonerFlatt.flatMap((org) => { - const parent = organisasjonerFlatt.find((it) => - it.underenheter.some((it) => it.orgnr === org.orgnr) - ); - if (parent === undefined) { - return []; - } - return [[org.orgnr, parent]]; - }) - ); - - const organisasjonsInfo = Record.fromEntries( - organisasjonerFlatt.map((org) => { - const refusjonstatus = userInfo.refusjoner.find( - ({ virksomhetsnummer }) => virksomhetsnummer === org.orgnr - ); - - const digisyfoOrganisasjon = findRecursive( - userInfo.digisyfoOrganisasjoner, - ({ orgnr }) => orgnr === org.orgnr - ); - return [ - org.orgnr, - { - øversteLedd: hentØversteLedd(org, orgnrTilParent), - parent: orgnrTilParent.get(org.orgnr), - organisasjon: org, - altinntilgang: Record.map( - userInfo.tilganger, - (_: AltinntjenesteId, orgnrMedTilgang: Set): boolean => - orgnrMedTilgang.has(org.orgnr) - ), - syfotilgang: digisyfoOrganisasjon !== undefined, - antallSykmeldte: digisyfoOrganisasjon?.antallSykmeldte ?? 0, - reporteetilgang: organisasjonerFlatt.some( - ({ orgnr }) => orgnr === org.orgnr - ), - refusjonstatus: refusjonstatus?.statusoversikt ?? {}, - refusjonstatustilgang: refusjonstatus?.tilgang ?? false, - }, - ]; - }) - ); - - return { - organisasjonsInfo, - parentMap: orgnrTilParent.mapEntries(([key, value]) => [key, value.orgnr]), - childrenMap: orgnrTilParent.reduce( - (acc, parent, child) => - acc.update(parent.orgnr, [], (value) => value.concat(child)), - Immutable.Map() - ), - organisasjonerFlatt, - }; - }, [userInfo]); -}; - -const useBeregnOrganisasjonstre = (): { organisasjonstre: Organisasjon[] } => { - const { userInfo } = useUserInfo(); - - return useMemo(() => { - if (userInfo === undefined) { - return { organisasjonstre: [] }; - } - - // TODO: naive implementation, perhaps need to deep check for duplicates - const organisasjonstre: Organisasjon[] = [...userInfo.organisasjoner]; - for (const digisyfoOrganisasjon of userInfo.digisyfoOrganisasjoner) { - if (organisasjonstre.every(({ orgnr }) => orgnr !== digisyfoOrganisasjon.orgnr)) { - organisasjonstre.push(digisyfoOrganisasjon); - } - } - - return { organisasjonstre }; - }, [userInfo]); -}; - export const OrganisasjonerOgTilgangerProvider: FunctionComponent = (props) => { const { organisasjonstre } = useBeregnOrganisasjonstre(); - const { organisasjonsInfo, organisasjonerFlatt, parentMap, childrenMap } = + const { organisasjonsInfo, organisasjonerFlatt, orgnrTilParentMap, orgnrTilChildrenMap } = useBeregnOrganisasjonsInfo(); const altinnTilgangssøknad = useBeregnAltinnTilgangssøknad(); @@ -233,8 +36,8 @@ export const OrganisasjonerOgTilgangerProvider: FunctionComponent ); }; - -const hentØversteLedd = ( - org: Organisasjon | undefined, - underenhetTilParent: Immutable.Map -): Organisasjon | undefined => { - if (org === undefined) return undefined; - - const parentOrg = underenhetTilParent.get(org.orgnr); - if (parentOrg === undefined) return org; - - return hentØversteLedd(parentOrg, underenhetTilParent); -}; diff --git a/src/Pages/Saksoversikt/FilterChips.tsx b/src/Pages/Saksoversikt/FilterChips.tsx index 8a7327491..6593906a1 100644 --- a/src/Pages/Saksoversikt/FilterChips.tsx +++ b/src/Pages/Saksoversikt/FilterChips.tsx @@ -3,7 +3,7 @@ import { Button, Chips, Heading } from '@navikt/ds-react'; import { oppgaveTilstandTilTekst } from './Saksfilter/Saksfilter'; import { VirksomhetChips } from './Saksfilter/VirksomhetChips'; import { Set } from 'immutable'; -import { count } from '../../utils/util'; +import { count, flatUtTre } from '../../utils/util'; import { Filter, State } from './useOversiktStateTransitions'; import { Organisasjon } from '../OrganisasjonerOgTilgangerContext'; import { Collapse, Expand } from '@navikt/ds-icons'; @@ -16,7 +16,10 @@ export type FilterChipsProps = { }; export const FilterChips = ({ state, byttFilter }: FilterChipsProps) => { - const { organisasjonstre, childrenMap, parentMap } = useOrganisasjonerOgTilgangerContext(); + const { organisasjonstre, orgnrTilChildrenMap, orgnrTilParentMap } = + useOrganisasjonerOgTilgangerContext(); + const organisasjonstreFlat = flatUtTre(organisasjonstre); + const alleOrganisasjoner = organisasjonstreFlat.flatMap((it) => [it, ...it.underenheter]); const onTømAlleFilter = () => { byttFilter({ @@ -35,7 +38,7 @@ export const FilterChips = ({ state, byttFilter }: FilterChipsProps) => { >(() => { const chips: (Organisasjon & { erHovedenhet: boolean })[] = []; - for (let { underenheter, ...hovedenhet } of organisasjonstre) { + for (let { underenheter, ...hovedenhet } of alleOrganisasjoner) { if (state.filter.virksomheter.has(hovedenhet.orgnr)) { const antallUnderValgt = count(underenheter, (it) => state.filter.virksomheter.has(it.orgnr) @@ -118,11 +121,11 @@ export const FilterChips = ({ state, byttFilter }: FilterChipsProps) => { let valgte = state.filter.virksomheter.remove(virksomhet.orgnr); // om virksomhet.OrganizatonNumber er siste underenhet, fjern hovedenhet også. - const parent = parentMap.get(virksomhet.orgnr); + const parent = orgnrTilParentMap.get(virksomhet.orgnr); if (parent === undefined) { return; } - const underenheter = childrenMap.get(parent) ?? []; + const underenheter = orgnrTilChildrenMap.get(parent) ?? []; if (underenheter.every((it) => !valgte.has(it))) { valgte = valgte.remove(parent); } diff --git a/src/Pages/Saksoversikt/Saksfilter/Virksomhetsmeny/Virksomhetsmeny.tsx b/src/Pages/Saksoversikt/Saksfilter/Virksomhetsmeny/Virksomhetsmeny.tsx index d0adf2a5f..95593f399 100644 --- a/src/Pages/Saksoversikt/Saksfilter/Virksomhetsmeny/Virksomhetsmeny.tsx +++ b/src/Pages/Saksoversikt/Saksfilter/Virksomhetsmeny/Virksomhetsmeny.tsx @@ -19,10 +19,16 @@ export const Virksomhetsmeny = ({ valgteEnheter: valgteEnheterInput, setValgteEnheter, }: VirksomhetsmenyProps) => { - const { organisasjonstre, parentMap, childrenMap } = useOrganisasjonerOgTilgangerContext(); - const alleOrganisasjoner = useMemo( - () => flatUtTre(organisasjonstre).flatMap((it) => [it, ...it.underenheter]), - [organisasjonstre] + const { organisasjonstre, orgnrTilParentMap, orgnrTilChildrenMap } = + useOrganisasjonerOgTilgangerContext(); + + const organisasjonstreFlat = flatUtTre(organisasjonstre); + const alleOrganisasjoner = organisasjonstreFlat.flatMap((it) => [it, ...it.underenheter]); + const parentMap = orgnrTilParentMap.filter((parent, _child) => + organisasjonstreFlat.some((it) => it.orgnr === parent) + ); + const childrenMap = orgnrTilChildrenMap.filter((_children, parent) => + organisasjonstreFlat.some((it) => it.orgnr === parent) ); const parentsOf = (orgnr: Set): Set => @@ -70,6 +76,7 @@ export const Virksomhetsmeny = ({ // uten at hovedenhet er huket av. const lagtTil = nyeValgte.subtract(valgteEnheter); const implisittValgteHovedenheter = parentsOf(lagtTil); + console.log('implisittValgteHovedenheter', implisittValgteHovedenheter.toArray()); return nyeValgte.subtract(implisittFjernedUnderenehter).union(implisittValgteHovedenheter); }; @@ -96,7 +103,9 @@ export const Virksomhetsmeny = ({ }; const onCheckboxGroupChange = (checkedEnheter: string[]) => { + console.log(checkedEnheter); const nyveValgte = utledNyeValgte(Set(checkedEnheter)); + console.error('nyveValgte', nyveValgte.toArray()); setValgteEnheter(nyveValgte); amplitudeValgteVirksomheter(nyveValgte); }; @@ -113,7 +122,7 @@ export const Virksomhetsmeny = ({ onChange={onCheckboxGroupChange} >
    - {organisasjonstre.map((hovedenhet) => { + {organisasjonstreFlat.map((hovedenhet) => { const underenheter = hovedenhet.underenheter; if (søketreff && !søketreff.has(hovedenhet.orgnr)) { return null; diff --git a/src/mocks/scenarios/dagligLederScenario.ts b/src/mocks/scenarios/dagligLederScenario.ts index 9fc4dfbaf..980892454 100644 --- a/src/mocks/scenarios/dagligLederScenario.ts +++ b/src/mocks/scenarios/dagligLederScenario.ts @@ -13,6 +13,7 @@ import { alleSaker } from '../brukerApi/alleSaker'; import { alleKalenderavtaler } from '../brukerApi/alleKalenderavtaler'; import { alleNotifikasjoner } from '../brukerApi/alleNotifikasjoner'; import { Merkelapp } from '../brukerApi/alleMerkelapper'; +import { mapRecursive } from '../../utils/util'; const alleTilganger = [ '5216:1', // sykefraværsstatistikk @@ -55,11 +56,24 @@ const underenheter = [ }, ]; +const orgledd = { + orgnr: orgnr(), + navn: faker.company.name(), + organisasjonsform: 'ORGL', + underenheter: [ + { + orgnr: orgnr(), + navn: faker.company.name(), + organisasjonsform: 'ORGL', + underenheter: underenheter.slice(0, 1), + }, + ], +}; export const dagligLederOrganisasjon = { orgnr: orgnr(), navn: faker.company.name(), organisasjonsform: 'AS', - underenheter, + underenheter: [...underenheter.slice(1), orgledd], }; export const dagligLederScenario = [ @@ -74,16 +88,10 @@ export const dagligLederScenario = [ ]) ), digisyfoError: false, - digisyfoOrganisasjoner: [ - { - ...dagligLederOrganisasjon, - antallSykmeldte: faker.number.int({ min: 0, max: 10 }), - underenheter: dagligLederOrganisasjon.underenheter.map((o) => ({ - ...o, - antallSykmeldte: faker.number.int({ min: 0, max: 10 }), - })), - }, - ], + digisyfoOrganisasjoner: mapRecursive([dagligLederOrganisasjon], (org) => ({ + ...org, + antallSykmeldte: faker.number.int({ min: 0, max: 10 }), + })), refusjoner: underenheter.map(({ orgnr }) => ({ virksomhetsnummer: orgnr, statusoversikt: { diff --git a/src/tests/A11y.test.tsx b/src/tests/A11y.test.tsx index 3036f2e5a..a444d2d8f 100644 --- a/src/tests/A11y.test.tsx +++ b/src/tests/A11y.test.tsx @@ -10,7 +10,10 @@ import { NotifikasjonWidgetProvider } from '@navikt/arbeidsgiver-notifikasjon-wi import { MemoryRouter } from 'react-router-dom'; import { useOrganisasjonsDetaljerContext } from '../Pages/OrganisasjonsDetaljerContext'; import { OrganisasjonerOgTilgangerProvider } from '../Pages/OrganisasjonerOgTilgangerProvider'; -import { server } from './mocks'; +import { setupServer } from 'msw/node'; +import { graphql, http, HttpResponse } from 'msw'; +import { orgnr } from '../mocks/brukerApi/helpers'; +import { faker } from '@faker-js/faker'; describe('Hovedside', () => { beforeAll(() => server.listen()); @@ -38,12 +41,9 @@ const MedValgtOrganisasjon: FC<{ children: ReactNode }> = ({ children }) => { const { organisasjonsInfo } = useOrganisasjonerOgTilgangerContext(); const { valgtOrganisasjon, endreOrganisasjon } = useOrganisasjonsDetaljerContext(); - console.error('valgtOrganisasjon', valgtOrganisasjon); useEffect(() => { - console.error('useEffect.valgtOrganisasjon', valgtOrganisasjon); if (valgtOrganisasjon.organisasjon.orgnr === '182345674') return; endreOrganisasjon(organisasjonsInfo['182345674'].organisasjon); - console.error('useEffect.endreOrganisasjon', organisasjonsInfo['182345674'].organisasjon); }, [valgtOrganisasjon, organisasjonsInfo]); return ( @@ -63,6 +63,8 @@ const ComponentTestEnabler: FC<{ children: ReactNode }> = ({ children }) => { > new Map(), shouldRetryOnError: (err) => { // liten hack for å tvinge evt. fetch error til å bli logget console.error(err); @@ -82,3 +84,608 @@ const ComponentTestEnabler: FC<{ children: ReactNode }> = ({ children }) => { ); }; + +const server = setupServer( + http.get(`${__BASE_PATH__}/api/userInfo/v3`, () => + HttpResponse.json({ + altinnError: false, + organisasjoner: [ + { + orgnr: orgnr(), + underenheter: [ + { + orgnr: '182345674', + underenheter: [], + navn: faker.company.name(), + organisasjonsform: 'BEDR', + }, + { + orgnr: '118345674', + underenheter: [], + navn: faker.company.name(), + organisasjonsform: 'BEDR', + }, + { + orgnr: '119985432', + underenheter: [], + navn: faker.company.name(), + organisasjonsform: 'BEDR', + }, + { + orgnr: '119988432', + underenheter: [], + navn: faker.company.name(), + organisasjonsform: 'BEDR', + }, + ], + navn: faker.company.name(), + organisasjonsform: 'AS', + }, + ], + tilganger: { + '5384:1': ['182345674', '118345674', '119985432', '119988432'], + '4936:1': ['182345674', '118345674', '119985432', '119988432'], + '4826:1': ['182345674', '118345674', '119985432', '119988432'], + '5332:1': ['182345674', '118345674', '119985432', '119988432'], + '5441:1': ['182345674', '118345674', '119985432', '119988432'], + '5516:1': ['182345674', '118345674', '119985432', '119988432'], + '5516:2': ['182345674', '118345674', '119985432', '119988432'], + '5516:3': ['182345674', '118345674', '119985432', '119988432'], + '5516:4': ['182345674', '118345674', '119985432', '119988432'], + '5516:5': ['182345674', '118345674', '119985432', '119988432'], + '3403:1': ['182345674', '118345674', '119985432', '119988432'], + '5934:1': ['182345674', '118345674', '119985432', '119988432'], + '5078:1': ['182345674', '118345674', '119985432', '119988432'], + '5278:1': ['182345674', '118345674', '119985432', '119988432'], + '5902:1': ['182345674', '118345674', '119985432', '119988432'], + }, + digisyfoError: false, + digisyfoOrganisasjoner: [ + { + orgnr: '121488424', + navn: 'BIRTAVARRE OG VÆRLANDET FORELDER', + organisasjonsform: 'AS', + antallSykmeldte: 0, + underenheter: [ + { + orgnr: '999999999', + navn: 'Saltrød og Høneby', + organisasjonsform: 'BEDR', + antallSykmeldte: 0, + underenheter: [], + }, + ], + }, + { + navn: 'BALLSTAD OG HORTEN', + orgnr: '118345674', + organisasjonsform: 'FLI', + antallSykmeldte: 0, + underenheter: [ + { + navn: 'BALLSTAD OG HAMARØY', + organisasjonsform: 'AAFY', + orgnr: '182345674', + antallSykmeldte: 4, + underenheter: [], + }, + ], + }, + { + navn: 'BareSyfo Juridisk', + orgnr: '111111111', + organisasjonsform: 'FLI', + antallSykmeldte: 4, + underenheter: [ + { + navn: 'BareSyfo Virksomhet', + organisasjonsform: 'AAFY', + orgnr: '121212121', + antallSykmeldte: 4, + underenheter: [], + }, + ], + }, + ], + refusjoner: [ + { + virksomhetsnummer: '999999999', + statusoversikt: { + KLAR_FOR_INNSENDING: 3, + FOR_TIDLIG: 1, + }, + tilgang: true, + }, + { + virksomhetsnummer: '121488424', + statusoversikt: { + KLAR_FOR_INNSENDING: 1, + FOR_TIDLIG: 2, + }, + tilgang: true, + }, + { + virksomhetsnummer: '182345674', + statusoversikt: { + FOR_TIDLIG: 2, + }, + tilgang: true, + }, + ], + }) + ), + http.post(`${__BASE_PATH__}/api/varslingStatus/v1`, () => + HttpResponse.json({ + status: 'OK', + varselTimestamp: '2021-01-01T00:00:00', + kvittertEventTimestamp: '2021-01-04T00:00:00Z', + }) + ), + http.get(/.*arbeidsgiver-arbeidsforhold-api\/antall-arbeidsforhold.*/, () => + HttpResponse.json({ + second: 53, + }) + ), + http.get(/.*presenterte-kandidater-api\/ekstern\/antallkandidater.*/, () => + HttpResponse.json({ + antallKandidater: 85, + }) + ), + http.get(`${__BASE_PATH__}/stillingsregistrering-api/api/stillinger/numberByStatus`, () => + HttpResponse.json({ PUBLISERT: 20 }) + ), + http.post(`${__BASE_PATH__}/stillingsregistrering-api/api/arbeidsgiver/:orgnr`, () => + HttpResponse.json({}) + ), + http.get(/.*tiltaksgjennomforing-api\/avtaler.*/, () => + HttpResponse.json([ + { + tiltakstype: 'SOMMERJOBB', + }, + { + tiltakstype: 'SOMMERJOBB', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'VARIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'INKLUDERINGSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'SOMMERJOBB', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'ARBEIDSTRENING', + }, + { + tiltakstype: 'INKLUDERINGSTILSKUDD', + }, + { + tiltakstype: 'MENTOR', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'ARBEIDSTRENING', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'SOMMERJOBB', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'SOMMERJOBB', + }, + { + tiltakstype: 'MENTOR', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'VARIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'SOMMERJOBB', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MENTOR', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'SOMMERJOBB', + }, + { + tiltakstype: 'SOMMERJOBB', + }, + { + tiltakstype: 'SOMMERJOBB', + }, + { + tiltakstype: 'ARBEIDSTRENING', + }, + { + tiltakstype: 'INKLUDERINGSTILSKUDD', + }, + { + tiltakstype: 'ARBEIDSTRENING', + }, + { + tiltakstype: 'SOMMERJOBB', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'VARIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'SOMMERJOBB', + }, + { + tiltakstype: 'VARIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'ARBEIDSTRENING', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MENTOR', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + { + tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', + }, + ]) + ), + http.get(/.*api\/sykefravaerstatistikk.*/, () => + HttpResponse.json({ + type: 'BRANSJE', + label: 'Barnehager', + prosent: 15.8, + }) + ), + http.post<{}, { orgnr: string }>(`${__BASE_PATH__}/api/ereg/underenhet`, async ({ request }) => + HttpResponse.json({ + organisasjonsnummer: (await request.json()).orgnr, + navn: 'Upopulær Dyreflokk', + organisasjonsform: { + kode: 'BEDR', + beskrivelse: 'Bedrift', + _links: { + self: { + href: '/min-side-arbeidsgiver/api/ereg/organisasjonsformer/BEDR', + }, + }, + }, + postadresse: { + land: 'Norge', + landkode: 'NO', + postnummer: '1358', + poststed: 'JAR', + adresse: ['Ringstabekkveien 58'], + kommune: 'BÆRUM', + kommunenummer: '3024', + }, + registreringsdatoEnhetsregisteret: '2010-12-15', + registrertIMvaregisteret: false, + naeringskode1: { + beskrivelse: 'Administrasjon av finansmarkeder', + kode: '66.110', + }, + antallAnsatte: 42, + overordnetEnhet: '818711111', + oppstartsdato: '2010-12-15', + datoEierskifte: '2010-12-15', + beliggenhetsadresse: { + land: 'Norge', + landkode: 'NO', + postnummer: '7950', + poststed: 'ABELVÆR', + adresse: ['Abelværvegen 1175'], + kommune: 'NÆRØYSUND', + kommunenummer: '5060', + }, + _links: { + self: { + href: '/min-side-arbeidsgiver/api/ereg/underenheter/151488454', + }, + overordnetEnhet: { + href: '/min-side-arbeidsgiver/api/ereg/enheter/181488484', + }, + }, + }) + ), + http.get(`${__BASE_PATH__}/api/altinn-tilgangssoknad`, () => + HttpResponse.json([ + { + orgnr: '321988123', + status: 'Unopened', + submitUrl: 'https://fake-altinn/send-inn-soknad/', + serviceCode: '5278', + serviceEdition: 1, + createdDateTime: '', + lastChangedDateTime: '', + }, + { + orgnr: '321988123', + status: 'Created', + submitUrl: 'https://fake-altinn/send-inn-soknad/', + serviceCode: '5332', + serviceEdition: 1, + createdDateTime: '', + lastChangedDateTime: '', + }, + ]) + ), + graphql.query('hentSaker', () => { + return HttpResponse.json({ + data: { + saker: { + saker: [ + { + id: '525a419e-56c9-4194-bb92-2a406a826243', + tittel: 'Permitteringsmelding 14 ansatte TEST', + lenke: '#', + virksomhet: { + navn: 'Gamle Fredikstad og Riksdalen regnskap', + virksomhetsnummer: + 'tempore commodi corrupti aut asperiores ut perferendis', + __typename: 'Virksomhet', + }, + sisteStatus: { + type: 'UNDER_BEHANDLING', + tekst: 'Under behandling', + tidspunkt: '2024-01-06T11:45:25.073Z', + __typename: 'SakStatus', + }, + tidslinje: [ + { + __typename: 'OppgaveTidslinjeElement', + id: '0.ju5z2d82kyc', + tekst: 'Avtalen må godkjennes på nytt.', + tilstand: 'NY', + frist: '2023-12-30T12:05:25.073Z', + opprettetTidspunkt: '2023-12-28T12:27:25.073Z', + paaminnelseTidspunkt: null, + utfoertTidspunkt: null, + utgaattTidspunkt: null, + }, + { + __typename: 'BeskjedTidslinjeElement', + id: '0.y7egbm5yzg', + tekst: 'Avtale om arbeidstiltak godkjent.', + opprettetTidspunkt: '2024-01-13T07:27:25.073Z', + }, + ], + __typename: 'Sak', + }, + { + id: '61ddfc9f-dd0d-4eb3-973e-f53dd7557007', + tittel: 'Søknad om fritak fra arbeidsgiverperioden – gravid ansatt Glovarm Bagasje', + lenke: '#', + virksomhet: { + navn: 'Gamle Fredikstad og Riksdalen regnskap', + virksomhetsnummer: + 'tempore reprehenderit blanditiis inventore at nihil architecto', + __typename: 'Virksomhet', + }, + sisteStatus: { + type: 'UNDER_BEHANDLING', + tekst: 'Mottatt', + tidspunkt: '2023-11-14T12:06:25.073Z', + __typename: 'SakStatus', + }, + tidslinje: [ + { + __typename: 'BeskjedTidslinjeElement', + id: '0.ymz4g2gw8yn', + tekst: 'Avtalen må godkjennes på nytt.', + opprettetTidspunkt: '2024-01-02T12:27:25.073Z', + }, + { + __typename: 'OppgaveTidslinjeElement', + id: '0.8ccy3cavfio', + tekst: 'Avtalen må godkjennes på nytt.', + tilstand: 'UTFOERT', + frist: '2024-01-12T12:26:25.073Z', + opprettetTidspunkt: '2023-12-17T12:06:25.073Z', + paaminnelseTidspunkt: '2023-12-19T19:27:25.073Z', + utfoertTidspunkt: '2023-07-27T10:03:15.426Z', + utgaattTidspunkt: null, + }, + ], + __typename: 'Sak', + }, + { + id: '1af36b5b-5630-406e-b989-6b08047e3530', + tittel: 'Varsel om permittering 12 ansatte TEST', + lenke: '#', + virksomhet: { + navn: 'Gamle Fredikstad og Riksdalen regnskap', + virksomhetsnummer: 'porro qui voluptatem qui magni aut id', + __typename: 'Virksomhet', + }, + sisteStatus: { + type: 'UNDER_BEHANDLING', + tekst: 'Under behandling', + tidspunkt: '2024-01-03T12:34:25.073Z', + __typename: 'SakStatus', + }, + tidslinje: [ + { + __typename: 'BeskjedTidslinjeElement', + id: '0.x8wuv8runs', + tekst: 'Du kan nå søke om refusjon.', + opprettetTidspunkt: '2024-01-14T19:06:25.073Z', + }, + { + __typename: 'OppgaveTidslinjeElement', + id: '0.diy6gwrzlfk', + tekst: 'Mål i avtale endret av veileder.', + tilstand: 'UTFOERT', + frist: null, + opprettetTidspunkt: '2023-12-20T12:11:25.073Z', + paaminnelseTidspunkt: '2023-12-16T00:33:25.073Z', + utfoertTidspunkt: '2023-10-12T02:08:06.941Z', + utgaattTidspunkt: null, + }, + ], + __typename: 'Sak', + }, + ], + sakstyper: [ + { + navn: 'Lønnstilskudd', + antall: 4, + __typename: 'Sakstype', + }, + { + navn: 'Mentor', + antall: 1, + __typename: 'Sakstype', + }, + { + navn: 'Sommerjobb', + antall: 2, + __typename: 'Sakstype', + }, + { + navn: 'Arbeidstrening', + antall: 7, + __typename: 'Sakstype', + }, + ], + feilAltinn: true, + totaltAntallSaker: 314, + oppgaveTilstandInfo: [ + { + tilstand: 'UTFOERT', + antall: 621, + __typename: 'OppgaveTilstandInfo', + }, + { + tilstand: 'NY', + antall: 877, + __typename: 'OppgaveTilstandInfo', + }, + ], + __typename: 'SakerResultat', + }, + }, + }); + }) +); diff --git a/src/tests/mocks.ts b/src/tests/mocks.ts deleted file mode 100644 index f2ed0c37a..000000000 --- a/src/tests/mocks.ts +++ /dev/null @@ -1,611 +0,0 @@ -import { setupServer } from 'msw/node'; -import { graphql, http, HttpResponse } from 'msw'; -import { orgnr } from '../mocks/brukerApi/helpers'; -import { faker } from '@faker-js/faker'; - -export const server = setupServer( - http.get(`${__BASE_PATH__}/api/userInfo/v3`, () => - HttpResponse.json({ - altinnError: false, - organisasjoner: [ - { - orgnr: orgnr(), - underenheter: [ - { - orgnr: '182345674', - underenheter: [], - navn: faker.company.name(), - organisasjonsform: 'BEDR', - }, - { - orgnr: '118345674', - underenheter: [], - navn: faker.company.name(), - organisasjonsform: 'BEDR', - }, - { - orgnr: '119985432', - underenheter: [], - navn: faker.company.name(), - organisasjonsform: 'BEDR', - }, - { - orgnr: '119988432', - underenheter: [], - navn: faker.company.name(), - organisasjonsform: 'BEDR', - }, - ], - navn: faker.company.name(), - organisasjonsform: 'AS', - }, - ], - tilganger: { - '5384:1': ['182345674', '118345674', '119985432', '119988432'], - '4936:1': ['182345674', '118345674', '119985432', '119988432'], - '4826:1': ['182345674', '118345674', '119985432', '119988432'], - '5332:1': ['182345674', '118345674', '119985432', '119988432'], - '5441:1': ['182345674', '118345674', '119985432', '119988432'], - '5516:1': ['182345674', '118345674', '119985432', '119988432'], - '5516:2': ['182345674', '118345674', '119985432', '119988432'], - '5516:3': ['182345674', '118345674', '119985432', '119988432'], - '5516:4': ['182345674', '118345674', '119985432', '119988432'], - '5516:5': ['182345674', '118345674', '119985432', '119988432'], - '3403:1': ['182345674', '118345674', '119985432', '119988432'], - '5934:1': ['182345674', '118345674', '119985432', '119988432'], - '5078:1': ['182345674', '118345674', '119985432', '119988432'], - '5278:1': ['182345674', '118345674', '119985432', '119988432'], - '5902:1': ['182345674', '118345674', '119985432', '119988432'], - }, - digisyfoError: false, - digisyfoOrganisasjoner: [ - { - orgnr: '121488424', - navn: 'BIRTAVARRE OG VÆRLANDET FORELDER', - organisasjonsform: 'AS', - antallSykmeldte: 0, - underenheter: [ - { - orgnr: '999999999', - navn: 'Saltrød og Høneby', - organisasjonsform: 'BEDR', - antallSykmeldte: 0, - underenheter: [], - }, - ], - }, - { - navn: 'BALLSTAD OG HORTEN', - orgnr: '118345674', - organisasjonsform: 'FLI', - antallSykmeldte: 0, - underenheter: [ - { - navn: 'BALLSTAD OG HAMARØY', - organisasjonsform: 'AAFY', - orgnr: '182345674', - antallSykmeldte: 4, - underenheter: [], - }, - ], - }, - { - navn: 'BareSyfo Juridisk', - orgnr: '111111111', - organisasjonsform: 'FLI', - antallSykmeldte: 4, - underenheter: [ - { - navn: 'BareSyfo Virksomhet', - organisasjonsform: 'AAFY', - orgnr: '121212121', - antallSykmeldte: 4, - underenheter: [], - }, - ], - }, - ], - refusjoner: [ - { - virksomhetsnummer: '999999999', - statusoversikt: { - KLAR_FOR_INNSENDING: 3, - FOR_TIDLIG: 1, - }, - tilgang: true, - }, - { - virksomhetsnummer: '121488424', - statusoversikt: { - KLAR_FOR_INNSENDING: 1, - FOR_TIDLIG: 2, - }, - tilgang: true, - }, - { - virksomhetsnummer: '182345674', - statusoversikt: { - FOR_TIDLIG: 2, - }, - tilgang: true, - }, - ], - }) - ), - http.post(`${__BASE_PATH__}/api/varslingStatus/v1`, () => - HttpResponse.json({ - status: 'OK', - varselTimestamp: '2021-01-01T00:00:00', - kvittertEventTimestamp: '2021-01-04T00:00:00Z', - }) - ), - http.get(/.*arbeidsgiver-arbeidsforhold-api\/antall-arbeidsforhold.*/, () => - HttpResponse.json({ - second: 53, - }) - ), - http.get(/.*presenterte-kandidater-api\/ekstern\/antallkandidater.*/, () => - HttpResponse.json({ - antallKandidater: 85, - }) - ), - http.get(`${__BASE_PATH__}/stillingsregistrering-api/api/stillinger/numberByStatus`, () => - HttpResponse.json({ PUBLISERT: 20 }) - ), - http.post(`${__BASE_PATH__}/stillingsregistrering-api/api/arbeidsgiver/:orgnr`, () => - HttpResponse.json({}) - ), - http.get(/.*tiltaksgjennomforing-api\/avtaler.*/, () => - HttpResponse.json([ - { - tiltakstype: 'SOMMERJOBB', - }, - { - tiltakstype: 'SOMMERJOBB', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'VARIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'INKLUDERINGSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'SOMMERJOBB', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'ARBEIDSTRENING', - }, - { - tiltakstype: 'INKLUDERINGSTILSKUDD', - }, - { - tiltakstype: 'MENTOR', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'ARBEIDSTRENING', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'SOMMERJOBB', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'SOMMERJOBB', - }, - { - tiltakstype: 'MENTOR', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'VARIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'SOMMERJOBB', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MENTOR', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'SOMMERJOBB', - }, - { - tiltakstype: 'SOMMERJOBB', - }, - { - tiltakstype: 'SOMMERJOBB', - }, - { - tiltakstype: 'ARBEIDSTRENING', - }, - { - tiltakstype: 'INKLUDERINGSTILSKUDD', - }, - { - tiltakstype: 'ARBEIDSTRENING', - }, - { - tiltakstype: 'SOMMERJOBB', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'VARIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'SOMMERJOBB', - }, - { - tiltakstype: 'VARIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'ARBEIDSTRENING', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MENTOR', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - { - tiltakstype: 'MIDLERTIDIG_LONNSTILSKUDD', - }, - ]) - ), - http.get(/.*api\/sykefravaerstatistikk.*/, () => - HttpResponse.json({ - type: 'BRANSJE', - label: 'Barnehager', - prosent: 15.8, - }) - ), - http.get( - `${__BASE_PATH__}/mock/data.brreg.no/enhetsregisteret/api/underenheter/:orgnr`, - ({ params }) => - HttpResponse.json({ - organisasjonsnummer: params.orgnr, - navn: 'Upopulær Dyreflokk', - organisasjonsform: { - kode: 'BEDR', - beskrivelse: 'Bedrift', - _links: { - self: { - href: '/min-side-arbeidsgiver/api/ereg/organisasjonsformer/BEDR', - }, - }, - }, - postadresse: { - land: 'Norge', - landkode: 'NO', - postnummer: '1358', - poststed: 'JAR', - adresse: ['Ringstabekkveien 58'], - kommune: 'BÆRUM', - kommunenummer: '3024', - }, - registreringsdatoEnhetsregisteret: '2010-12-15', - registrertIMvaregisteret: false, - naeringskode1: { - beskrivelse: 'Administrasjon av finansmarkeder', - kode: '66.110', - }, - antallAnsatte: 42, - overordnetEnhet: '818711111', - oppstartsdato: '2010-12-15', - datoEierskifte: '2010-12-15', - beliggenhetsadresse: { - land: 'Norge', - landkode: 'NO', - postnummer: '7950', - poststed: 'ABELVÆR', - adresse: ['Abelværvegen 1175'], - kommune: 'NÆRØYSUND', - kommunenummer: '5060', - }, - _links: { - self: { - href: '/min-side-arbeidsgiver/api/ereg/underenheter/151488454', - }, - overordnetEnhet: { - href: '/min-side-arbeidsgiver/api/ereg/enheter/181488484', - }, - }, - }) - ), - http.get(`${__BASE_PATH__}/api/altinn-tilgangssoknad`, () => - HttpResponse.json([ - { - orgnr: '321988123', - status: 'Unopened', - submitUrl: 'https://fake-altinn/send-inn-soknad/', - serviceCode: '5278', - serviceEdition: 1, - createdDateTime: '', - lastChangedDateTime: '', - }, - { - orgnr: '321988123', - status: 'Created', - submitUrl: 'https://fake-altinn/send-inn-soknad/', - serviceCode: '5332', - serviceEdition: 1, - createdDateTime: '', - lastChangedDateTime: '', - }, - ]) - ), - graphql.query('hentSaker', () => { - return HttpResponse.json({ - data: { - saker: { - saker: [ - { - id: '525a419e-56c9-4194-bb92-2a406a826243', - tittel: 'Permitteringsmelding 14 ansatte TEST', - lenke: '#', - virksomhet: { - navn: 'Gamle Fredikstad og Riksdalen regnskap', - virksomhetsnummer: - 'tempore commodi corrupti aut asperiores ut perferendis', - __typename: 'Virksomhet', - }, - sisteStatus: { - type: 'UNDER_BEHANDLING', - tekst: 'Under behandling', - tidspunkt: '2024-01-06T11:45:25.073Z', - __typename: 'SakStatus', - }, - tidslinje: [ - { - __typename: 'OppgaveTidslinjeElement', - id: '0.ju5z2d82kyc', - tekst: 'Avtalen må godkjennes på nytt.', - tilstand: 'NY', - frist: '2023-12-30T12:05:25.073Z', - opprettetTidspunkt: '2023-12-28T12:27:25.073Z', - paaminnelseTidspunkt: null, - utfoertTidspunkt: null, - utgaattTidspunkt: null, - }, - { - __typename: 'BeskjedTidslinjeElement', - id: '0.y7egbm5yzg', - tekst: 'Avtale om arbeidstiltak godkjent.', - opprettetTidspunkt: '2024-01-13T07:27:25.073Z', - }, - ], - __typename: 'Sak', - }, - { - id: '61ddfc9f-dd0d-4eb3-973e-f53dd7557007', - tittel: 'Søknad om fritak fra arbeidsgiverperioden – gravid ansatt Glovarm Bagasje', - lenke: '#', - virksomhet: { - navn: 'Gamle Fredikstad og Riksdalen regnskap', - virksomhetsnummer: - 'tempore reprehenderit blanditiis inventore at nihil architecto', - __typename: 'Virksomhet', - }, - sisteStatus: { - type: 'UNDER_BEHANDLING', - tekst: 'Mottatt', - tidspunkt: '2023-11-14T12:06:25.073Z', - __typename: 'SakStatus', - }, - tidslinje: [ - { - __typename: 'BeskjedTidslinjeElement', - id: '0.ymz4g2gw8yn', - tekst: 'Avtalen må godkjennes på nytt.', - opprettetTidspunkt: '2024-01-02T12:27:25.073Z', - }, - { - __typename: 'OppgaveTidslinjeElement', - id: '0.8ccy3cavfio', - tekst: 'Avtalen må godkjennes på nytt.', - tilstand: 'UTFOERT', - frist: '2024-01-12T12:26:25.073Z', - opprettetTidspunkt: '2023-12-17T12:06:25.073Z', - paaminnelseTidspunkt: '2023-12-19T19:27:25.073Z', - utfoertTidspunkt: '2023-07-27T10:03:15.426Z', - utgaattTidspunkt: null, - }, - ], - __typename: 'Sak', - }, - { - id: '1af36b5b-5630-406e-b989-6b08047e3530', - tittel: 'Varsel om permittering 12 ansatte TEST', - lenke: '#', - virksomhet: { - navn: 'Gamle Fredikstad og Riksdalen regnskap', - virksomhetsnummer: 'porro qui voluptatem qui magni aut id', - __typename: 'Virksomhet', - }, - sisteStatus: { - type: 'UNDER_BEHANDLING', - tekst: 'Under behandling', - tidspunkt: '2024-01-03T12:34:25.073Z', - __typename: 'SakStatus', - }, - tidslinje: [ - { - __typename: 'BeskjedTidslinjeElement', - id: '0.x8wuv8runs', - tekst: 'Du kan nå søke om refusjon.', - opprettetTidspunkt: '2024-01-14T19:06:25.073Z', - }, - { - __typename: 'OppgaveTidslinjeElement', - id: '0.diy6gwrzlfk', - tekst: 'Mål i avtale endret av veileder.', - tilstand: 'UTFOERT', - frist: null, - opprettetTidspunkt: '2023-12-20T12:11:25.073Z', - paaminnelseTidspunkt: '2023-12-16T00:33:25.073Z', - utfoertTidspunkt: '2023-10-12T02:08:06.941Z', - utgaattTidspunkt: null, - }, - ], - __typename: 'Sak', - }, - ], - sakstyper: [ - { - navn: 'Lønnstilskudd', - antall: 4, - __typename: 'Sakstype', - }, - { - navn: 'Mentor', - antall: 1, - __typename: 'Sakstype', - }, - { - navn: 'Sommerjobb', - antall: 2, - __typename: 'Sakstype', - }, - { - navn: 'Arbeidstrening', - antall: 7, - __typename: 'Sakstype', - }, - ], - feilAltinn: true, - totaltAntallSaker: 314, - oppgaveTilstandInfo: [ - { - tilstand: 'UTFOERT', - antall: 621, - __typename: 'OppgaveTilstandInfo', - }, - { - tilstand: 'NY', - antall: 877, - __typename: 'OppgaveTilstandInfo', - }, - ], - __typename: 'SakerResultat', - }, - }, - }); - }) -); diff --git a/src/utils/util.test.ts b/src/utils/util.test.ts new file mode 100644 index 000000000..1e7a48b5e --- /dev/null +++ b/src/utils/util.test.ts @@ -0,0 +1,122 @@ +import { expect, test } from 'vitest'; +import { flatUtTre, alleOrganisasjonerFlatt, mapRecursive } from './util'; + +test('henter løvnoder og parent som flat liste', () => { + const flat = flatUtTre(hierarki); + expect(flat).toEqual([ + { + orgnr: '1', + navn: '1', + organisasjonsform: 'AS', + underenheter: [ + { orgnr: '1.2', navn: '1.2', organisasjonsform: 'BEDR', underenheter: [] }, + ], + }, + { + orgnr: '1.1', + navn: '1.1', + organisasjonsform: 'ORGL', + underenheter: [ + { orgnr: '1.1.1', navn: '1.1.1', organisasjonsform: 'BEDR', underenheter: [] }, + ], + }, + { + orgnr: '1.3.1', + navn: '1.3.1', + organisasjonsform: 'ORGL', + underenheter: [ + { orgnr: '1.3.1.1', navn: '1.3.1.1', organisasjonsform: 'BEDR', underenheter: [] }, + { orgnr: '1.3.1.2', navn: '1.3.1.2', organisasjonsform: 'BEDR', underenheter: [] }, + ], + }, + ]); +}); + +test('mapRecursive kan modifisere rekursivt', () => { + const orgs = flatUtTre(hierarki); + + const mapped = mapRecursive(orgs, (org) => ({ + ...org, + navn: org.navn + ' mapped', + })); + + expect(mapped[0].navn).toBe(orgs[0].navn + ' mapped'); + expect(mapped[0].underenheter[0].navn).toBe(orgs[0].underenheter[0].navn + ' mapped'); +}); + +test('alleOrganisasjonerFlatt gir alle noder i treet som en flat liste', () => { + const flat = alleOrganisasjonerFlatt(hierarki); + expect(flat.length).toEqual(9); + expect(flat.map((o) => o.orgnr)).toEqual([ + '1', + '1.1', + '1.1.1', + '1.2', + '1.3', + '1.3.1', + '1.3.1.1', + '1.3.1.2', + '2', + ]); +}); + +const hierarki = [ + { + orgnr: '1', + navn: '1', + organisasjonsform: 'AS', + underenheter: [ + { + orgnr: '1.1', + navn: '1.1', + organisasjonsform: 'ORGL', + underenheter: [ + { + orgnr: '1.1.1', + navn: '1.1.1', + organisasjonsform: 'BEDR', + underenheter: [], + }, + ], + }, + { + orgnr: '1.2', + navn: '1.2', + organisasjonsform: 'BEDR', + underenheter: [], + }, + { + orgnr: '1.3', + navn: '1.3', + organisasjonsform: 'ORGL', + underenheter: [ + { + orgnr: '1.3.1', + navn: '1.3.1', + organisasjonsform: 'ORGL', + underenheter: [ + { + orgnr: '1.3.1.1', + navn: '1.3.1.1', + organisasjonsform: 'BEDR', + underenheter: [], + }, + { + orgnr: '1.3.1.2', + navn: '1.3.1.2', + organisasjonsform: 'BEDR', + underenheter: [], + }, + ], + }, + ], + }, + ], + }, + { + orgnr: '2', + navn: '2', + organisasjonsform: 'AS', + underenheter: [], + }, +]; diff --git a/src/utils/util.ts b/src/utils/util.ts index 239341684..386921060 100644 --- a/src/utils/util.ts +++ b/src/utils/util.ts @@ -34,6 +34,10 @@ export const capitalize = (s: string): string => { export const formatOrgNr = (orgNr: string): string => orgNr.replace(/(\d{3})(\d{3})(\d{3})/, '$1 $2 $3'); +/** + * Denne funksjonen tar en trestruktur og returnerer en flat liste av alle løvnoder og dems første ledd parent. + * mellomledd vil ikke være med i resultatet, med mindre de er direkte parent av en løvnode. + */ export const flatUtTre = (organisasjonstre: Organisasjon[]): Organisasjon[] => { const mapR = (parent: Organisasjon): Organisasjon[] => { const [children, otherParents] = splittListe( @@ -54,3 +58,49 @@ export const flatUtTre = (organisasjonstre: Organisasjon[]): Organisasjon[] => { }; return organisasjonstre.flatMap((o) => mapR(o)).sort((a, b) => a.navn.localeCompare(b.navn)); }; + +/** + * Denne funksjonen tar en trestruktur av organisasjoner og mapper over hver node i treet med den gitte mapping funksjonen. + */ +export const mapRecursive = (list: T[], mapper: (o: T) => T): T[] => { + return list.map((org) => { + return { + ...mapper({ + ...org, + underenheter: mapRecursive(org.underenheter as T[], mapper), + }), + }; + }); +}; + +/** + * Denne funksjonen tar en trestruktur av organisasjoner og mapper alle noder til en flat liste, inklusiv alle mellomledd + */ +export const alleOrganisasjonerFlatt = (organisasjonstre: Organisasjon[]): Organisasjon[] => { + const mapR = (parent: Organisasjon): Organisasjon[] => [ + parent, + ...parent.underenheter.flatMap(mapR), + ]; + return organisasjonstre.flatMap((o) => mapR(o)); +}; + +export const mergeOrgTre = (first: Organisasjon[], second: Organisasjon[]): Organisasjon[] => { + const map = new Map(); + + [...first, ...second].forEach((org) => { + if (map.has(org.orgnr)) { + map.set(org.orgnr, mergeOrgs(map.get(org.orgnr)!, org)); + } else { + map.set(org.orgnr, org); + } + }); + + return Array.from(map.values()); +}; + +const mergeOrgs = (orgA: Organisasjon, orgB: Organisasjon): Organisasjon => ({ + navn: orgA.navn, + orgnr: orgA.orgnr, + organisasjonsform: orgA.organisasjonsform, + underenheter: mergeOrgTre(orgA.underenheter, orgB.underenheter), +}); diff --git a/tsconfig.build.json b/tsconfig.build.json index de74c8291..f1af0eaa9 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -29,6 +29,7 @@ "vite-env.d.ts", ], "exclude": [ - "**/tests/*" + "**/tests/*", + "**/*.test.ts*", ], } \ No newline at end of file diff --git a/vite-env.d.ts b/vite-env.d.ts index 805e055e1..30696b6a7 100644 --- a/vite-env.d.ts +++ b/vite-env.d.ts @@ -1,5 +1,6 @@ /// declare const __BASE_PATH__: string; +declare const __BUILD_TIMESTAMP__: string; declare module '*.graphql'; diff --git a/vitest.config.ts b/vitest.config.ts index 71477ab40..ca9f110bd 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -27,5 +27,6 @@ export default defineConfig({ exclude: [...configDefaults.exclude, './vitest.setup.ts', 'build/**/*'], setupFiles: './vitest.setup.ts', reporters: 'verbose', + disableConsoleIntercept: true, }, });