Commit Graph

4 Commits

Author SHA1 Message Date
Claude VM aa246c2d91 fix(epay-ui): show localitate + judet on intern extracts; hide cancelled rows
The intern (and gis-api-sourced) rows showed an empty "jud." with no UAT name
or county, and a few dead cancelled/test rows cluttered the list.

- gis-api returns siruta + uatName but judetName is null there, and the
  CfExtractRow type didn't even declare those fields so adaptCfRow blanked
  them. Added the fields to the type; adaptCfRow now surfaces uatName + siruta.
- New enrichCfLocations(rows) fills missing uatName/judetName from SIRUTA via
  the local GisUat table (batched, one query). Applied in both list proxies
  (/api/cf/orders for gis rows, /api/ancpi/orders for old legacy intern rows
  whose judetName was stored empty). So intern rows now read "LOCALITATE,
  jud. X".
- Hide status='cancelled' rows from the Extrase CF list (dead — payment
  refused / cleaned-up bad orders, e.g. the old 354686 test). failed/review
  stay (actionable via Reincearca).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 21:25:23 +03:00
Claude VM f49fdb1da0 harden(epay): cart hygiene, auth/IDOR gates, single-page fetch, parallel downloads
Live-path hardening from the 2026-06-04 deep-dive (11 confirmed criticals).
ArchiTools-only; the legacy queue is still the sole fulfiller.

Security:
- requireCfAccess() — staff-only, portal accounts blocked, fail-closed
  in-route on download / download-zip / cf-status / orders (C4 IDOR/PII)
  and order / recover (C3). order also enforces a daily credit cap
  (ANCPI_DAILY_CREDIT_CAP, default 200) and stamps userId.
- /api/ancpi/test returns 404 in production — it was a GET that spends 2
  real credits, CSRF-able (C5).
- drop the token-metadata debug blob from the session (QW8).

Correctness / robustness:
- cart hygiene (C1): build the ePay cart under an invariant — the Nth add
  must report N items; any excess = pre-existing junk, so we wipe + abort
  (never submit a cart we didn't fully build). Pre-submit failures clean
  up our basket rows; post-submit we never touch the cart (recover owns
  it). metadata-less rows are deleted from the cart.
- getOrderStatus fetches the whole order in ONE page (itemsPerPage, QW4);
  navDir loop kept only as fallback. index-fallback matches are flagged
  'review' instead of silently 'completed' with a possibly-wrong PDF (R4).
- downloadDocument asserts %PDF magic bytes — a login page returned mid
  session no longer gets stored as a .pdf (R2). Session reuse TTL aligned
  under ANCPI's ~10min expiry.
- recover accepts ?extractId= and pre-submit states; retry buttons in the
  ePay tab re-run poll+download with no new charge (QW2/QW3).

Performance:
- parallel document downloads (V1, concurrency 4); poll writes only on
  status change via updateMany (QW5); getNextFileIndex scans the cadastral
  prefix instead of the whole bucket — and actually works now (it was
  ^-anchoring the full key, so every file got index 1) (V2); download-zip
  streams instead of buffering the whole archive, capped at 100 (V3).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 23:59:44 +03:00
AI Assistant a59d9bc923 feat(ancpi): complete ePay UI redesign + ZIP download + smart batch ordering
UI Redesign:
- ePay auto-connect when UAT is selected (no manual button)
- Credit badge with tooltip ("N credite ePay disponibile")
- Search result cards show CF status: Valid (green), Expirat (orange),
  Lipsă (gray), Se proceseaza (yellow pulse)
- Action buttons on each card: download/update/order CF extract
- "Lista mea" numbered rows + CF Status column + smart batch button
  "Scoate Extrase CF": skips valid, re-orders expired, orders new
- "Descarca Extrase CF" button → ZIP archive with numbered files
- Extrase CF tab simplified: clean table, filters (Toate/Valabile/
  Expirate/In procesare), search, download-all ZIP

Backend:
- GET /api/ancpi/download-zip?ids=... → JSZip streaming
- GET /api/ancpi/orders: multi-cadastral status check with statusMap
  (valid/expired/none/processing) + latestById

Data:
- Simulated expired extract for 328611 (Cluj-Napoca, expired 2026-03-17)
- Cleaned old error records from DB

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 09:13:51 +02:00
AI Assistant 3921852eb5 feat(parcel-sync): add ANCPI ePay CF extract ordering backend
Foundation (Phase 1):
- CfExtract Prisma model with version tracking, expiry, MinIO path
- epay-types.ts: all ePay API response types
- epay-counties.ts: WORKSPACE_ID → ePay county index mapping (42 counties)
- epay-storage.ts: MinIO helpers (bucket, naming, upload, download)
- docker-compose.yml: ANCPI env vars

ePay Client (Phase 2):
- epay-client.ts: full HTTP client (login, credits, cart, search estate,
  submit order, poll status, download PDF) with cookie jar + auto-relogin
- epay-session-store.ts: separate session from eTerra

Queue + API (Phase 3):
- epay-queue.ts: sequential FIFO queue (global cart constraint),
  10-step workflow per order with DB status updates at each step
- POST /api/ancpi/session: connect/disconnect
- POST /api/ancpi/order: create single or bulk orders
- GET /api/ancpi/orders: list all extracts
- GET /api/ancpi/credits: live credit balance
- GET /api/ancpi/download: stream PDF from MinIO

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 00:09:52 +02:00