4.6 KiB
4.6 KiB
phase, plan, status, subsystem, tags, requirements, dependency-graph, tech-stack, key-files, decisions, metrics
| phase | plan | status | subsystem | tags | requirements | dependency-graph | tech-stack | key-files | decisions | metrics | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| quick-260723-e7i | 01 | complete | tenders |
|
|
|
|
|
|
|
Quick Task 260723-e7i: Normalizer-Gap Phase 13 schliessen (NetServer/Cosinex-Bag-Dispatch) Summary
Fixed TenderNormalizerService.normalize() to dispatch per sourceType, so ai-netserver and cosinex-dtvp records (which carry a flat ocdsPayload bag instead of eForms/OCDS structure) map their real title/buyerName/procedureType/deadlineAt instead of falling through to defaults/nulls — unblocking cross-source fingerprint dedup between DÖE and the scraper adapters.
What Was Built
Task 1 — Per-sourceType dispatch + shared assemble():
- Extracted a private
assemble(raw, core)method that computesstatus,dedupKey,contentHash(via the existingcomputeContentHash, not duplicated), andpublishedAt, plus the pass-through identity fields (sourcePortal,sourceNoticeId,ocid,sourceUrl). - Moved the existing DÖE eForms/OCDS extraction logic into
normalizeDoe(raw)— byte-identical behavior, confirmed by the full pre-existing test suite staying green. - Added
normalizeBag(raw)for the flat bag shape shared by NetServer and cosinex/DTVP: readsraw.ocdsPayloaddefensively, mapstitle(fallback'Unbenannte Ausschreibung'when empty/missing),buyerName/procedureType(null-tolerant, no invented fallback strings),deadlineAtvia the existingparseOcdsDate().cpvCodes/cpvDivisions=[],region/plz/bundesland/estimatedValue=null.legalFrameworkis read but intentionally not mapped (no target field). normalize()now doesswitch (raw.sourceType):ai-netserver/cosinex-dtvp→normalizeBag;doe-opendata/default→normalizeDoe(default never throws, protecting the additiveSourceTypeunion).
Task 2 — Unit tests:
- Added
bagRecord(sourceType, bag)helper to construct inlineRawTenderRecords for the bag sources (no fixture ZIPs exist for these). - New tests: full-bag mapping for
ai-netserverandcosinex-dtvp(identical shape → identical mapping), null/empty-field fallback (buyerName/procedureType/deadlineAtstaynull, emptytitlefalls back), and acontentHashsha256-format assertion provingassemble()reuse. - Existing DÖE fixture-based regression tests (10 pre-existing tests) untouched and still green.
Task 3 — Non-regression gate:
npx tsc --noEmit -p tsconfig.json— clean.npx vitest run— full API suite: 288/288 tests passed across 25 test files (up from the pre-existing baseline + 4 new bag tests), includingtender-dedup.service.spec.ts,tender-ingestion.service.spec.ts, andtender-fingerprint.spec.ts. No code change needed in this task.
Deviations from Plan
None — plan executed exactly as written.
Test Results
npx vitest run src/tenders/tender-normalizer.service.spec.ts— 14/14 passed (10 pre-existing DÖE tests + 4 new bag tests)npx tsc --noEmit -p tsconfig.json— clean, no errorsnpx vitest run(full API suite) — 288/288 passed, 25 test files, 3.06s