diff --git a/backend/src/ilmoitustauluSyote/ilmoitusKuulutus.ts b/backend/src/ilmoitustauluSyote/ilmoitusKuulutus.ts index 03fe6e1eb..a574c053a 100644 --- a/backend/src/ilmoitustauluSyote/ilmoitusKuulutus.ts +++ b/backend/src/ilmoitustauluSyote/ilmoitusKuulutus.ts @@ -14,6 +14,6 @@ export type IlmoitusKuulutus = { maakunnat?: number[]; vaylamuoto?: string[]; date: string; - elyt?: number[]; - lelyt?: number[]; + elyt?: string[]; + lelyt?: string[]; }; diff --git a/backend/src/ilmoitustauluSyote/ilmoitustauluSyoteAdapter.ts b/backend/src/ilmoitustauluSyote/ilmoitustauluSyoteAdapter.ts index b390113e4..60a992ee6 100644 --- a/backend/src/ilmoitustauluSyote/ilmoitustauluSyoteAdapter.ts +++ b/backend/src/ilmoitustauluSyote/ilmoitustauluSyoteAdapter.ts @@ -13,6 +13,7 @@ import { linkAloituskuulutus, linkHyvaksymisPaatos, linkSuunnitteluVaihe } from import { parseDate } from "../util/dateUtil"; import { kuntametadata } from "../../../common/kuntametadata"; import { assertIsDefined } from "../util/assertions"; +import { sortedUniq } from "lodash"; class IlmoitustauluSyoteAdapter { adaptAloitusKuulutusJulkaisu( @@ -128,11 +129,14 @@ class IlmoitustauluSyoteAdapter { assertIsDefined(velho.kunnat); assertIsDefined(velho.vaylamuoto); const maakunnat = velho.maakunnat; - const elyt = maakunnat - ?.map(kuntametadata.maakuntaForMaakuntaId) - .map((maakunta) => maakunta?.ely) - .filter((m) => !!m) as number[]; - const lelyt = elyt?.map(kuntametadata.liikennevastuuElyIdFromElyId).filter((m) => !!m) as number[]; + let elyt = velho.kunnat + ?.map(kuntametadata.kuntaForKuntaId) + .map((kunta) => kunta?.ely) + .filter((m) => !!m) as string[]; + if (elyt) { + elyt = sortedUniq(elyt); + } + const lelyt = velho.kunnat?.map(kuntametadata.liikennevastuuElyIdFromKuntaId).filter((m) => !!m) as string[]; return { oid, kunnat: velho.kunnat, diff --git a/backend/src/ilmoitustauluSyote/ilmoitustauluSyoteHandler.ts b/backend/src/ilmoitustauluSyote/ilmoitustauluSyoteHandler.ts index 5ed3e1655..ca73d5e24 100644 --- a/backend/src/ilmoitustauluSyote/ilmoitustauluSyoteHandler.ts +++ b/backend/src/ilmoitustauluSyote/ilmoitustauluSyoteHandler.ts @@ -22,7 +22,7 @@ class IlmoitustauluSyoteHandler { if (ely) { if (elyId) { terms.push({ - term: { elyt: elyId }, + term: { "elyt.keyword": elyId }, }); } else { throw new NotFoundError("ELY " + ely + " on tuntematon"); @@ -33,7 +33,7 @@ class IlmoitustauluSyoteHandler { if (lely) { if (lelyId) { terms.push({ - term: { lelyt: lelyId }, + term: { "lelyt.keyword": lelyId }, }); } else { throw new NotFoundError("Liikenne-ELY " + lely + " on tuntematon"); diff --git a/backend/src/velho/velhoAdapter.ts b/backend/src/velho/velhoAdapter.ts index 052c5561b..873c2f731 100644 --- a/backend/src/velho/velhoAdapter.ts +++ b/backend/src/velho/velhoAdapter.ts @@ -162,7 +162,7 @@ function getKunnat(data: ProjektiProjekti): number[] | undefined { if (data.ominaisuudet.kunta) { const kunnat: number[] = []; data.ominaisuudet.kunta.forEach((kuntaVelhoKey) => { - const kuntaId = kuntametadata.parseNumberIdFromVelhoKey(kuntaVelhoKey as unknown as string); + const kuntaId = parseNumberIdFromVelhoKey(kuntaVelhoKey as unknown as string); if (!kuntametadata.kuntaForKuntaId(kuntaId)) { log.warn("Velhosta saatua kuntaa ei löydy: " + kuntaId); } else { @@ -178,7 +178,7 @@ function getMaakunnat(data: ProjektiProjekti) { if (data.ominaisuudet.maakunta) { const maakunnat: number[] = []; data.ominaisuudet.maakunta.forEach((maakuntaVelhoKey) => { - const maakuntaId = kuntametadata.parseNumberIdFromVelhoKey(maakuntaVelhoKey as unknown as string); + const maakuntaId = parseNumberIdFromVelhoKey(maakuntaVelhoKey as unknown as string); if (!kuntametadata.maakuntaForMaakuntaId(maakuntaId)) { log.warn("Velhosta saatua maakuntaa ei löydy: " + maakuntaId); } else { @@ -363,3 +363,14 @@ function objectToString(s: unknown): T | undefined { // eslint-disable-next-line @typescript-eslint/ban-types return s as unknown as T; } + +function parseNumberIdFromVelhoKey(key: string): number { + const match = key.match(/\w+\/[a-z]+(\d+)/); + if (match && match.length == 2) { + const val = Number.parseInt(match[1]); + if (!isNaN(val)) { + return val; + } + } + throw new Error("Could not parse number from key:" + key); +} diff --git a/backend/test/ilmoitustauluSyote/__snapshots__/ilmoitustauluSyote.test.ts.snap b/backend/test/ilmoitustauluSyote/__snapshots__/ilmoitustauluSyote.test.ts.snap index 08a5318b2..ac10549e8 100644 --- a/backend/test/ilmoitustauluSyote/__snapshots__/ilmoitustauluSyote.test.ts.snap +++ b/backend/test/ilmoitustauluSyote/__snapshots__/ilmoitustauluSyote.test.ts.snap @@ -5,8 +5,7 @@ Array [ Object { "date": "2022-03-28T14:28:00+03:00", "elyt": Array [ - 1001, - 1019, + "ely/ely07", ], "kieli": "SUOMI", "kunnat": Array [ @@ -15,8 +14,9 @@ Array [ 740, ], "lelyt": Array [ - 1001, - 1019, + "ely/ely08", + "ely/ely08", + "ely/ely08", ], "maakunnat": Array [ 1, @@ -33,8 +33,7 @@ Array [ Object { "date": "2022-03-28T14:28:00+03:00", "elyt": Array [ - 1001, - 1019, + "ely/ely07", ], "kieli": "RUOTSI", "kunnat": Array [ @@ -43,8 +42,9 @@ Array [ 740, ], "lelyt": Array [ - 1001, - 1019, + "ely/ely08", + "ely/ely08", + "ely/ely08", ], "maakunnat": Array [ 1, @@ -61,16 +61,14 @@ Array [ Object { "date": "2022-06-20T11:54:00+03:00", "elyt": Array [ - 1001, - 1019, + "ely/ely01", ], "kieli": "SUOMI", "kunnat": Array [ 245, ], "lelyt": Array [ - 1001, - 1019, + "ely/ely01", ], "maakunnat": Array [ 1, @@ -87,16 +85,14 @@ Array [ Object { "date": "2022-06-20T11:54:00+03:00", "elyt": Array [ - 1001, - 1019, + "ely/ely01", ], "kieli": "RUOTSI", "kunnat": Array [ 245, ], "lelyt": Array [ - 1001, - 1019, + "ely/ely01", ], "maakunnat": Array [ 1, @@ -113,7 +109,7 @@ Array [ Object { "date": "2022-06-09T00:00:00+03:00", "elyt": Array [ - 1001, + "ely/ely01", ], "kieli": "SUOMI", "kunnat": Array [ @@ -121,7 +117,8 @@ Array [ 92, ], "lelyt": Array [ - 1001, + "ely/ely01", + "ely/ely01", ], "maakunnat": Array [ 1, @@ -137,7 +134,7 @@ Array [ Object { "date": "2022-06-09T00:00:00+03:00", "elyt": Array [ - 1001, + "ely/ely01", ], "kieli": "RUOTSI", "kunnat": Array [ @@ -145,7 +142,8 @@ Array [ 92, ], "lelyt": Array [ - 1001, + "ely/ely01", + "ely/ely01", ], "maakunnat": Array [ 1, diff --git a/backend/test/projektiSearch/__snapshots__/dynamoDBStreamHandler.test.ts.snap b/backend/test/projektiSearch/__snapshots__/dynamoDBStreamHandler.test.ts.snap index 51bbcc7d2..61998e08d 100644 --- a/backend/test/projektiSearch/__snapshots__/dynamoDBStreamHandler.test.ts.snap +++ b/backend/test/projektiSearch/__snapshots__/dynamoDBStreamHandler.test.ts.snap @@ -103,8 +103,7 @@ Array [ Object { "date": "2022-03-28T14:28:00+03:00", "elyt": Array [ - 1001, - 1019, + "ely/ely07", ], "kieli": "SUOMI", "kunnat": Array [ @@ -113,8 +112,9 @@ Array [ 740, ], "lelyt": Array [ - 1001, - 1019, + "ely/ely08", + "ely/ely08", + "ely/ely08", ], "maakunnat": Array [ 1, @@ -134,8 +134,7 @@ Array [ Object { "date": "2022-03-28T14:28:00+03:00", "elyt": Array [ - 1001, - 1019, + "ely/ely07", ], "kieli": "RUOTSI", "kunnat": Array [ @@ -144,8 +143,9 @@ Array [ 740, ], "lelyt": Array [ - 1001, - 1019, + "ely/ely08", + "ely/ely08", + "ely/ely08", ], "maakunnat": Array [ 1, diff --git a/common/kuntametadata.test.ts b/common/kuntametadata.test.ts index 214819c88..379f0f930 100644 --- a/common/kuntametadata.test.ts +++ b/common/kuntametadata.test.ts @@ -8,10 +8,10 @@ describe("Metadata", () => { const tampere = kuntametadata.kuntaForKuntaId(837); expect(tampere).to.not.be.undefined; expect(tampere).to.eql({ - elyId: 5, + ely: "ely/ely05", id: 837, - liikennevastuuElyId: 5, - maakuntaId: 6, + liikennevastuuEly: "ely/ely05", + maakunta: "maakunta/maakunta06", nimi: { SUOMI: "Tampere", RUOTSI: "Tammerfors", @@ -20,19 +20,24 @@ describe("Metadata", () => { const pirkanmaa = kuntametadata.maakuntaForMaakuntaId(6); expect(pirkanmaa).to.eql({ - id: 6, - ely: 1019, + id: "maakunta/maakunta06", + koodi: "06", nimi: { RUOTSI: "Birkaland", SUOMI: "Pirkanmaa", }, }); - expect(tampere!.maakuntaId).to.eq(pirkanmaa!.id); + expect(tampere!.maakunta).to.eq(pirkanmaa!.id); }); it("should tolerate upper-, and lowercase variations", () => { const joroinen = kuntametadata.idForKuntaName("JOROINEN"); expect(joroinen).to.eq(171); }); + + it("should handle ely lyhenne to ely successfully", () => { + const uud = kuntametadata.elyIdFromKey("UUD"); + expect(uud).to.eq("ely/ely01"); + }); }); diff --git a/common/kuntametadata.ts b/common/kuntametadata.ts index f22d667ae..a89efec06 100644 --- a/common/kuntametadata.ts +++ b/common/kuntametadata.ts @@ -1,188 +1,40 @@ -import velhometadata from "./generated/velhometadata.json"; -import sykeKunnat from "./generated/kunnat.json"; -import sykeMaakunnat from "./generated/maakunnat.json"; -import elyt from "./generated/ely.json"; +import { alueData } from "./generated/aluedata"; import { RequiredLocalizedMap } from "../backend/src/database/model"; import { IlmoitettavaViranomainen, Kieli } from "./graphql/apiModel"; import { IllegalArgumentError } from "../backend/src/error/IllegalArgumentError"; import log from "loglevel"; -import NodeCache from "node-cache"; - -const metadataCache = new NodeCache(); - -type VelhoKunta = { - maakunta: string; //"maakunta/maakunta17", - koodi: string; //"563", - otsikko: string; // "Oulainen", - "liikennevastuu-ely": string; //"ely/ely13", - ely: string; //"ely/ely13", - avi: string; // "avi/avi5" - lakkautettu?: string; -}; - -type VelhoMaakunta = { - maakunta: string; //"maakunta/maakunta17", - koodi: string; //"563", - lakkautettu?: string; -}; +import { findKey } from "lodash"; export type Kunta = { id: number; - maakuntaId: number; + maakunta: string; nimi: RequiredLocalizedMap; - elyId: number; - liikennevastuuElyId: number; + ely: string; + liikennevastuuEly: string; + lakkautettu?: boolean; }; export type Maakunta = { - id: number; + id: string; + koodi: string; nimi: RequiredLocalizedMap; - ely: number; + lakkautettu?: boolean; }; -const sykeKuntaIdToLocalizedNimi = () => - sykeKunnat.value.reduce((kunnat, kunta) => { - kunnat[kunta.Kunta_Id] = { - [Kieli.SUOMI]: kunta.Nimi, - [Kieli.RUOTSI]: kunta.NimiRuo, - }; - return kunnat; - }, {} as Record>); - -const sykeMaakuntaIdToMaakunta = () => - sykeMaakunnat.value.reduce((maakunnat, maakunta) => { - maakunnat[maakunta.Maakunta_Id] = { - nimi: { - [Kieli.SUOMI]: maakunta.Nimi, - [Kieli.RUOTSI]: maakunta.NimiRuo, - }, - elyId: maakunta.Ely_Id, - }; - return maakunnat; - }, {} as Record; elyId: number }>); - -abstract class AbstractLocalCache { - private readonly mapCacheKey: string; - private readonly listCacheKey: string; - - protected constructor(cacheKey: string) { - this.mapCacheKey = cacheKey + "_map"; - this.listCacheKey = cacheKey + "_list"; - } - - get list(): T[] { - if (!metadataCache.has(this.listCacheKey)) { - this.populateInternal(); - } - return metadataCache.get(this.listCacheKey)!; - } - - getById(id: number): T { - if (!metadataCache.has(this.mapCacheKey)) { - this.populateInternal(); - } - return (metadataCache.get(this.mapCacheKey)! as Record)[id]; - } - - private populateInternal() { - const { list, map } = this.populate(); - metadataCache.set(this.listCacheKey, list); - metadataCache.set(this.mapCacheKey, map); - } - - abstract populate(): { list: T[]; map: Record }; -} - -class Kunnat extends AbstractLocalCache { - constructor() { - super("kunnat"); - } - - populate(): { list: Kunta[]; map: Record } { - const kuntaList: Kunta[] = []; - const kuntaMap: Record = {}; - - const velhoKunnat = kuntametadata.extractLatestVersionOfVelhoMetadata(velhometadata, "alueet/kunta") as Record; - for (const velhoKuntaId in velhoKunnat) { - const velhoKunta = velhoKunnat[velhoKuntaId]; - if (!velhoKunta.lakkautettu) { - const kuntaId = Number.parseInt(velhoKunta.koodi); - let nimi = sykeKuntaIdToLocalizedNimi()[kuntaId]; - if (!nimi) { - // Honkajokea ei enää ole itsenäisenä kuntana - if (velhoKunta.otsikko !== "Honkajoki") { - log.warn("Kuntaa ei löydy syke-aineistosta", { nimi, velhoKunta }); - } - nimi = { SUOMI: velhoKunta.otsikko }; - } - const kunta = { - id: kuntaId, - nimi, - elyId: kuntametadata.parseNumberIdFromVelhoKey(velhoKunta.ely), - liikennevastuuElyId: kuntametadata.parseNumberIdFromVelhoKey(velhoKunta["liikennevastuu-ely"]), - maakuntaId: kuntametadata.parseNumberIdFromVelhoKey(velhoKunta.maakunta), - }; - kuntaList.push(kunta); - kuntaMap[kuntaId] = kunta; - } - } - return { list: kuntaList, map: kuntaMap }; - } -} - -class Maakunnat extends AbstractLocalCache { - constructor() { - super("maakunnat"); - } +export type Ely = { + nro: string; + lyhenne: string; + sykeElyId: number; +}; - populate(): { list: Maakunta[]; map: Record } { - const maakuntaList: Maakunta[] = []; - const maakuntaMap: Record = {}; - const velhoMaakunnat = kuntametadata.extractLatestVersionOfVelhoMetadata(velhometadata, "alueet/maakunta") as Record< - string, - VelhoMaakunta - >; - for (const velhoMaakuntaId in velhoMaakunnat) { - const velhoMaakunta = velhoMaakunnat[velhoMaakuntaId]; - if (!velhoMaakunta.lakkautettu) { - const maakuntaId = Number.parseInt(velhoMaakunta.koodi); - const sykeMaakunta = sykeMaakuntaIdToMaakunta()[maakuntaId]; - if (sykeMaakunta) { - const maakunta = { - id: maakuntaId, - nimi: sykeMaakunta.nimi, - ely: sykeMaakunta.elyId, - }; - maakuntaList.push(maakunta); - maakuntaMap[maakuntaId] = maakunta; - } - } - } - return { list: maakuntaList, map: maakuntaMap }; - } -} +export type AlueData = { + kunnat: Record; + maakunnat: Record; + elyt: Record; +}; class KuntaMetadata { - kunnat = new Kunnat(); - maakunnat = new Maakunnat(); - - extractLatestVersionOfVelhoMetadata(velhoJSON: typeof velhometadata, field: string): unknown { - const definition: any = (velhoJSON.info["x-velho-nimikkeistot"] as any)[field]; - return definition.nimikkeistoversiot[definition["uusin-nimikkeistoversio"]]; - } - - parseNumberIdFromVelhoKey(key: string): number { - const match = key.match(/\w+\/[a-z]+(\d+)/); - if (match && match.length == 2) { - const val = Number.parseInt(match[1]); - if (!isNaN(val)) { - return val; - } - } - throw new Error("Could not parse number from key:" + key); - } - public idsForKuntaNames(names: string[] | number[]): number[] { return names.map(kuntametadata.idForKuntaName); } @@ -192,11 +44,11 @@ class KuntaMetadata { return name; } const trimmedName = name.trim().toLowerCase(); - const kunta = kuntametadata.kunnat.list.find((kunta) => kunta.nimi.SUOMI.toLowerCase() == trimmedName); - if (kunta) { - return kunta.id; + const kuntaId = findKey(alueData.kunnat, (kunta: Kunta) => kunta.nimi.SUOMI.toLowerCase() == trimmedName); + if (kuntaId) { + return alueData.kunnat[kuntaId].id; } - throw new IllegalArgumentError("kuntaa ei löydy:" + name); + throw new IllegalArgumentError("kuntaa ei löydy: " + name); } idsForMaakuntaNames(names: string[] | number[]): number[] { @@ -207,20 +59,26 @@ class KuntaMetadata { if (typeof name == "number" || !isNaN(Number(name))) { return Number(name); } - const maakunta = kuntametadata.maakunnat.list.find((maakunta) => maakunta.nimi.SUOMI == name); - if (maakunta) { - return maakunta.id; + const maakuntaId = findKey(alueData.maakunnat, (maakunta) => { + return maakunta.nimi.SUOMI.toLowerCase() == name.toLowerCase(); + }); + if (maakuntaId) { + return Number.parseInt(maakuntaId); } throw new IllegalArgumentError("maakuntaa ei löydy:" + name); } public kuntaOptions(lang: string, addEmptyOption = true): { value: string; label: string }[] { let options: { label: string; value: string }[]; - const kuntaList = kuntametadata.kunnat.list; + const kuntaList = Object.values(alueData.kunnat); if (lang == "sv") { - options = kuntaList.map((kunta) => ({ value: String(kunta.id), label: kunta.nimi.RUOTSI || kunta.nimi.SUOMI })); + options = kuntaList + .filter((kunta) => !kunta.lakkautettu) + .map((kunta) => { + return { value: String(kunta.id), label: kunta.nimi.RUOTSI || kunta.nimi.SUOMI }; + }); } else { - options = kuntaList.map((kunta) => ({ value: String(kunta.id), label: kunta.nimi.SUOMI })); + options = kuntaList.filter((kunta) => !kunta.lakkautettu).map((kunta) => ({ value: String(kunta.id), label: kunta.nimi.SUOMI })); } if (addEmptyOption) { options.push({ label: "", value: "" }); @@ -230,11 +88,15 @@ class KuntaMetadata { public maakuntaOptions(lang: string, addEmptyOption = true): { value: string; label: string }[] { let options: { label: string; value: string }[]; - const maakuntaList = kuntametadata.maakunnat.list; + const maakuntaList = Object.values(alueData.maakunnat); if (lang == "sv") { - options = maakuntaList.map((kunta) => ({ value: String(kunta.id), label: kunta.nimi.RUOTSI || kunta.nimi.SUOMI })); + options = maakuntaList + .filter((maakunta) => !maakunta.lakkautettu) + .map((maakunta) => ({ value: String(maakunta.id), label: maakunta.nimi.RUOTSI || maakunta.nimi.SUOMI })); } else { - options = maakuntaList.map((kunta) => ({ value: String(kunta.id), label: kunta.nimi.SUOMI })); + options = maakuntaList + .filter((maakunta) => !maakunta.lakkautettu) + .map((maakunta) => ({ value: String(maakunta.id), label: maakunta.nimi.SUOMI })); } if (addEmptyOption) { options.push({ label: "", value: "" }); @@ -243,7 +105,7 @@ class KuntaMetadata { } public nameForKuntaId(kuntaId: number, kieli: Kieli | string): string { - const nimi = kuntametadata.kunnat.getById(kuntaId)?.nimi; + const nimi = alueData.kunnat[kuntaId]?.nimi; if (!nimi) { log.error("kuntaa-ei-löydy:" + kuntaId); return "kuntaa-ei-löydy:" + kuntaId; @@ -257,7 +119,7 @@ class KuntaMetadata { } public nameForMaakuntaId(maakuntaId: number, kieli: Kieli): string { - const nimi = kuntametadata.maakunnat.getById(maakuntaId)?.nimi; + const nimi = alueData.maakunnat[maakuntaId]?.nimi; if (!nimi) { log.error("maakuntaa-ei-löydy:" + maakuntaId); return "maakuntaa-ei-löydy:" + maakuntaId; @@ -278,13 +140,13 @@ class KuntaMetadata { return maakuntaIds?.map((maakuntaId) => kuntametadata.nameForMaakuntaId(maakuntaId, normalizeKieli(kieli))) || []; } - public viranomainenForMaakuntaId(maakuntaId: number): IlmoitettavaViranomainen { - const maakunta = sykeMaakuntaIdToMaakunta()[maakuntaId]; - if (!maakunta) { - throw new Error("Maakuntaa ei löydy:" + maakuntaId); + public viranomainenForKuntaId(kuntaId: number): IlmoitettavaViranomainen { + const kunta = alueData.kunnat[kuntaId]; + if (!kunta) { + throw new Error("Kuntaa ei löydy:" + kuntaId); } - const viranomainen = elyToIlmoitettavaViranomainen[maakunta.elyId]; + const viranomainen = elyToIlmoitettavaViranomainen[kunta.ely]; if (viranomainen) { return viranomainen; } @@ -292,27 +154,27 @@ class KuntaMetadata { } kuntaForKuntaId(kuntaId: number): Kunta | undefined { - return kuntametadata.kunnat.getById(kuntaId); + return alueData.kunnat[kuntaId]; } maakuntaForMaakuntaId(maakuntaId: number): Maakunta | undefined { - return kuntametadata.maakunnat.getById(maakuntaId); + return alueData.maakunnat[maakuntaId]; } /** - * Käytetään ilmoitustaulusyötteen avaimen muuttamiseen numero-id:ksi + * Käytetään ilmoitustaulusyötteen avaimen muuttamiseen id:ksi (esim. UUD -> "ely/ely01") * @param key */ elyIdFromKey(key: string) { - return elyt[key as keyof typeof elyt]?.id; + return Object.keys(alueData.elyt).find((elyKey) => alueData.elyt[elyKey].lyhenne == key); } - liikennevastuuElyIdFromElyId(elyId: number): number { - const ely = Object.values(elyt).find((ely) => ely.id == elyId); - if (ely) { - return ely.lelyId; + liikennevastuuElyIdFromKuntaId(kuntaId: number): string { + const liikennevastuuEly = alueData.kunnat[kuntaId].liikennevastuuEly; + if (liikennevastuuEly) { + return liikennevastuuEly; } - throw new IllegalArgumentError("Liikenne-ely ei löydy ely-id:lle " + elyId); + throw new IllegalArgumentError("Liikenne-ely ei löydy kuntaId:lle " + kuntaId); } } @@ -331,22 +193,21 @@ function normalizeKieli(kieli: Kieli | string): Kieli { export const kuntametadata = new KuntaMetadata(); -// Lähde: https://rajapinnat.ymparisto.fi/api/Hakemistorajapinta/1.0/odata/Ely -const elyToIlmoitettavaViranomainen: Record = { - 1001: IlmoitettavaViranomainen.UUDENMAAN_ELY, - 1005: IlmoitettavaViranomainen.ETELA_SAVO_ELY, - 1008: IlmoitettavaViranomainen.ETELA_POHJANMAAN_ELY, - 1003: IlmoitettavaViranomainen.HAME_ELY, - 1004: IlmoitettavaViranomainen.KAAKKOIS_SUOMEN_ELY, - 1009: IlmoitettavaViranomainen.KESKI_SUOMEN_ELY, - 1012: IlmoitettavaViranomainen.KAINUUN_ELY, - 1013: IlmoitettavaViranomainen.LAPIN_ELY, - 1019: IlmoitettavaViranomainen.PIRKANMAAN_ELY, - 1021: IlmoitettavaViranomainen.POHJANMAAN_ELY, - 1007: IlmoitettavaViranomainen.POHJOIS_KARJALAN_ELY, - 1011: IlmoitettavaViranomainen.POHJOIS_POHJANMAAN_ELY, - 1006: IlmoitettavaViranomainen.POHJOIS_SAVON_ELY, - 1020: IlmoitettavaViranomainen.SATAKUNNAN_ELY, - 1002: IlmoitettavaViranomainen.VARSINAIS_SUOMEN_ELY, - 1030: IlmoitettavaViranomainen.AHVENANMAAN_MAAKUNTA, +const elyToIlmoitettavaViranomainen: Record = { + "ely/ely01": IlmoitettavaViranomainen.UUDENMAAN_ELY, + "ely/ely07": IlmoitettavaViranomainen.ETELA_SAVO_ELY, + "ely/ely11": IlmoitettavaViranomainen.ETELA_POHJANMAAN_ELY, + "ely/ely04": IlmoitettavaViranomainen.HAME_ELY, + "ely/ely06": IlmoitettavaViranomainen.KAAKKOIS_SUOMEN_ELY, + "ely/ely10": IlmoitettavaViranomainen.KESKI_SUOMEN_ELY, + "ely/ely14": IlmoitettavaViranomainen.KAINUUN_ELY, + "ely/ely15": IlmoitettavaViranomainen.LAPIN_ELY, + "ely/ely05": IlmoitettavaViranomainen.PIRKANMAAN_ELY, + "ely/ely12": IlmoitettavaViranomainen.POHJANMAAN_ELY, + "ely/ely09": IlmoitettavaViranomainen.POHJOIS_KARJALAN_ELY, + "ely/ely13": IlmoitettavaViranomainen.POHJOIS_POHJANMAAN_ELY, + "ely/ely08": IlmoitettavaViranomainen.POHJOIS_SAVON_ELY, + "ely/ely03": IlmoitettavaViranomainen.SATAKUNNAN_ELY, + "ely/ely02": IlmoitettavaViranomainen.VARSINAIS_SUOMEN_ELY, + "ely/ely16": IlmoitettavaViranomainen.AHVENANMAAN_MAAKUNTA, }; diff --git a/package.json b/package.json index 6cdce626c..a91b4402e 100644 --- a/package.json +++ b/package.json @@ -158,12 +158,12 @@ "dev-under-construction": "next dev ./under-construction", "cypress": "cypress", "generate:velhoapi": "MSYS_NO_PATHCONV=1 cross-env docker run --rm --env-file .env.test -e VELHO_AUTH_URL -e VELHO_API_URL -e VELHO_USERNAME -e VELHO_PASSWORD -e VELHO_ACCESS_TOKEN=\"$(ts-node --project=tsconfig.cdk.json -r dotenv/config ./tools/velho/authenticate.ts dotenv_config_path=.env.test)\" -v $INIT_CWD:/work ${ACCOUNT_ID:=283563576583}.dkr.ecr.eu-west-1.amazonaws.com/hassu-build-image:$(cat .buildimageversion) /work/tools/velho/gradlew -p /work/tools/velho --info", - "postgenerate:velhoapi": "ts-node --project=tsconfig.cdk.json ./tools/velho/processMetaData.ts ./backend/src/velho/metadata.json ./common/generated/velhometadata.json ./common/generated/ely.json", + "postgenerate:velhoapi": "ts-node --project=tsconfig.cdk.json ./tools/velho/processMetaData.ts ./backend/src/velho/metadata.json", "pregenerate:api": "graphql-schema-utilities -s \"{./graphql/types.graphql,./graphql/inputs.graphql,./graphql/operations.graphql}\" -o schema.graphql", "generate:api": "cross-env docker run --rm -v $INIT_CWD:/work ${ACCOUNT_ID:=283563576583}.dkr.ecr.eu-west-1.amazonaws.com/hassu-build-image:$(cat .buildimageversion) bash -c \"cd /work && amplify codegen\"", "generate": "npm-run-all --aggregate-output --parallel generate:*", "buildimage:generate:velhoapi": "MSYS_NO_PATHCONV=1 VELHO_ACCESS_TOKEN=\"$(ts-node --project=tsconfig.cdk.json -r dotenv/config ./tools/velho/authenticate.ts dotenv_config_path=.env.test)\" ./tools/velho/gradlew -p ./tools/velho --info", - "postbuildimage:generate:velhoapi": "ts-node --project=tsconfig.cdk.json ./tools/velho/processMetaData.ts ./backend/src/velho/metadata.json ./common/generated/velhometadata.json ./common/generated/ely.json", + "postbuildimage:generate:velhoapi": "ts-node --project=tsconfig.cdk.json ./tools/velho/processMetaData.ts ./backend/src/velho/metadata.json", "prebuildimage:generate:api": "graphql-schema-utilities -s \"{./graphql/types.graphql,./graphql/inputs.graphql,./graphql/operations.graphql}\" -o schema.graphql", "buildimage:generate:api": "amplify codegen", "buildimage:generate": "npm-run-all --aggregate-output --parallel buildimage:generate:*", diff --git a/src/util/defaultVastaanottajat.ts b/src/util/defaultVastaanottajat.ts index a9a827f14..b54b3be1a 100644 --- a/src/util/defaultVastaanottajat.ts +++ b/src/util/defaultVastaanottajat.ts @@ -40,22 +40,24 @@ export default function defaultVastaanottajat( } else { // tapaus, jossa lomake alustetaan ensimmäistä kertaa const vaylavirastoKirjaamo = kirjaamoOsoitteet?.find((osoite) => osoite.nimi == "VAYLAVIRASTO"); - viranomaiset = - projekti?.velho?.suunnittelustaVastaavaViranomainen === "VAYLAVIRASTO" - ? projekti?.velho?.maakunnat?.map((maakunta) => { - const ely: IlmoitettavaViranomainen = kuntametadata.viranomainenForMaakuntaId(maakunta); - const kirjaamoOsoite = kirjaamoOsoitteet?.find((osoite) => osoite.nimi == ely); - if (kirjaamoOsoite) { - return { nimi: kirjaamoOsoite.nimi, sahkoposti: kirjaamoOsoite.sahkoposti }; - } else { - return { nimi: kuntametadata.nameForMaakuntaId(maakunta, Kieli.SUOMI), sahkoposti: "" } as ViranomaisVastaanottajaInput; - } - }) || [] - : [ - vaylavirastoKirjaamo - ? { nimi: vaylavirastoKirjaamo.nimi, sahkoposti: vaylavirastoKirjaamo.sahkoposti } - : ({ nimi: IlmoitettavaViranomainen.VAYLAVIRASTO, sahkoposti: "" } as ViranomaisVastaanottajaInput), - ]; + if (projekti?.velho?.suunnittelustaVastaavaViranomainen === "VAYLAVIRASTO") { + viranomaiset = + projekti?.velho?.kunnat?.map((kuntaId) => { + const ely: IlmoitettavaViranomainen = kuntametadata.viranomainenForKuntaId(kuntaId); + const kirjaamoOsoite = kirjaamoOsoitteet?.find((osoite) => osoite.nimi == ely); + if (kirjaamoOsoite) { + return { nimi: kirjaamoOsoite.nimi, sahkoposti: kirjaamoOsoite.sahkoposti }; + } else { + return { nimi: kuntametadata.nameForKuntaId(kuntaId, Kieli.SUOMI), sahkoposti: "" } as ViranomaisVastaanottajaInput; + } + }) || []; + } else { + viranomaiset = [ + vaylavirastoKirjaamo + ? { nimi: vaylavirastoKirjaamo.nimi, sahkoposti: vaylavirastoKirjaamo.sahkoposti } + : ({ nimi: IlmoitettavaViranomainen.VAYLAVIRASTO, sahkoposti: "" } as ViranomaisVastaanottajaInput), + ]; + } } return { kunnat, diff --git a/tools/velho/build.gradle b/tools/velho/build.gradle index 80c970333..50faea6b8 100644 --- a/tools/velho/build.gradle +++ b/tools/velho/build.gradle @@ -47,13 +47,13 @@ task downloadSwaggers { task downloadKuntaList(type: Download) { src 'http://rajapinnat.ymparisto.fi/api/Hakemistorajapinta/1.0/odata/Kunta' - dest "${buildDir}/../../../common/generated/kunnat.json".toString() + dest "build/kunnat.json".toString() overwrite false } task downloadMaakuntaList(type: Download) { src 'http://rajapinnat.ymparisto.fi/api/Hakemistorajapinta/1.0/odata/Maakunta' - dest "${buildDir}/../../../common/generated/maakunnat.json".toString() + dest "build/maakunnat.json".toString() overwrite false } diff --git a/tools/velho/processAlueData.ts b/tools/velho/processAlueData.ts new file mode 100644 index 000000000..72246b92a --- /dev/null +++ b/tools/velho/processAlueData.ts @@ -0,0 +1,132 @@ +import sykeKunnat from "./build/kunnat.json"; +import sykeMaakunnat from "./build/maakunnat.json"; +import sykeElyt from "./build/ely.json"; +import * as fs from "fs"; +import { Kieli } from "../../common/graphql/apiModel"; +import { Ely, Kunta, Maakunta } from "../../common/kuntametadata"; + +const metaDataJSON = JSON.parse(fs.readFileSync(__dirname + "/build/metadata.json").toString("UTF-8")); + +const velhometadata = { + info: { + "x-velho-nimikkeistot": ["alueet/kunta", "alueet/maakunta", "alueet/ely"].reduce((catalog: any, key) => { + catalog[key] = (metaDataJSON.info["x-velho-nimikkeistot"] as any)[key]; + return catalog; + }, {}), + }, +}; + +type VelhoKunta = { + maakunta: string; //"maakunta/maakunta17", + koodi: string; //"563", + otsikko: string; // "Oulainen", + "liikennevastuu-ely": string; //"ely/ely13", + ely: string; //"ely/ely13", + avi: string; // "avi/avi5" + lakkautettu?: string; + Nro: string; +}; + +type VelhoMaakunta = { + maakunta: string; //"maakunta/maakunta17", + koodi: string; //"563", + otsikko: string; + lakkautettu?: string; +}; + +type VelhoEly = { + koodi: string; + otsikko: string; +}; + +function parseKunnat(): Record { + const kuntaMap: Record = {}; + + const velhoKunnat = extractLatestVersionOfVelhoMetadata(velhometadata, "alueet/kunta") as Record; + for (const velhoKuntaId in velhoKunnat) { + const velhoKunta = velhoKunnat[velhoKuntaId]; + if (!velhoKunta.lakkautettu) { + const kuntaId = Number.parseInt(velhoKunta.koodi); + let velhoKuntanimi = velhoKunta.otsikko; + if (velhoKuntanimi == "Maarianhamina - Mariehamn") { + velhoKuntanimi = "Maarianhamina"; + } + let nimi = { SUOMI: velhoKuntanimi }; + let kunta: Kunta = { + id: kuntaId, + nimi, + ely: velhoKunta.ely, + liikennevastuuEly: velhoKunta["liikennevastuu-ely"], + maakunta: velhoKunta.maakunta, + }; + if (velhoKunta.lakkautettu) { + kunta.lakkautettu = true; + } else { + let sykeKunta = sykeKunnat.value.find((sykeKunta) => sykeKunta.Kunta_Id == kuntaId); + if (sykeKunta) { + kunta.nimi.RUOTSI = sykeKunta.NimiRuo; + } + } + kuntaMap[kuntaId] = kunta; + } + } + return kuntaMap; +} + +function parseMaakunnat(): Record { + const maakuntaMap: Record = {}; + const velhoMaakunnat = extractLatestVersionOfVelhoMetadata(velhometadata, "alueet/maakunta") as Record; + for (const velhoMaakuntaId in velhoMaakunnat) { + const velhoMaakunta = velhoMaakunnat[velhoMaakuntaId]; + const maakuntaId = Number.parseInt(velhoMaakunta.koodi); + const maakunta: Maakunta = { + id: velhoMaakuntaId, + koodi: velhoMaakunta.koodi, + nimi: { [Kieli.SUOMI]: velhoMaakunta.otsikko }, + }; + if (velhoMaakunta.lakkautettu) { + maakunta.lakkautettu = true; + } else { + let sykeMaakunta = sykeMaakunnat.value.find((sykeMaakunta) => sykeMaakunta.Maakunta_Id == maakuntaId); + if (sykeMaakunta) { + maakunta.nimi.RUOTSI = sykeMaakunta.NimiRuo; + } + } + maakuntaMap[maakuntaId] = maakunta; + } + return maakuntaMap; +} + +function parseVelhoElyt() { + const velhoElyt = extractLatestVersionOfVelhoMetadata(velhometadata, "alueet/ely") as Record; + return Object.keys(velhoElyt).reduce((result: Record, velhoElyId) => { + const velhoEly = velhoElyt[velhoElyId]; + const nro = velhoEly.koodi; + + let sykeEly = sykeElyt.value.find((sykeEly) => sykeEly.Nro == nro); + if (!sykeEly) { + throw new Error("Syke-elyä ei löydy numerolla " + nro); + } + + result[velhoElyId] = { nro, lyhenne: sykeEly.Lyhenne, sykeElyId: sykeEly.Ely_Id }; + return result; + }, {} as Record); +} + +function extractLatestVersionOfVelhoMetadata(velhoJSON: typeof velhometadata, field: string): unknown { + const definition: any = (velhoJSON.info["x-velho-nimikkeistot"] as any)[field]; + return definition.nimikkeistoversiot[definition["uusin-nimikkeistoversio"]]; +} + +export function processAlueData() { + const kunnat = parseKunnat(); + const maakunnat = parseMaakunnat(); + const elyt = parseVelhoElyt(); + + fs.writeFileSync( + __dirname + "/../../common/generated/aluedata.ts", + `import { AlueData } from "../kuntametadata"; +export const alueData : AlueData = ${JSON.stringify({ kunnat, maakunnat, elyt }, null, 2)}` + ); + console.log("Valmis."); +} diff --git a/tools/velho/processMetaData.ts b/tools/velho/processMetaData.ts index 8ec0516c2..cc89beca2 100644 --- a/tools/velho/processMetaData.ts +++ b/tools/velho/processMetaData.ts @@ -1,4 +1,5 @@ import * as fs from "fs"; +import { processAlueData } from "./processAlueData"; const metaDataJSON = JSON.parse(fs.readFileSync(__dirname + "/build/metadata.json").toString("UTF-8")); @@ -18,23 +19,6 @@ const redactedMetaData = { }; fs.writeFileSync(process.argv[2], JSON.stringify(redactedMetaData)); -const redactedMetaDataKunnatMaakunnat = { - info: { - "x-velho-nimikkeistot": ["alueet/kunta", "alueet/maakunta"].reduce((catalog: any, key) => { - catalog[key] = (metaDataJSON.info["x-velho-nimikkeistot"] as any)[key]; - return catalog; - }, {}), - }, -}; -fs.writeFileSync(process.argv[3], JSON.stringify(redactedMetaDataKunnatMaakunnat)); - -const elyData = JSON.parse(fs.readFileSync(__dirname + "/build/ely.json").toString()).value; -const elyt = elyData.reduce((all: Record, ely: any) => { - all[ely.Lyhenne] = { id: ely.Ely_Id, nimi: ely.Nimi, lelyId: ely.LiikenneEly_Id }; - return all; -}, {}); -fs.writeFileSync(process.argv[4], JSON.stringify(elyt)); - function extractVelhoValuesIntoMap(field: string) { const values: any = {}; const definition: any = (metaDataJSON.info["x-velho-nimikkeistot"] as any)[field]; @@ -58,3 +42,4 @@ function parseSuunnitelmanTilat() { } parseSuunnitelmanTilat(); +processAlueData();