docs: update SKILLS.md with complete ANCPI ePay documentation
This commit is contained in:
@@ -214,6 +214,89 @@ siruta, layerId, status, totalRemote, totalLocal, newFeatures, removedFeatures,
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## ANCPI ePay — CF Extract Ordering
|
||||||
|
|
||||||
|
### Overview
|
||||||
|
|
||||||
|
Orders CF extracts (Carte Funciară) from ANCPI ePay (epay.ancpi.ro).
|
||||||
|
Separate auth system from eTerra. Uses credits (prepaid, 1 per extract).
|
||||||
|
|
||||||
|
### Critical Discovery: ID Mapping
|
||||||
|
|
||||||
|
- **ePay internal county IDs = eTerra WORKSPACE_IDs** (CLUJ=127, ALBA=10, etc.)
|
||||||
|
- **ePay UAT IDs = SIRUTA codes** (Cluj-Napoca=54975, Florești=57706)
|
||||||
|
- This means ZERO discovery calls needed — use GisUat.workspacePk + siruta directly
|
||||||
|
|
||||||
|
### Auth Flow (OpenAM)
|
||||||
|
|
||||||
|
1. GET login page with `module=SelfRegistration&goto=http://epay.ancpi.ro:80/epay/LogIn.action`
|
||||||
|
2. POST credentials (`IDToken1`, `IDToken2`) → gets `AMAuthCookie` (NOT `iPlanetDirectoryPro`)
|
||||||
|
3. Navigate to `http://epay.ancpi.ro:80/epay/LogIn.action` (HTTP, not HTTPS!) for JSESSIONID
|
||||||
|
4. Session TTL: ~1 hour
|
||||||
|
|
||||||
|
### Order Flow (4 requests per batch)
|
||||||
|
|
||||||
|
1. `POST AddToCartOrWishListFromPost.action` × N → basketRowIds
|
||||||
|
2. `POST EpayJsonInterceptor.action` (multipart) × N → `reqType=saveProductMetadataForBasketItem` + `productMetadataJSON`
|
||||||
|
3. `POST EditCartSubmit.action` → `goToCheckout=true` (ONE submit for ALL items)
|
||||||
|
4. `GET CheckoutConfirmationSubmit.action` → confirms order
|
||||||
|
5. Poll `ShowOrderDetails.action?orderId=...` → parse documents from HTML-encoded JSON (`"` → `"`)
|
||||||
|
6. `POST DownloadFile.action?typeD=4&id=...` with `Content-Type: application/pdf` in REQUEST header
|
||||||
|
|
||||||
|
### ePay Endpoint Gotchas
|
||||||
|
|
||||||
|
1. **EpayJsonInterceptor uses form-urlencoded** (NOT JSON): `reqType=nomenclatorUAT&countyId=127`
|
||||||
|
2. **saveProductMetadataForBasketItem uses multipart/form-data** (form-data npm package)
|
||||||
|
3. **CF/CAD use `stringValues[0]`** (array!), not `stringValue`
|
||||||
|
4. **Document IDs are HTML-encoded** in ShowOrderDetails: `"idDocument":47301767` → decode first
|
||||||
|
5. **DownloadFile sends Content-Type: application/pdf in the REQUEST** (not response)
|
||||||
|
6. **EditCartSubmit returns 200** (not redirect) — Angular does client-side redirect to CheckoutConfirmation
|
||||||
|
7. **SearchEstate needs `identificator`/`judet`/`uat`** (not `identifier`/`countyId`/`uatId`), plus requires internal IDs
|
||||||
|
8. **MinIO metadata must be ASCII** — strip diacritics from values (`Florești` → `Floresti`)
|
||||||
|
|
||||||
|
### Dedup Protection
|
||||||
|
|
||||||
|
- **Queue level**: batch key = sorted cadastral numbers, 60s dedup window
|
||||||
|
- **API level**: optional `nonce` field, 60s idempotency cache
|
||||||
|
- **Test endpoint**: 30s dedup on hardcoded test parcels
|
||||||
|
|
||||||
|
### Key Files
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `services/epay-client.ts` | HTTP client (login, cart, metadata, submit, poll, download) |
|
||||||
|
| `services/epay-queue.ts` | Batch queue with dedup |
|
||||||
|
| `services/epay-storage.ts` | MinIO storage helpers |
|
||||||
|
| `services/epay-counties.ts` | County index mapping (legacy, not needed for ordering) |
|
||||||
|
| `services/epay-session-store.ts` | Session singleton |
|
||||||
|
| `services/epay-types.ts` | TypeScript types |
|
||||||
|
| `components/epay-connect.tsx` | Connection widget |
|
||||||
|
| `components/epay-order-button.tsx` | Per-parcel order button |
|
||||||
|
| `components/epay-tab.tsx` | Full "Extrase CF" tab |
|
||||||
|
| `api/ancpi/session/` | Connect/disconnect |
|
||||||
|
| `api/ancpi/order/` | Create batch orders |
|
||||||
|
| `api/ancpi/orders/` | List all extracts |
|
||||||
|
| `api/ancpi/credits/` | Credit balance |
|
||||||
|
| `api/ancpi/download/` | Stream PDF from MinIO |
|
||||||
|
| `api/ancpi/test/` | Diagnostic/test endpoint (temporary) |
|
||||||
|
|
||||||
|
### DB Model: CfExtract
|
||||||
|
|
||||||
|
- `orderId` — shared across batch items (NOT unique)
|
||||||
|
- `nrCadastral`, `siruta`, `judetName`, `uatName` — parcel identity
|
||||||
|
- `status` — pending|queued|cart|ordering|polling|downloading|completed|failed|cancelled
|
||||||
|
- `minioPath` — `parcele/{nrCadastral}/{idx}_Extras CF_{nrCadastral} - {DD-MM-YYYY}.pdf`
|
||||||
|
- `expiresAt` — 30 days after documentDate
|
||||||
|
- `version` — increments on re-order for same cadastral number
|
||||||
|
|
||||||
|
### Credentials
|
||||||
|
|
||||||
|
- Env vars: `ANCPI_USERNAME`, `ANCPI_PASSWORD` (hardcoded in docker-compose for Portainer CE)
|
||||||
|
- Default solicitant: ID `14452` (Beletage persoană juridică)
|
||||||
|
- MinIO bucket: `ancpi-documente`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Last Updated
|
## Last Updated
|
||||||
|
|
||||||
2026-03-22 — Added county population via nomenclature API, local feature count in UAT dropdown.
|
2026-03-23 — ANCPI ePay CF extract ordering: full backend + UI + dedup protection.
|
||||||
|
|||||||
Reference in New Issue
Block a user