feat(data-loading): load fee schedule catalogs and data from generated JSON payloads instead of bundled Germany TypeScript exports
This commit is contained in:
+20
-129
@@ -5,89 +5,17 @@ import { fileURLToPath } from 'node:url';
|
||||
|
||||
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
const sourceRoot = path.join(packageRoot, '.nogit', 'fee-schedules-sources');
|
||||
const outDir = path.join(packageRoot, 'ts', 'germany');
|
||||
const onlyGitDir = path.join(packageRoot, '.onlygit');
|
||||
const manifestPath = path.join(onlyGitDir, 'fee-schedules.sources.json');
|
||||
const outPath = path.join(onlyGitDir, 'fee-schedules.json');
|
||||
const generatedAt = new Date().toISOString().slice(0, 10);
|
||||
|
||||
const federalSources = [
|
||||
{ scheduleId: 'de-goae', fileName: 'goae', exportName: 'GERMANY_GOAE_FEE_SCHEDULE_DATA', sourcePath: 'go__1982', rowMode: 'code' },
|
||||
{ scheduleId: 'de-goz', fileName: 'goz', exportName: 'GERMANY_GOZ_FEE_SCHEDULE_DATA', sourcePath: 'goz_1987', rowMode: 'code' },
|
||||
{ scheduleId: 'de-gop', fileName: 'gop', exportName: 'GERMANY_GOP_FEE_SCHEDULE_DATA', sourcePath: 'gop', rowMode: 'none' },
|
||||
{ scheduleId: 'de-got', fileName: 'got', exportName: 'GERMANY_GOT_FEE_SCHEDULE_DATA', sourcePath: 'got_2022', rowMode: 'code' },
|
||||
{ scheduleId: 'de-stbvv', fileName: 'stbvv', exportName: 'GERMANY_STBVV_FEE_SCHEDULE_DATA', sourcePath: 'stbgebv', rowMode: 'table' },
|
||||
{ scheduleId: 'de-rvg', fileName: 'rvg', exportName: 'GERMANY_RVG_FEE_SCHEDULE_DATA', sourcePath: 'rvg', rowMode: 'code' },
|
||||
{ scheduleId: 'de-gnotkg', fileName: 'gnotkg', exportName: 'GERMANY_GNOTKG_FEE_SCHEDULE_DATA', sourcePath: 'gnotkg', rowMode: 'code' },
|
||||
{ scheduleId: 'de-gkg', fileName: 'gkg', exportName: 'GERMANY_GKG_FEE_SCHEDULE_DATA', sourcePath: 'gkg_2004', rowMode: 'code' },
|
||||
{ scheduleId: 'de-famgkg', fileName: 'famgkg', exportName: 'GERMANY_FAMGKG_FEE_SCHEDULE_DATA', sourcePath: 'famgkg', rowMode: 'code' },
|
||||
{ scheduleId: 'de-gvkostg', fileName: 'gvkostg', exportName: 'GERMANY_GVKOSTG_FEE_SCHEDULE_DATA', sourcePath: 'gvkostg', rowMode: 'code' },
|
||||
{ scheduleId: 'de-jveg', fileName: 'jveg', exportName: 'GERMANY_JVEG_FEE_SCHEDULE_DATA', sourcePath: 'jveg', rowMode: 'code' },
|
||||
{ scheduleId: 'de-insvv', fileName: 'insvv', exportName: 'GERMANY_INSVV_FEE_SCHEDULE_DATA', sourcePath: 'insvv', rowMode: 'none' },
|
||||
{ scheduleId: 'de-hoai', fileName: 'hoai', exportName: 'GERMANY_HOAI_FEE_SCHEDULE_DATA', sourcePath: 'hoai_2013', rowMode: 'table' },
|
||||
{ scheduleId: 'de-ampreisv', fileName: 'ampreisv', exportName: 'GERMANY_AMPREISV_FEE_SCHEDULE_DATA', sourcePath: 'ampreisv', rowMode: 'none' },
|
||||
];
|
||||
|
||||
const externalSources = [
|
||||
{
|
||||
scheduleId: 'de-ebm',
|
||||
fileName: 'ebm',
|
||||
exportName: 'GERMANY_EBM_FEE_SCHEDULE_DATA',
|
||||
sourceName: 'Kassenärztliche Bundesvereinigung EBM',
|
||||
sourceUrl: 'https://www.kbv.de/html/ebm.php',
|
||||
note: 'External self-administration source; not part of gesetze-im-internet federal XML corpus.',
|
||||
},
|
||||
{
|
||||
scheduleId: 'de-bema',
|
||||
fileName: 'bema',
|
||||
exportName: 'GERMANY_BEMA_FEE_SCHEDULE_DATA',
|
||||
sourceName: 'Kassenzahnärztliche Bundesvereinigung BEMA',
|
||||
sourceUrl: 'https://www.kzbv.de/bema',
|
||||
note: 'External dental self-administration source; not part of gesetze-im-internet federal XML corpus.',
|
||||
},
|
||||
{
|
||||
scheduleId: 'de-ag-drg-fpv',
|
||||
fileName: 'agdrgfpv',
|
||||
exportName: 'GERMANY_AGDRGFPV_FEE_SCHEDULE_DATA',
|
||||
sourceName: 'InEK aG-DRG Fallpauschalen-Katalog / FPV',
|
||||
sourceUrl: 'https://www.g-drg.de',
|
||||
note: 'Year-specific InEK catalog source; not part of gesetze-im-internet federal XML corpus.',
|
||||
},
|
||||
{
|
||||
scheduleId: 'de-uv-goae',
|
||||
fileName: 'uvgoae',
|
||||
exportName: 'GERMANY_UVGOAE_FEE_SCHEDULE_DATA',
|
||||
sourceName: 'Deutsche Gesetzliche Unfallversicherung UV-GOÄ',
|
||||
sourceUrl: 'https://www.dguv.de',
|
||||
note: 'External accident insurance fee schedule source; not part of gesetze-im-internet federal XML corpus.',
|
||||
},
|
||||
{
|
||||
scheduleId: 'de-heilmittel-gkv',
|
||||
fileName: 'heilmittelgkv',
|
||||
exportName: 'GERMANY_HEILMITTELGKV_FEE_SCHEDULE_DATA',
|
||||
sourceName: 'GKV-Spitzenverband Heilmittel contracts and price lists',
|
||||
sourceUrl: 'https://www.gkv-spitzenverband.de/krankenversicherung/ambulante_leistungen/heilmittel/heilmittel.jsp',
|
||||
note: 'External contract and price list source by remedy area; not part of gesetze-im-internet federal XML corpus.',
|
||||
},
|
||||
{
|
||||
scheduleId: 'de-hebammenhilfevertrag',
|
||||
fileName: 'hebammenhilfevertrag',
|
||||
exportName: 'GERMANY_HEBAMMENHILFEVERTRAG_FEE_SCHEDULE_DATA',
|
||||
sourceName: 'GKV-Spitzenverband Hebammenhilfevertrag',
|
||||
sourceUrl: 'https://www.gkv-spitzenverband.de/krankenversicherung/ambulante_leistungen/hebammen_geburtshaeuser/hebammenhilfevertrag/hebammenhilfevertrag.jsp',
|
||||
note: 'External contract and remuneration agreement source; not part of gesetze-im-internet federal XML corpus.',
|
||||
},
|
||||
{
|
||||
scheduleId: 'de-gebueh',
|
||||
fileName: 'gebueh',
|
||||
exportName: 'GERMANY_GEBUEH_FEE_SCHEDULE_DATA',
|
||||
sourceName: 'Gebührenverzeichnis für Heilpraktiker',
|
||||
sourceUrl: 'https://www.gebueh.de',
|
||||
note: 'Non-official customary fee directory; not part of gesetze-im-internet federal XML corpus.',
|
||||
},
|
||||
];
|
||||
|
||||
const allSources = [...federalSources, ...externalSources];
|
||||
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
||||
const federalSources = manifest.generationSources.federal;
|
||||
const externalSources = manifest.generationSources.external;
|
||||
|
||||
fs.mkdirSync(sourceRoot, { recursive: true });
|
||||
fs.mkdirSync(outDir, { recursive: true });
|
||||
fs.mkdirSync(onlyGitDir, { recursive: true });
|
||||
|
||||
const decodeEntities = (input) => input
|
||||
.replace(/ | /g, ' ')
|
||||
@@ -140,20 +68,6 @@ const getRowType = (cells, mode) => {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const writeGeneratedTsFile = (fileName, exportName, data) => {
|
||||
const filePath = path.join(outDir, `${fileName}.ts`);
|
||||
const body = [
|
||||
`// Generated by scripts/generate-germany.mjs on ${generatedAt}.`,
|
||||
'// Do not edit this file manually.',
|
||||
"import type { IFeeScheduleData } from '../feeschedules.types.js';",
|
||||
'',
|
||||
`export const ${exportName}: IFeeScheduleData = ${JSON.stringify(data, null, 2)};`,
|
||||
'',
|
||||
].join('\n');
|
||||
|
||||
fs.writeFileSync(filePath, body);
|
||||
};
|
||||
|
||||
const downloadFederalXml = async (source) => {
|
||||
const zipUrl = `https://www.gesetze-im-internet.de/${source.sourcePath}/xml.zip`;
|
||||
const zipPath = path.join(sourceRoot, `${source.sourcePath}.zip`);
|
||||
@@ -303,49 +217,26 @@ const getExternalSourceData = (source) => ({
|
||||
notes: [source.note],
|
||||
});
|
||||
|
||||
for (const source of allSources) {
|
||||
const filePath = path.join(outDir, `${source.fileName}.ts`);
|
||||
if (fs.existsSync(filePath)) {
|
||||
fs.rmSync(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
const generatedData = [];
|
||||
const scheduleData = [];
|
||||
|
||||
for (const source of federalSources) {
|
||||
const data = await parseFederalSource(source);
|
||||
writeGeneratedTsFile(source.fileName, source.exportName, data);
|
||||
generatedData.push({ ...source, data });
|
||||
console.log(`${source.fileName}.ts: ${data.dataStatus}, rows=${data.feeRows.length}, sections=${data.ruleSections.length}`);
|
||||
scheduleData.push(data);
|
||||
console.log(`${source.fileName}: ${data.dataStatus}, rows=${data.feeRows.length}, sections=${data.ruleSections.length}`);
|
||||
}
|
||||
|
||||
for (const source of externalSources) {
|
||||
const data = getExternalSourceData(source);
|
||||
writeGeneratedTsFile(source.fileName, source.exportName, data);
|
||||
generatedData.push({ ...source, data });
|
||||
console.log(`${source.fileName}.ts: ${data.dataStatus}, rows=0, sections=0`);
|
||||
scheduleData.push(data);
|
||||
console.log(`${source.fileName}: ${data.dataStatus}, rows=0, sections=0`);
|
||||
}
|
||||
|
||||
const indexImports = generatedData
|
||||
.map((source) => `import { ${source.exportName} } from './${source.fileName}.js';`)
|
||||
.join('\n');
|
||||
const payload = {
|
||||
schemaVersion: 1,
|
||||
generatedAt,
|
||||
catalogs: manifest.catalogs,
|
||||
scheduleData,
|
||||
};
|
||||
|
||||
const indexExports = generatedData
|
||||
.map((source) => `export { ${source.exportName} } from './${source.fileName}.js';`)
|
||||
.join('\n');
|
||||
|
||||
const indexBody = [
|
||||
`// Generated by scripts/generate-germany.mjs on ${generatedAt}.`,
|
||||
'// Do not edit this file manually.',
|
||||
"import type { IFeeScheduleData } from '../feeschedules.types.js';",
|
||||
indexImports,
|
||||
'',
|
||||
indexExports,
|
||||
'',
|
||||
'export const GERMANY_FEE_SCHEDULE_DATA: IFeeScheduleData[] = [',
|
||||
...generatedData.map((source) => ` ${source.exportName},`),
|
||||
'];',
|
||||
'',
|
||||
].join('\n');
|
||||
|
||||
fs.writeFileSync(path.join(outDir, 'index.ts'), indexBody);
|
||||
fs.writeFileSync(outPath, `${JSON.stringify(payload, null, 2)}\n`);
|
||||
console.log(`wrote ${path.relative(packageRoot, outPath)}`);
|
||||
|
||||
Reference in New Issue
Block a user