initial: split from gov-agreg — vreau.digital standalone platform

Moved from gov-agreg/src/pages/achizitii/* to root (drop prefix).
- 22 pages migrated, 127 files total
- All internal links: /achizitii/X → /X (176 occurrences fixed)
- AchizitiiLayout subnav rewritten: /X paths, top-right link to vreaudigital.ro hub
- BaseLayout new (vreau.digital branding, OG tags, site URL)
- astro.config.mjs: site https://vreau.digital, server output (was static)
- docker-compose: port 5096 (vreaudigital is 5095), container vreau-digital
- deploy.sh: paths /opt/vreau-digital, log /var/log/vreau-digital-deploy.log

Backend shared with gov-agreg:
- PostgreSQL satra (same schemas: seap, firms, anaf, anre, ...)
- Photon, Martin tiles
- Infisical /vreaudigital path (DATABASE_URL etc. shared)

build: PASS (npx astro check 0 errors, npm run build 5s vite + 10s server)
This commit is contained in:
Claude VM
2026-05-13 00:10:32 +03:00
commit a6c03a091e
352 changed files with 75295 additions and 0 deletions
@@ -0,0 +1,56 @@
/**
* Standalone test for CNAS Layout-B parser.
*
* Reads pdftotext -layout output for the 8 known Layout-B PDFs (the 9th is
* an empty form template), parses with parseProviderTextJudetGrouped(), and
* prints results for manual inspection.
*
* Usage:
* npx tsx scripts/test-cnas-layout-b.ts /tmp/cnas-pdfs/Lista-furnizori-testare-genetica-2024-2025_all.pdf
* npx tsx scripts/test-cnas-layout-b.ts /tmp/cnas-pdfs/*.pdf
*/
import { execFile } from 'child_process';
import { promisify } from 'util';
import { basename } from 'path';
import { parseProviderTextJudetGrouped, parseProviderTextRadio, parseProviderTextSingleCAS, parseProviderTextNumberedDot } from '../src/cnas-layout-b.js';
const execFileAsync = promisify(execFile);
async function pdftotextLayout(pdfPath: string): Promise<string> {
const { stdout } = await execFileAsync('pdftotext', ['-layout', '-enc', 'UTF-8', pdfPath, '-'], {
maxBuffer: 64 * 1024 * 1024,
});
return stdout;
}
async function main() {
const files = process.argv.slice(2);
if (files.length === 0) {
console.error('Usage: tsx test-cnas-layout-b.ts <pdf>...');
process.exit(1);
}
for (const f of files) {
const fn = basename(f);
console.log(`\n=== ${fn} ===`);
const text = await pdftotextLayout(f);
let rows;
if (/radioterapie/i.test(fn)) {
rows = parseProviderTextRadio(text, { tip: 'radioterapie' });
} else if (/CAS-GORJ.*PNS/i.test(fn) || /Valori-de-contract-furnizori-PNS/i.test(fn)) {
rows = parseProviderTextSingleCAS(text, { tip: 'pns', judet: 'GORJ' });
} else if (/ASISTENTA-MEDICALA-PRIMARA/i.test(fn)) {
rows = parseProviderTextNumberedDot(text, { tip: 'medicina_familie', judet: 'SIBIU' });
} else {
rows = parseProviderTextJudetGrouped(text, { tip: 'oncologie' });
}
const limit = parseInt(process.env.TEST_LIMIT || '20');
console.log(`Parsed ${rows.length} rows`);
for (let i = 0; i < Math.min(rows.length, limit); i++) {
const r = rows[i];
console.log(` [${i + 1}] judet=${r.judet || '-'} name="${r.name}" sediu="${r.sediu || '-'}" tel=${r.telefon || '-'} email=${r.email || '-'} flags=${r.specialitate || '-'}`);
}
if (rows.length > limit) console.log(` ... and ${rows.length - limit} more`);
}
}
main().catch((e) => { console.error(e); process.exit(1); });