test(10-03): add failing specs + real DÖE fixtures for adapter/normalizer
- Capture real, trimmed DÖE day-export fixtures (pubDay=2026-07-19, 8 notices spanning tender/award/planning/untagged-with-awards tag classes) under tenders/__fixtures__/, live-downloaded from oeffentlichevergabe.de - Define RawTenderRecord/NormalizedTenderFields/SourceType (tender.types.ts) and TenderSourceAdapter (day-cursor fetchTenders signature per RESEARCH Pattern 1) - RED: doe-opendata.adapter.spec.ts asserts D-02 exact-count filtering, HTTP-400 no-op, and a zip-bomb ceiling guard (T-10-07) - RED: tender-normalizer.service.spec.ts asserts eForms-primary deadline recovery where OCDS is null (RESEARCH Pattern 3), nullable deadline/value, dedupKey priority (ocid -> sourcePortal:sourceNoticeId), and a stable sha256 contentHash
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import type { RawTenderRecord, SourceType } from '../tender.types';
|
||||
|
||||
/**
|
||||
* Contract implemented by every tender source adapter (DÖE OpenData this
|
||||
* phase; AI-NetServer/cosinex/RSS/email-alert in later phases).
|
||||
*
|
||||
* `fetchTenders` takes a day-cursor string (`YYYY-MM-DD`), NOT a `since: Date`
|
||||
* timestamp — the DÖE OpenData API is a daily batch-export API with no
|
||||
* incremental/since parameter (RESEARCH.md Pattern 1 corrects the
|
||||
* `ARCHITECTURE.md` sketch's `since?: Date` signature). Day-cursor is kept
|
||||
* as the shared interface shape so future adapters that ARE incremental
|
||||
* (e.g. RSS) can still satisfy it by treating the day as a coarse filter,
|
||||
* rather than forking the interface per source.
|
||||
*/
|
||||
export interface TenderSourceAdapter {
|
||||
readonly sourceType: SourceType;
|
||||
|
||||
/**
|
||||
* Fetch and lightly parse all open-tender ("tender"-tagged", D-02)
|
||||
* notices for the given calendar day (Europe/Berlin), already filtered —
|
||||
* implementations must NOT return award/planning/untagged-with-awards
|
||||
* notices.
|
||||
*
|
||||
* @param dayCursor - `YYYY-MM-DD`, must be strictly in the past (today/
|
||||
* future is rejected upstream by the DÖE API with HTTP 400). Implementations
|
||||
* treat that 400 as an expected no-op and resolve to `[]`, never throw.
|
||||
*/
|
||||
fetchTenders(dayCursor: string): Promise<RawTenderRecord[]>;
|
||||
}
|
||||
Reference in New Issue
Block a user