diff --git a/README.md b/README.md index cb6b1a2..fda92ef 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,3 @@ -# api +## Documentation -Current JWT payload: -```json -{ - "username": "saman_insurer@gmail.com", - "sub": "6a144979799f3c63aa63f67c", - "fullName": "بیمه گر سامان", - "role": "company", - "userType": "UserType", - "clientKey": "67f0fd0e53868dc1ff8a2738", - "iat": 1781339791, - "exp": 1781343391 -} -``` +- [Fanavaran integration](docs/fanavaran/README.md) \ No newline at end of file diff --git a/docs/documening-fanavaran-flow.md b/docs/documening-fanavaran-flow.md new file mode 100644 index 0000000..1a3a2a8 --- /dev/null +++ b/docs/documening-fanavaran-flow.md @@ -0,0 +1,27 @@ +--- +last_updated: 2026-08-08 +tags: [fanavaran, documentation] +source: fanavaran-module-docs +--- + +# Fanavaran documentation brief (moved) + +The implementation reference for Fanavaran (Parsian template, multi-tenant) now lives under: + +**[docs/fanavaran/README.md](./fanavaran/README.md)** + +That set covers the original goals: + +1. Write APIs (auth + GEN.03/07/08/12) +2. Read/lookup APIs +3. Constants +4. Tenant vs shared matrix +5. Full claim flow + diagrams +6. YARA integration points +7. Data mapping +8. System dependencies +9. Error handling +10. Testing +11. New-client onboarding checklist + +Related: [external-api-curls.md](./external-api-curls.md), `.agents/skills/fanavaran-apis/references/third-party-cases.md`. diff --git a/docs/fanavaran/01-write-apis.md b/docs/fanavaran/01-write-apis.md new file mode 100644 index 0000000..03d837f --- /dev/null +++ b/docs/fanavaran/01-write-apis.md @@ -0,0 +1,345 @@ +--- +last_updated: 2026-08-08 +tags: [fanavaran, api, write, gen03, gen07, gen08, gen12] +source: fanavaran-module-docs +--- + +# 01 — Write APIs (Claim Registration) + +Base host: + +```text +https://apimanager.iraneit.com/BimeApiManager/api +BimeApi v2: .../api/BimeApi/v2.0 +``` + +Common business headers (after Login): + +| Header | Source | +|--------|--------| +| `authenticationToken` | Login response | +| `CorpId` | Tenant auth | +| `ContractId` | Tenant auth | +| `Location` | Tenant auth | +| `Content-Type` | `application/json` (except GEN.07 multipart) | + +Template values below are **Parsian-proven** unless noted. + +--- + +## 1. GetAppToken + +| Item | Value | +|------|-------| +| نام عملیات | دریافت App Token | +| Endpoint | `POST /api/EITAuthentication/GetAppToken` | +| Method | `POST` | +| Body | Empty (`Content-Length: 0`; no JSON) | +| Authentication | Headers `appname`, `secret` (tenant) | + +**Headers** + +| Header | Required | Notes | +|--------|----------|-------| +| `appname` | ✅ | Tenant `auth.appName` | +| `secret` | ✅ | Tenant `auth.secret` | + +**Success:** token in response header `appToken` / `apptoken`. +**Error:** invalid app credentials → Fanavaran error body/message. + +**YARA:** `FanavaranAuthService` → `getAppTokenUrl`. + +--- + +## 2. Login + +| Item | Value | +|------|-------| +| نام عملیات | ورود و دریافت authenticationToken | +| Endpoint | `POST /api/EITAuthentication/Login` | +| Method | `POST` | +| Body | Empty | +| Authentication | `appToken` + `userName` + `password` | + +**Headers** + +| Header | Required | +|--------|----------| +| `appToken` | ✅ fresh from GetAppToken | +| `userName` | ✅ | +| `password` | ✅ | + +**Success:** `authenticationToken` in header or body. +**Cache (YARA):** until next **Asia/Tehran midnight** — memory + Mongo `fanavaranAuthTokens`. +**Error example:** `نام کاربر یا رمز عبور صحیح نیست` (wrong password or stale/wrong appToken). + +**YARA:** `FanavaranAuthService.getAuthenticationToken(clientKey)`. + +--- + +## 3. GEN.03 — Base claim create + +Doc: `CAR.THID.APIH.GEN.03` + +| Item | Value | +|------|-------| +| نام عملیات | ایجاد پرونده خسارت مالی ثالث | +| Endpoint | `POST /Api/BimeApi/v2.0/car/third-party-car-financial-claims` | +| Method | `POST` | +| Auth | Business headers | + +Also available: `GET .../{claimid}`, `GET ...?{ODATA}`. + +### Key request fields + +| Field | Parsian template | Notes | +|-------|------------------|-------| +| `PolicyId` | from inquiry | **Required** for submit | +| `ClaimExpertId` | `154` | GEN.03 role = مسئول پرونده مالی (≠ GEN.08) | +| `AccidentCityId` | `701` | Shared default | +| `AccidentReportTypeId` | `155` | Shared | +| `AccidentVehicleUsedId` | `1` | Shared | +| `CompensationReferenceId` | `167` | Shared | +| `CulpritLicenceTypeId` | `2` | Shared | +| `CulpritTypeId` | `337` | Shared | +| `AccidentCauseId` | `6` | Shared code default | +| `AccidentDate` / `AnnouncementDate` / `DocReceivedDate` | Jalali from blame/claim time | | +| `AccidentTime` | `HH:mm` | | +| `AccidentLocationAddress` | `استان تهران شهر تهران` | Provisional constant | +| `EstimateAmount` | ≥ 1; provisional `1000` | Must be positive | +| `CulpritLicenceNo` | real or dummy | Never empty | +| `CulpritLicenceIssuDate` | party / default | | +| Many others | `null` | **Keep explicit nulls** — do not omit | + +Full shape: see skill reference sample and `buildFanavaranSubmitPayload` / `applyFanavaranDefaultFields`. + +### Validation (YARA) + +- Only `THIRD_PARTY` claims (not `CAR_BODY`) +- `PolicyId` required on submit (`requirePolicyId: true`) +- Skip if local `claimId` / `claimNo` already set +- `EstimateAmount` normalized to positive + +### Success response + +| Field | Local store | +|-------|-------------| +| `Id` | `claimCases.claimId` | +| `ClaimNo` | `claimCases.claimNo` | + +History: `FANAVARAN_EARLY_AUTO_SUBMIT_SUCCEEDED`. +SMS owner via `SmsOrchestrationService` (deduped `fanavaranSync.baseClaim.smsNotifiedAt`). + +### Error handling + +- Never throw out of normal user claim flow on auto-submit +- Persist `fanavaranSync.baseClaim.status=failed`, `lastError`, schedule retry +- Manual: `POST /v2/fanavaran/{client}/claim-cases/{id}/base-claim/submit` + +### Sample (Parsian-shaped) + +```json +{ + "AccidentCityId": 701, + "AccidentReportTypeId": 155, + "AccidentVehicleUsedId": 1, + "ClaimExpertId": 154, + "CompensationReferenceId": 167, + "CulpritLicenceTypeId": 2, + "CulpritTypeId": 337, + "AccidentCauseId": 6, + "AccidentDate": "1405/04/05", + "AnnouncementDate": "1405/04/05", + "DocReceivedDate": "1405/04/05", + "AccidentTime": "08:03", + "AccidentLocationAddress": "استان تهران شهر تهران", + "EstimateAmount": 1000, + "PolicyId": 13764408, + "CulpritLicenceNo": "1124242", + "CulpritLicenceIssuDate": "1394/10/13", + "DamagedCount": 1, + "IsLicenseMatchWithVehicleKind": 1, + "HasOtherCulprit": 0, + "IsAccidentOutOfBorder": 0, + "IsFatalAccident": 0, + "IsPlaqueChanged": 0, + "PoliceOfficerId": 1, + "IsLicenseReplacement": 0, + "PreviousPolicyEndDate": "", + "ActualPremium": null, + "ArchiveNo": null +} +``` + +Proven Parsian: `claimId=4909952`, `claimNo=1632`, `policyId=13764408`. + +--- + +## 4. GEN.12 — Damage case + +Doc: `CAR.THID.APIH.GEN.12` + +| Item | Value | +|------|-------| +| نام عملیات | ثبت مورد خسارت (خودرو/شخص زیان‌دیده) | +| Endpoint | `POST .../third-party-car-financial-claims/{claimId}/dmg-cases` | +| Method | `POST` | + +Requires existing `claimId` (soft-ensures GEN.03 if missing). + +### Key request fields + +| Field | Source | +|-------|--------| +| `Desc` | Joined selected outer part labels (`سپر عقب/...`) | +| `DriverId` | Fanavaran person inquiry (cached) | +| `VehicleKindId` | Lookup match on `claimCase.vehicle.carType` | +| `InsuranceCorpId` | Resolve from `INSURANCE_CORP_ID` caption | +| `ChassisNo` / `MotorNo` / `VIN` / plate fields | Party vehicle inquiry | +| `PolicyNo` / `PolicyCINumber` / dates | Inquiry aliases | +| `LicenceNo` | Driver/insurer licence; never empty | +| `EstimateAmount` | Provisional `1000` early | +| `DmgCaseTypeId` / `DmgHistoryStatus` / plate kinds | Tenant defaults | + +### Success + +| Field | Local store | +|-------|-------------| +| `Id` | `claimCases.dmgCaseId` | + +History: `FANAVARAN_DAMAGE_CASE_AUTO_SUBMIT_SUCCEEDED`. +Proven Parsian: `dmgCaseId=427594`, `DriverId=2426953`. + +### Trigger + +After local `SELECT_OUTER_PARTS` — before image upload. + +Manual: `POST /v2/fanavaran/{client}/claim-cases/{id}/damage-case/submit`. + +--- + +## 5. GEN.07 — Attachments + +Doc: `CAR.THID.APIH.GEN.07` + +| Item | Value | +|------|-------| +| نام عملیات | آپلود فایل پیوست پرونده | +| Endpoint | `POST .../third-party-car-financial-claims/{claimId}/files` | +| Method | `POST` | +| Content-Type | `multipart/form-data` (boundary by FormData) | + +### Multipart shape + +| Part name | Content | +|-----------|---------| +| `content` | JSON string (`application/json`) with `FileName`, `FileTypeId`, optional `Files[]` | +| `files` | Real file bytes (one request per local image) | + +**Do not** base64-encode. Filenames in JSON must match multipart filenames. + +### FileTypeId (critical — tenant-specific) + +| Tenant | `ClaimFileTypeId` | Note | +|--------|-------------------|------| +| **parsian** | **63** | `ساير مدارک خسارت` — proven. **Do not use 70** | +| tejaratno | `23` | Default | +| moallem | shared `23` until confirmed | Verify in `file-types` lookup | + +Fanavaran error if id missing from tenant lookup: +`مقدار فیلد نوع فايل با منبع لوکاپ مطابقت ندارد`. + +### Success + +File ids recorded under `fanavaranSync.attachments.files[]`. +Best-effort: failures audited + retried; local user flow continues. +No videos unless Fanavaran confirms support. + +Manual: `POST /v2/fanavaran/{client}/claim-cases/{id}/attachments/submit`. + +--- + +## 6. GEN.08 — Expertise + +Doc: `CAR.THID.APIH.GEN.08` + +| Item | Value | +|------|-------| +| نام عملیات | ثبت کارشناسی خسارت مالی ثالث | +| Endpoint | `POST .../third-party-car-financial-claims/{claimId}/expertise` | +| Method | `POST` | + +Requires `claimId` + `dmgCaseId` (soft-ensures earlier stages). + +### Key request fields + +| Field | Mapping | +|-------|---------| +| `ClaimExpertId` | Tenant **`ExpertiseClaimExpertId`** (Parsian `29`) — assessor role | +| `DmgCaseId` | Local `dmgCaseId` | +| `RepairWage` | Sum of part `salary` | +| `ComponentReplacementCost` | Sum of part `price` | +| `WasteValue` | Sum of `daghi.price` | +| `DmgAssessmentDate` / `InspectionTime` | From expert reply submit time | +| `InspectionPlaceId` | Currently `282` (code constant; verify per tenant lookup) | +| `DropAmountStatus` | Currently `5458` | +| `DropAmountAdditionsDeductions` | `evaluation.priceDrop.total` | +| `DamagedVehicleCurrentPrice` | `evaluation.priceDrop.carPrice` | +| `DmgSections[]` | One row per priced part | + +`DmgSections[]` row: + +| Field | Source | +|-------|--------| +| `DmgSectionId` | Fanavaran car-components / part id | +| `AccidentLevel` | Part damage type / default `5456` | +| `Desc` | Damage type / label | +| `RepairWage` / `ComponentReplacementCost` / `WasteValue` | Line amounts | + +### Validation + +- Active expert reply with submit-ready parts +- Factor-needed lines wait until `totalPayment > 0` +- Missing `DmgCaseId` / section ids → `BadRequestException` with `warnings[]` + +### Success + +| Field | Local store | +|-------|-------------| +| `Id` | `claimCases.expertiseId` | + +History: `FANAVARAN_EXPERTISE_AUTO_SUBMIT_SUCCEEDED`. +Proven Parsian: `expertiseId=403144`, `ClaimExpertId=29`. + +Manual: `POST /v2/fanavaran/{client}/claim-cases/{id}/expertise/submit`. + +--- + +## Follow-up APIs (documented upstream, not all wired) + +| Doc | Purpose | +|-----|---------| +| GEN.09 | Damaged points | +| GEN.10 | `dmg-department-referral` | +| GEN.11 | Cancel expertise | +| GEN.13 | Drop amounts GET | +| GEN.14 | Culprit damaged points | + +Current YARA production path focuses on GEN.03 → 12 → 07 → 08. + +--- + +## YARA manual HTTP surface + +Controller: `FanavaranController` (`src/fanavaran/fanavaran.controller.ts`) +Prefix: `/v2/fanavaran` — Bearer + `LocalActorAuthGuard`. + +| Method | Path | +|--------|------| +| GET | `/clients` | +| GET/POST | `/:client/claim-cases/:id/base-claim/preview\|submit` | +| GET/POST | `/:client/claim-cases/:id/damage-case/preview\|submit` | +| GET/POST | `/:client/claim-cases/:id/attachments/preview\|submit` | +| GET/POST | `/:client/claim-cases/:id/expertise/preview\|submit` | + +`:client` ∈ `parsian` \| `tejaratno` \| `moallem`. diff --git a/docs/fanavaran/02-read-apis-lookups.md b/docs/fanavaran/02-read-apis-lookups.md new file mode 100644 index 0000000..20abc23 --- /dev/null +++ b/docs/fanavaran/02-read-apis-lookups.md @@ -0,0 +1,139 @@ +--- +last_updated: 2026-08-08 +tags: [fanavaran, api, read, lookups] +source: fanavaran-module-docs +--- + +# 02 — Read APIs & Lookups + +All read calls use the same business headers as write APIs (`authenticationToken`, `CorpId`, `ContractId`, `Location`). + +Lookup responses are **tenant-specific**. Cache directory: + +```text +files/fanavaran-lookups/{clientKey}/ +``` + +Config: `src/fanavaran/fanavaran-lookup.config.ts` +Service: `FanavaranLookupService` +Local HTTP: `LookupsController` / `LookupsService` + +--- + +## 1. Policy inquiry (guilty party) + +| Item | Value | +|------|-------| +| Endpoint | `GET /Api/BimeApi/v2.0/common/Policies/inquiry-my-policies` | +| Query | `InsuranceLineId=5` (third-party), `NationalCode={insurerNationalCode}` | +| Usage | Resolve `PolicyId` for GEN.03 | +| Selection | `selectLatestActiveFanavaranPolicy` — latest non-expired by `EndDate` | +| Cache | `fanavaranSync.baseClaim.policyId` (resolve-once) | +| Force refresh | Manual preview `forceRefreshPolicy=true` only | + +**Errors (YARA messages):** + +- No policies → contact admin +- Latest expired → cannot send +- Invalid PolicyId/EndDate → contact admin + +**Do not** treat UI `resolvePolicy=true` as cache-bust (deprecated; ignored for re-inquiry). + +--- + +## 2. Driver / person inquiry + +Used when building GEN.12 to resolve `DriverId`. + +| Item | Value | +|------|-------| +| Endpoint | `GET /Api/BimeApi/v2.0/common/parties/inquiry-by-unique-identifier` | +| Usage | `resolveDriverFanavaranId(clientKey, nationalCode, birthday, driverIsInsurer)` via `FanavaranLookupService` | +| Cache | `fanavaranSync.damageCase.driverId` and `blameCase.parties[].person.fanavaranDriverId` | + +Prefer cache before live call. + +--- + +## 3. Remote lookup catalogue + +Base: `https://apimanager.iraneit.com/BimeApiManager/api/BimeApi/v2.0` + +| Name | Fanavaran path | Local YARA route | Used for | +|------|----------------|------------------|----------| +| accident-causes | `/car/base-info/accident-causes` | `GET /lookups/accident-causes` | Accident cause options | +| accident-report-type | `/car/code-list/accident-report-type` | `GET /lookups/accident-report-type` | Defaults / UI | +| vehicle-use-types | `/car/base-info/vehicle-use-types` | `GET /lookups/vehicle-use-types` | Vehicle use | +| dmg-pay-method | `/car/code-list/dmg-pay-method` | `GET /lookups/dmg-pay-method` | Pay method | +| driving-licence-types | `/car/base-info/driving-licence-types` | `GET /lookups/driving-licence-types` | Licence type | +| accident-culprit-type | `/car/code-list/accident-culprit-type` | `GET /lookups/accident-culprit-type` | Culprit type | +| inspection-place | `/car/code-list/inspection-place` | `GET /lookups/inspection-place` | GEN.08 | +| drop-amount-status | `/car/code-list/drop-amount-status` | `GET /lookups/drop-amount-status` | GEN.08 | +| car-components | `/car/base-info/car-components` | `GET /lookups/car-components` | `DmgSectionId` | +| accident-level | `/car/code-list/accident-level` | `GET /lookups/accident-level` | Section severity | +| expert-status | `/car/code-list/expert-status` | `GET /lookups/expert-status` | Expertise status | +| vehicle-kinds | `/car/base-info/vehicle-kinds` | `GET /lookups/vehicle-kinds` | GEN.12 `VehicleKindId` | +| person-role | `/common/code-list/person-role` | `GET /lookups/person-role` | Roles | +| insurance-corp | `/common/code-list/insurance-corp` | via fanavaran + resolve | GEN.12 `InsuranceCorpId` | +| file-types | `/common/base-info/file-types` | `GET /lookups/file-types` | GEN.07 `FileTypeId` | +| cities | `/common/base-info/cities` | `GET /lookups/cities` | City ids | +| provinces | `/common/base-info/Provinces` | `GET /lookups/provinces` | Provinces | +| dmg-case-type | `/car/code-list/dmg-case-type` | `GET /lookups/dmg-case-type` | GEN.12 | +| dmg-history-status | `/car/code-list/dmg-case-history-status` | `GET /lookups/dmg-history-status` | GEN.12 | +| used-place | `/car/code-list/used-place` | `GET /lookups/used-place` | Used place | +| dmg-business-line | `/car/code-list/dmg-business-line` | `GET /lookups/dmg-business-line` | Business line | + +### Generic accessor + +```http +GET /lookups/fanavaran +GET /lookups/fanavaran/{lookupName} +``` + +Lists / fetches by name for the **active** `FANAVARAN_CLIENT`. + +--- + +## 4. Other read helpers (LookupsController) + +| Route | Purpose | +|-------|---------| +| `GET /lookups/inquiry-by-vin` | VIN inquiry via Fanavaran | +| `GET /lookups/my-policies` | Policies for national code | +| `GET /lookups/third-party-policy/:policyId` | Policy by id | +| `GET /lookups/body-policy/:policyId` | Body policy by id | +| `GET /lookups/accident-reason\|way\|type\|fields` | UI accident fields (Tejarat static + Fanavaran map) | + +--- + +## 5. Insurance corp resolve + +| Item | Value | +|------|-------| +| Env | `INSURANCE_CORP_ID` = Persian **Caption** in insurance-corp list | +| Method | `FanavaranLookupService.resolveInsuranceCorpId(clientKey)` | +| Behavior | Fetch list once, match caption → numeric `Id`, cache | +| Parsian proven | `InsuranceCorpId=329` (for that deployment caption) | + +--- + +## 6. Vehicle kind resolve + +| Item | Value | +|------|-------| +| Input | Local `claimCase.vehicle.carType` (sedan/suv/…) | +| Method | Match Fanavaran `vehicle-kinds` Caption keywords | +| Cache | `fanavaranSync.damageCase.vehicleKindId` | +| Parsian proven | `VehicleKindId=6704` on sample case | + +--- + +## 7. How lookups are used in project + +1. First call for a tenant fetches from Fanavaran (authenticated). +2. Writes JSON under `files/fanavaran-lookups/{client}/`. +3. Subsequent reads prefer cache file. +4. Claim payload builders call `getFanavaranLookupRows(clientKey, name)` when mapping ids. +5. Outer car parts catalogue can align with Fanavaran car-components (`FANAVARAN_CAR_PARTS_CATALOG` / helpers). + +**Dependency:** Auth must succeed for cold cache. Transient “try again later” triggers tenant backoff (see [09-error-handling.md](./09-error-handling.md)). diff --git a/docs/fanavaran/03-constants.md b/docs/fanavaran/03-constants.md new file mode 100644 index 0000000..4ff483b --- /dev/null +++ b/docs/fanavaran/03-constants.md @@ -0,0 +1,111 @@ +--- +last_updated: 2026-08-08 +tags: [fanavaran, constants, config] +source: fanavaran-module-docs +--- + +# 03 — Constants + +Legend for **Varies by company?** +✅ = different per insurer tenant · ❌ = shared across tenants in current code + +Secrets are **not** printed here — read from Mongo `fanavaranClientConfigs` or seed profiles. + +--- + +## Auth (tenant) + +| Name | Example (Parsian) | Where used | Why | Varies? | +|------|-------------------|------------|-----|---------| +| `appName` | `ParsianService` | GetAppToken | App identity | ✅ | +| `secret` | *(config)* | GetAppToken | App secret | ✅ | +| `username` | `ParsianServiceUser` | Login | User | ✅ | +| `password` | *(config)* | Login | Password | ✅ | +| `corpId` | `543` | All business calls | Corp scope | ✅ | +| `contractId` | `28` | All business calls | Contract | ✅ | +| `location` | `210050` | All business calls / OpBUId | Branch/location | ✅ | + +Seed: `SEED_FANAVARAN_CLIENT_PROFILES` · Runtime: `getFanavaranClientProfile(key)`. + +--- + +## Payload defaults (tenant profile.defaults) + +| Name | Shared seed | Parsian override | Tejaratno | Moallem | Varies? | +|------|-------------|------------------|-----------|---------|---------| +| `AccidentCityId` | 701 | same | same | same | usually ❌ | +| `AccidentReportTypeId` | 155 | same | same | same | usually ❌ | +| `AccidentVehicleUsedId` | 1 | same | same | same | usually ❌ | +| `ClaimExpertId` (GEN.03) | 4543092 | **154** | 4543092 | shared TBD | ✅ | +| `ExpertiseClaimExpertId` (GEN.08) | 2709 | **29** | **2709** | shared TBD | ✅ | +| `CompensationReferenceId` | 167 | same | same | same | usually ❌ | +| `CulpritLicenceTypeId` | 2 | same | same | same | usually ❌ | +| `CulpritTypeId` | 337 | same | same | same | usually ❌ | +| `DmgCaseTypeId` | 175 | same | same | same | may ✅ | +| `DmgHistoryStatus` | 5214 | same | same | same | may ✅ | +| `PlaqueKindId` | 8 | same | same | same | may ✅ | +| `PlaqueSampleId` | 10 | same | same | same | may ✅ | +| `DriverIsOwner` | 0 | same | same | same | ❌ | +| `FaultPercent` | 100 | same | same | same | ❌ | +| `ClaimFileTypeId` (GEN.07) | 23 | **63** | 23 | 23 TBD | ✅ | + +**Never swap** GEN.03 `ClaimExpertId` with GEN.08 `ExpertiseClaimExpertId` — different Fanavaran roles. + +--- + +## Code-level shared constants + +File: `claim-request-management.service.ts` + +| Name | Value | Where | Why | Varies? | +|------|-------|-------|-----|---------| +| `FANAVARAN_SUBMIT_URL` | `.../third-party-car-financial-claims` | All stage posts | API root | ❌ (same host) | +| `FANAVARAN_ACCIDENT_LOCATION_ADDRESS` | `استان تهران شهر تهران` | GEN.03 | Provisional address | currently ❌ | +| `FANAVARAN_DEFAULT_ACCIDENT_CAUSE_ID` | `6` | GEN.03 | Default cause | may ✅ later | +| `FANAVARAN_DEFAULT_ACCIDENT_LEVEL` | `5456` | GEN.08 sections | Default severity | may ✅ | +| `FANAVARAN_PROVISIONAL_ESTIMATE_AMOUNT` | `1000` | GEN.03/12 early | Positive estimate | ❌ | +| `FANAVARAN_DUMMY_LICENCE_NO` | env or `9705463515` | Licence fields | Never empty | env override | +| `InspectionPlaceId` (expertise) | `282` | GEN.08 | Hardcoded today | should verify ✅ | +| `DropAmountStatus` (expertise) | `5458` | GEN.08 | Hardcoded today | should verify ✅ | +| Auth URLs | apimanager.iraneit.com | Auth service | Host | ❌ | +| Lookup base | same host `/BimeApi/v2.0` | Lookups | Host | ❌ | + +--- + +## Env / activation + +| Name | Example | Where | Why | Varies? | +|------|---------|-------|-----|---------| +| `FANAVARAN_CLIENT` | `parsian` | `resolveFanavaranClientKey` | Active tenant | ✅ per deploy | +| `CLIENT_ID` | `8` → parsian | Fallback hint | Legacy deploy map | ✅ | +| `INSURANCE_CORP_ID` | Persian caption | Damage `InsuranceCorpId` | Match lookup Caption | ✅ | +| `FANAVARAN_DUMMY_LICENCE_NO` | digits | Licence fallback | Test/prod dummy | optional | + +--- + +## Enums / claim types (YARA) + +| Name | Relevant values | Fanavaran use | +|------|-----------------|---------------| +| Claim type | `THIRD_PARTY` only | Fanavaran path enabled | +| | `CAR_BODY` | **Not** submitted to Fanavaran | +| `ClaimCaseStatus` | local workflow | Triggers stages indirectly | +| History event types | `FANAVARAN_*_SUCCEEDED/FAILED` | Audit trail on claim | + +--- + +## Retry / backoff constants + +| Name | Value | Where | +|------|-------|-------| +| `FANAVARAN_RETRY_DELAY_MS` | 5 min | Stage retry | +| `FANAVARAN_TRANSIENT_RETRY_DELAY_MS` | 10 min | “Try again later” stage retry | +| `FANAVARAN_MAX_RETRIES` | 2 | Per stage | +| `TRANSIENT_BACKOFF_MS` | 5 min | Tenant-wide auth backoff | +| Token TTL | Until Tehran midnight | Auth cache | + +--- + +## Plate letter codes + +`FANAVARAN_PLATE_LETTER_CODE` maps Persian plate letters → Fanavaran middle codes (shared mapping table in claim service). diff --git a/docs/fanavaran/04-tenant-matrix.md b/docs/fanavaran/04-tenant-matrix.md new file mode 100644 index 0000000..b8db556 --- /dev/null +++ b/docs/fanavaran/04-tenant-matrix.md @@ -0,0 +1,63 @@ +--- +last_updated: 2026-08-08 +tags: [fanavaran, tenant, matrix] +source: fanavaran-module-docs +--- + +# 04 — Tenant-specific vs shared + +## Comparison table + +| مورد | مشترک | وابسته به شرکت | +|------|:-----:|:--------------:| +| API host (`apimanager.iraneit.com`) | ✅ | ❌ | +| Endpoint paths (GEN.03/07/08/12, auth) | ✅ | ❌ | +| HTTP methods & payload **shape** | ✅ | ❌ | +| Auth flow (GetAppToken → Login) | ✅ | ❌ | +| Auth credentials (app/user/secret) | ❌ | ✅ | +| `CorpId` / `ContractId` / `Location` | ❌ | ✅ | +| `ClaimExpertId` (GEN.03) | ❌ | ✅ | +| `ExpertiseClaimExpertId` (GEN.08) | ❌ | ✅ | +| `ClaimFileTypeId` (GEN.07) | ❌ | ✅ | +| Lookup **Id values** (file-types, experts, …) | ❌ | ✅ | +| Lookup **endpoint URLs** | ✅ | ❌ | +| Policy inquiry algorithm | ✅ | ❌ | +| YARA orchestration / soft-ensure / retry | ✅ | ❌ | +| YARA internal routes `/v2/fanavaran/...` | ✅ | path `:client` only | +| `INSURANCE_CORP_ID` caption / resolved id | ❌ | ✅ | +| `FANAVARAN_CLIENT` env | ❌ | ✅ per deploy | +| Mapping YARA→Fanavaran field names | ✅ | ❌ | +| Validation: PolicyId required, EstimateAmount > 0 | ✅ | ❌ | +| Validation: FileTypeId ∈ tenant lookup | logic ✅ | allowed ids ✅ | +| Business: THIRD_PARTY only | ✅ | ❌ | +| Provisional address / dummy licence | ✅ today | may customize later | +| SMS template after base claim | shared orchestration | provider/templates may ✅ | +| Mongo collections / audit schema | ✅ | ❌ | +| Offline inquiry seeds | may exist per client | ✅ | + +## Current tenants + +| Key | Status | Notes | +|-----|--------|-------| +| `parsian` | **Template / proven E2E** | Use as reference for new clients | +| `tejaratno` | Working shape | Different experts + FileTypeId 23 | +| `moallem` | Auth seeded | Confirm expert + file-type ids via lookups before go-live | + +## What is reusable when adding a client + +1. Entire staged pipeline in `ClaimRequestManagementService` +2. `FanavaranAuthService`, audit, lookup cache machinery +3. Controllers + preview/submit surface +4. Policy selection helper +5. Soft-ensure + retry + history events + +## What must be configured per client + +1. Auth block + Corp/Contract/Location +2. GEN.03 / GEN.08 expert ids (from that tenant’s expert lists) +3. `ClaimFileTypeId` present in that tenant’s `file-types.json` +4. `INSURANCE_CORP_ID` caption for deploy +5. Warm lookups under `files/fanavaran-lookups/{key}/` +6. Optional: override city/cause/inspection ids if shared defaults fail validation + +See [11-onboard-new-client.md](./11-onboard-new-client.md). diff --git a/docs/fanavaran/05-claim-flow.md b/docs/fanavaran/05-claim-flow.md new file mode 100644 index 0000000..67a3ed8 --- /dev/null +++ b/docs/fanavaran/05-claim-flow.md @@ -0,0 +1,130 @@ +--- +last_updated: 2026-08-08 +tags: [fanavaran, flow, sequence] +source: fanavaran-module-docs +--- + +# 05 — Full claim registration flow + +Applies to **THIRD_PARTY** claims only. Template behavior = **Parsian**. + +## High-level stages + +```text +Start local claim + → Validate THIRD_PARTY + data readiness + → Auth (cached token) + → Policy inquiry (resolve-once PolicyId) + → GEN.03 base claim → store claimId / claimNo → SMS owner + → SELECT_OUTER_PARTS + → GEN.12 damage case → store dmgCaseId + → Upload docs/images locally + → GEN.07 attachments (per file, best-effort) + → Expert pricing ready + → GEN.08 expertise → store expertiseId + → End (local completion independent of Fanavaran success) +``` + +## Sequence diagram + +```mermaid +sequenceDiagram + autonumber + participant User as User / Expert + participant YARA as YARA ClaimRequestManagement + participant Auth as FanavaranAuthService + participant FV as Fanavaran API + participant DB as Mongo claimCases + + User->>YARA: Create THIRD_PARTY claim + YARA->>DB: Persist claimCase + YARA->>YARA: autoSubmitToFanavaranV2OnClaimCreated + + YARA->>Auth: getAuthenticationToken(client) + alt cache miss / past Tehran midnight + Auth->>FV: POST GetAppToken + Auth->>FV: POST Login + Auth->>DB: fanavaranAuthTokens + end + Auth-->>YARA: authenticationToken + + alt no cached policyId + YARA->>FV: GET inquiry-my-policies + YARA->>DB: fanavaranSync.baseClaim.policyId + end + + YARA->>FV: POST third-party-car-financial-claims (GEN.03) + FV-->>YARA: Id, ClaimNo + YARA->>DB: claimId, claimNo, history SUCCESS + YARA->>YARA: SMS owner (deduped) + + User->>YARA: SELECT_OUTER_PARTS + YARA->>YARA: autoSubmitFanavaranDamageCase... + Note over YARA: soft-ensure base if missing + YARA->>FV: POST .../dmg-cases (GEN.12) + FV-->>YARA: DmgCaseId + YARA->>DB: dmgCaseId + + User->>YARA: Upload images/docs + loop each image not yet uploaded + YARA->>FV: POST .../files multipart (GEN.07) + YARA->>DB: attachments.files[] + end + + User->>YARA: Expert reply priced + YARA->>YARA: autoSubmitFanavaranExpertise... + Note over YARA: soft-ensure damage/base + YARA->>FV: POST .../expertise (GEN.08) + FV-->>YARA: ExpertiseId + YARA->>DB: expertiseId, history SUCCESS +``` + +## Flow diagram (stages + soft-ensure) + +```mermaid +flowchart TD + A[Local claim created THIRD_PARTY] --> B{claimId exists?} + B -->|No| C[GEN.03 Base claim] + B -->|Yes| D[Skip base] + C --> E[Store claimId/claimNo] + E --> F[Outer parts selected] + D --> F + F --> G{dmgCaseId exists?} + G -->|No| H[Ensure base then GEN.12] + G -->|Yes| I[Skip damage] + H --> J[Store dmgCaseId] + J --> K[Local media upload] + I --> K + K --> L[GEN.07 per file] + L --> M[Expert pricing ready] + M --> N{expertiseId exists?} + N -->|No| O[Ensure damage then GEN.08] + N -->|Yes| P[Done] + O --> P +``` + +## Local triggers + +| Stage | Auto trigger | Function | +|-------|--------------|----------| +| Base | Claim create (early) | `autoSubmitToFanavaranV2OnClaimCreated` | +| Base | Claim completed (legacy/fallback; skips if already submitted) | `autoSubmitToFanavaranV2OnClaimCompleted` | +| Damage | After outer parts selection | `autoSubmitFanavaranDamageCaseOnOuterPartsSelected` | +| Attachments | After successful local image/doc upload | `autoSubmitFanavaranAttachment` | +| Expertise | After expert reply when priced | `autoSubmitFanavaranExpertiseOnExpertReply` | + +V5 note: when `requiresFileMakerApproval=true`, Fanavaran submit may wait for FileMaker approval per claim flow rules. + +## Manual retry + +Use `/v2/fanavaran/{client}/claim-cases/{claimCaseId}/.../submit` for any failed stage. Preview endpoints build payload without requiring submit success. + +## Status persistence + +Per stage under `claimCases.fanavaranSync.{baseClaim|damageCase|attachments|expertise}`: + +- `status`: success / failed / pending / skipped +- `lastError`, `lastTriedAt`, `retryCount`, `nextRetryAt` +- Cached ids + `lastPayload` + +Top-level: `claimId`, `claimNo`, `dmgCaseId`, `expertiseId`. diff --git a/docs/fanavaran/06-yara-integration.md b/docs/fanavaran/06-yara-integration.md new file mode 100644 index 0000000..dc97f6f --- /dev/null +++ b/docs/fanavaran/06-yara-integration.md @@ -0,0 +1,140 @@ +--- +last_updated: 2026-08-08 +tags: [fanavaran, yara, integration] +source: fanavaran-module-docs +--- + +# 06 — YARA ↔ Fanavaran integration points + +## Module map + +| Concern | Module | Primary files | +|---------|--------|---------------| +| HTTP surface | `FanavaranModule` | `fanavaran.controller.ts` | +| Auth | `FanavaranModule` | `fanavaran-auth.service.ts` | +| Lookups | `FanavaranLookupModule` / `LookupsModule` | `fanavaran-lookup.service.ts`, `lookups.*` | +| Audit | `FanavaranAuditModule` | `fanavaran-audit.service.ts` | +| Tenant config | boot + System Settings | `fanavaran-client-config.service.ts`, `system-settings.*` | +| Orchestration | `ClaimRequestManagementModule` | `claim-request-management.service.ts` | +| Policy select | same | `fanavaran-policy-selection.ts` | +| SMS after base | `SmsOrchestrationModule` | `sms-orchestration.service.ts` | + +--- + +## Interaction catalogue + +### A. Authentication + +| | | +|--|--| +| Module | `src/fanavaran` | +| Service | `FanavaranAuthService` | +| Controller | *(none external — used by claim/lookup)* | +| Functions | `getAuthenticationToken`, GetAppToken + Login internals | +| When | Before any Fanavaran business/lookup HTTP | +| Send | appname/secret → appToken → username/password | +| Receive | `authenticationToken` | +| Store | Memory cache + `fanavaranAuthTokens` | +| Consumers | Claim submit, lookups, policy inquiry | + +### B. Base claim preview/submit + +| | | +|--|--| +| Module | Fanavaran + ClaimRequestManagement | +| Controller | `FanavaranController.preview` / `submit` | +| Service | `ClaimRequestManagementService` | +| Functions | `previewFanavaranSubmitV2`, `submitFanavaranV2`, `executeFanavaranV2Submit`, `buildFanavaranSubmitPayload`, `getPolicyIdFromNationalCode` | +| When | Auto on claim create; manual preview/submit | +| Send | GEN.03 JSON + business headers | +| Receive | `Id`, `ClaimNo` | +| Store | `claimId`, `claimNo`, `fanavaranSync.baseClaim.*`, history | +| Consumers | Damage/expertise soft-ensure; UI claim detail; SMS | + +### C. Damage case + +| | | +|--|--| +| Controller | `previewDamageCase` / `submitDamageCase` | +| Functions | `previewFanavaranDamageCaseV2`, `submitFanavaranDamageCaseV2`, `buildFanavaranDamageCasePayload`, `autoSubmitFanavaranDamageCaseOnOuterPartsSelected`, `ensureFanavaranBaseClaim` | +| When | After outer parts selected; soft-ensure from later stages | +| Send | GEN.12 JSON | +| Receive | `Id` → `dmgCaseId` | +| Store | `dmgCaseId`, `fanavaranSync.damageCase.{driverId,vehicleKindId,insuranceCorpId,lastPayload}` | +| Consumers | Expertise payload (`DmgCaseId`) | + +### D. Attachments + +| | | +|--|--| +| Controller | `previewAttachments` / `submitAttachments` | +| Functions | `previewFanavaranAttachmentsV2`, `submitFanavaranAttachmentsV2`, `autoSubmitFanavaranAttachment` | +| When | After local required-doc / capture upload | +| Send | multipart GEN.07 | +| Receive | file metadata / ids | +| Store | `fanavaranSync.attachments.files[]` | +| Consumers | Manual retry of missing uploads | + +### E. Expertise + +| | | +|--|--| +| Controller | `previewExpertise` / `submitExpertise` | +| Functions | `previewFanavaranExpertiseV2`, `submitFanavaranExpertiseV2`, `buildFanavaranExpertisePayload`, `autoSubmitFanavaranExpertiseOnExpertReply`, `ensureFanavaranDamageCase` | +| When | Expert reply priced / factor validated | +| Send | GEN.08 JSON | +| Receive | `Id` → `expertiseId` | +| Store | `expertiseId`, `fanavaranSync.expertise.*` | +| Consumers | Claim completion reporting / history | + +### F. Lookups (read) + +| | | +|--|--| +| Controller | `LookupsController` | +| Service | `LookupsService` → `FanavaranLookupService` | +| When | UI dropdowns; cold cache; payload id resolution | +| Store | `files/fanavaran-lookups/{client}/*.json` | + +### G. Tenant config admin + +| | | +|--|--| +| Module | System Settings | +| Service | `SystemSettingsService` / `FanavaranClientConfigService` | +| When | Boot seed missing keys; admin update | +| Store | `fanavaranClientConfigs` → in-memory cache via `setFanavaranClientProfilesCache` | + +### H. Claim create call sites (auto base) + +`autoSubmitToFanavaranV2OnClaimCreated` is invoked from claim creation paths inside `ClaimRequestManagementService` (registrar / expert-initiated / v2 create flows — search call sites ~7717, 7839, 8141, 8243). + +Outer parts selection invokes damage auto-submit (~8422). +Document/capture upload hooks call attachment auto-submit (~9496+). +Expert reply path calls expertise auto-submit (~10576). + +--- + +## Controllers summary + +| Controller | Fanavaran-related routes | +|------------|--------------------------| +| `FanavaranController` | All `/v2/fanavaran/*` preview/submit | +| `LookupsController` | `/lookups/*` Fanavaran-backed reads | +| Claim V2 / registrar / expert mirrors | Create/select/upload that **trigger** auto-submit (no direct Fanavaran URL) | + +--- + +## Data written by Fanavaran stages + +| Field path | Stage | +|------------|-------| +| `claimCases.claimId` / `claimNo` | GEN.03 | +| `claimCases.dmgCaseId` | GEN.12 | +| `claimCases.expertiseId` | GEN.08 | +| `claimCases.fanavaranSync.*` | All | +| `claimCases.history[]` | Success/fail events | +| `blameCases.parties[].person.fanavaranDriverId` | GEN.12 driver resolve | +| `fanavaranAuditLogs` | Every real HTTP step | +| `fanavaranAuthTokens` | Auth cache | +| `fanavaranClientConfigs` | Tenant profiles | diff --git a/docs/fanavaran/07-data-mapping.md b/docs/fanavaran/07-data-mapping.md new file mode 100644 index 0000000..d17998c --- /dev/null +++ b/docs/fanavaran/07-data-mapping.md @@ -0,0 +1,92 @@ +--- +last_updated: 2026-08-08 +tags: [fanavaran, mapping] +source: fanavaran-module-docs +--- + +# 07 — Data mapping (YARA → Fanavaran) + +## GEN.03 — Base claim + +| YARA | Fanavaran | +|------|-----------| +| Guilty party insurer national code → policy inquiry | `PolicyId` | +| Tenant `defaults.ClaimExpertId` | `ClaimExpertId` | +| Tenant defaults city/report/vehicle-used/… | `AccidentCityId`, `AccidentReportTypeId`, … | +| Blame/claim `createdAt` (Jalali) | `AccidentDate`, `AnnouncementDate`, `DocReceivedDate` | +| Blame/claim time | `AccidentTime` | +| Constant address | `AccidentLocationAddress` | +| Sum damage parts estimate (or 1000) | `EstimateAmount` | +| Accident reason fanavaran id (else default 6) | `AccidentCauseId` | +| Culprit licence digits / dummy | `CulpritLicenceNo` | +| Culprit licence issue / birthday fallback | `CulpritLicenceIssuDate` | +| Tenant `CulpritLicenceTypeId` / `CulpritTypeId` | same | +| — | Explicit `null` placeholders for unused template fields | + +## GEN.12 — Damage case + +| YARA | Fanavaran | +|------|-----------| +| `damage.selectedParts` labels | `Desc` (`/` joined) | +| Party `nationalCodeOfDriver` + birthday (+ insurer flag) → inquiry | `DriverId` | +| `claimCase.vehicle.carType` → vehicle-kinds | `VehicleKindId` | +| `INSURANCE_CORP_ID` caption → insurance-corp | `InsuranceCorpId` | +| Inquiry `ShsNum` / Chassis* | `ChassisNo` | +| Inquiry `MtrNum` / Engine* | `MotorNo` | +| Inquiry `VIN` / vin | `VIN` | +| Inquiry / plate snapshot | `PlaqueLeftNo`, `PlaqueRightNo`, `PlaqueSerial`, `PlaqueMiddleCodeId`, `PlaqueNo` | +| Inquiry policy numbers / dates | `PolicyNo`, `PolicyCINumber`, `BeginDate`, `EndDate`, `PreviousPolicyEndDate` | +| Inquiry model year | `BuiltYear` | +| `person.driverLicense` / `insurerLicense` / dummy | `LicenceNo` | +| `person.driverBirthday` | `LicenceIssuDate` | +| `person.driverIsInsurer` | `DriverIsOwner` (1/0) | +| Tenant defaults | `DmgCaseTypeId`, `DmgHistoryStatus`, `PlaqueKindId`, `PlaqueSampleId`, `FaultPercent`, `AccidentVehicleUsedId`, `LicenceTypeId` | +| Provisional | `EstimateAmount` = 1000 | + +## GEN.07 — Attachments + +| YARA | Fanavaran | +|------|-----------| +| Local image filename | `FileName` (+ multipart `files`) | +| Tenant `ClaimFileTypeId` | `FileTypeId` | +| Local file bytes | multipart binary | +| `claimId` | URL path | + +## GEN.08 — Expertise + +| YARA | Fanavaran | +|------|-----------| +| Tenant `ExpertiseClaimExpertId` | `ClaimExpertId` | +| `claimCase.dmgCaseId` | `DmgCaseId` | +| Expert reply parts `salary` (sum) | `RepairWage` | +| Expert reply parts `price` (sum) | `ComponentReplacementCost` | +| Part `daghi.price` (sum) | `WasteValue` | +| Reply `submittedAt` | `DmgAssessmentDate`, `InspectionTime` | +| `evaluation.priceDrop.total` | `DropAmountAdditionsDeductions` | +| `evaluation.priceDrop.carPrice` | `DamagedVehicleCurrentPrice` | +| Part catalog / `partId` | `DmgSections[].DmgSectionId` | +| Part `typeOfDamage` / default level | `DmgSections[].AccidentLevel` | +| Part label / type | `DmgSections[].Desc` | +| Part line `salary` / `price` / daghi | section money fields | +| Code constants today | `InspectionPlaceId`, `DropAmountStatus` | + +## Auth headers + +| YARA profile.auth | Fanavaran header | +|-------------------|------------------| +| `corpId` | `CorpId` | +| `contractId` | `ContractId` | +| `location` | `Location` | +| token from Login | `authenticationToken` | + +## Not mapped / out of scope + +| YARA | Note | +|------|------| +| `CAR_BODY` claims | No Fanavaran submit | +| Videos | Not uploaded via GEN.07 in current code | +| Full police report fields | Often null unless later enriched | + +## Alias notes (inquiry) + +ESG / Tejarat inquiry payloads use multiple key names; builders try ordered aliases (e.g. `PrntCmpDocNo` / `printNumber` / `insuranceNumber` for policy number). See `pickPartyInquiryField` in claim service. diff --git a/docs/fanavaran/08-dependencies.md b/docs/fanavaran/08-dependencies.md new file mode 100644 index 0000000..c820f68 --- /dev/null +++ b/docs/fanavaran/08-dependencies.md @@ -0,0 +1,45 @@ +--- +last_updated: 2026-08-08 +tags: [fanavaran, dependencies] +source: fanavaran-module-docs +--- + +# 08 — System dependencies + +## Required + +| Dependency | Role | +|------------|------| +| **MongoDB** | `claimCases`, `blameCases` / request-management, `fanavaranAuthTokens`, `fanavaranAuditLogs`, `fanavaranClientConfigs`, claim documents refs | +| **Outbound HTTPS** | Fanavaran API Manager (`apimanager.iraneit.com`) | +| **Filesystem** | `files/fanavaran-lookups/{client}/`, uploaded claim media for GEN.07 | +| **Env / config** | `FANAVARAN_CLIENT`, `INSURANCE_CORP_ID`, optional `FANAVARAN_DUMMY_LICENCE_NO`, SMS provider env | +| **Nest HttpModule** | Axios via `HttpService` | +| **Logging** | Nest `Logger` + audit collection | + +## Optional / related + +| Dependency | Role | +|------------|------| +| **SMS provider** | Notify owner after successful GEN.03 (`SmsOrchestrationService`; same as login SMS stack) | +| **Offline inquiry seeds** | Can supply driver/policy test data without live inquiry | +| **Redis / Queue** | **Not** used for Fanavaran stage orchestration today — retries are in-process `setTimeout` + Mongo `nextRetryAt` | + +## Config sources (priority) + +1. Mongo `fanavaranClientConfigs` (loaded to memory on boot) +2. Seed `SEED_FANAVARAN_CLIENT_PROFILES` if key missing (never overwrite existing DB edits on seed) +3. Env selects **which** client is active (`FANAVARAN_CLIENT`) + +## Collections (Fanavaran-specific) + +| Collection | Purpose | +|------------|---------| +| `fanavaranClientConfigs` | Per-tenant auth + defaults | +| `fanavaranAuthTokens` | Shared token until Tehran midnight | +| `fanavaranAuditLogs` | Request/response audit (secrets masked, bodies truncated ~80KB) | +| `claimCases.fanavaranSync` | Stage state machine | + +## File storage + +Local claim images/documents must be readable by the process for multipart upload. Failures on missing files are recorded on the attachments stage without blocking the user journey. diff --git a/docs/fanavaran/09-error-handling.md b/docs/fanavaran/09-error-handling.md new file mode 100644 index 0000000..584f479 --- /dev/null +++ b/docs/fanavaran/09-error-handling.md @@ -0,0 +1,72 @@ +--- +last_updated: 2026-08-08 +tags: [fanavaran, errors, retry] +source: fanavaran-module-docs +--- + +# 09 — Error handling + +## Principles + +1. Fanavaran failures must **not** abort the local user claim flow on auto-submit. +2. Persist warning + history + `fanavaranSync.*.lastError`. +3. Allow manual retry via `/v2/fanavaran/.../submit`. +4. Audit only real Fanavaran HTTP (warm cache hits are silent). + +--- + +## Common errors + +| دلیل | پیام نمونه | مدیریت | Retry | Log | اطلاع‌رسانی | +|------|------------|--------|-------|-----|-------------| +| Wrong login / appToken | `نام کاربر یا رمز عبور صحیح نیست` | Fix credentials; ensure fresh GetAppToken before Login | After fix | Auth audit | Ops | +| Transient overload | `لطفا پس از چند لحظه مجدد تلاش فرمایید` | Tenant-wide backoff 5 min; do **not** immediately re-auth storm | Delayed (~5 min) | Auth + stage | Ops via audit | +| Missing PolicyId | No/expired policies messages | Block submit; preview may leave null | Manual after data fix | Stage fail history | Admin | +| Duplicate create | Local `claimId`/`claimNo` exists | Skip create; use follow-ups | N/A | skipReason | — | +| Invalid FileTypeId | `نوع فايل با منبع لوکاپ مطابقت ندارد` | Set `ClaimFileTypeId` from tenant `file-types` (Parsian **63**) | After config fix | Attachment stage | Ops | +| Expertise not ready | `Fanavaran expertise payload is not ready` + warnings | Wait for priced parts / factor | Auto when ready | — | Expert UI | +| Network / 5xx | Axios / gateway errors | Stage failed + schedule retry | Up to `maxRetries` (2) | Audit | Ops | +| Max retries exhausted | Logged warn | Manual submit only | Stop auto | Stage status | Ops | + +--- + +## Retry mechanics + +Implemented in `scheduleFanavaranRetry`: + +| Rule | Behavior | +|------|----------| +| Delay (normal) | 5 minutes | +| Delay (transient try-later) | 10 minutes + `registerFailure` tenant backoff (5 min) | +| Max | Default 2 per stage (`fanavaranSync.*.maxRetries`) | +| Dedupe | In-process timer map + existing future `nextRetryAt` | +| Lock | `withFanavaranStageLock` prevents concurrent stage runs | + +--- + +## History event types (examples) + +| Event | Meaning | +|-------|---------| +| `FANAVARAN_EARLY_AUTO_SUBMIT_SUCCEEDED` | GEN.03 ok | +| `FANAVARAN_EARLY_AUTO_SUBMIT_FAILED` | GEN.03 fail | +| `FANAVARAN_DAMAGE_CASE_AUTO_SUBMIT_SUCCEEDED` / `_FAILED` | GEN.12 | +| `FANAVARAN_EXPERTISE_AUTO_SUBMIT_SUCCEEDED` / `_FAILED` | GEN.08 | +| Attachment success/fail | Via sync status + audit (and related history where pushed) | + +--- + +## Audit log (`fanavaranAuditLogs`) + +Per HTTP step: + +- `requestUrl`, `requestMethod`, `httpStatus`, `durationMs` +- Headers/bodies (secrets masked, truncated) +- `errorMessage` / `errorDetails` on failure +- Look for `fromCache: true` meta when PolicyId/auth reused without live call + +--- + +## SMS + +After successful base claim, owner SMS may be sent once (`smsNotifiedAt`). Failure to SMS should not roll back Fanavaran claim create; treat as separate notification concern. diff --git a/docs/fanavaran/10-testing.md b/docs/fanavaran/10-testing.md new file mode 100644 index 0000000..545a223 --- /dev/null +++ b/docs/fanavaran/10-testing.md @@ -0,0 +1,90 @@ +--- +last_updated: 2026-08-08 +tags: [fanavaran, testing] +source: fanavaran-module-docs +--- + +# 10 — Testing + +## Prerequisites + +1. `FANAVARAN_CLIENT=parsian` (or target tenant) +2. Valid tenant credentials in Mongo / seed +3. `INSURANCE_CORP_ID` matching that tenant’s insurance-corp Caption +4. Network access to `apimanager.iraneit.com` +5. Optional: warm lookups via first `GET /lookups/fanavaran/{name}` or auth script + +## Auth smoke test + +```bash +scripts/fanavaran-auth.sh parsian +source files/fanavaran-auth/parsian/tokens.env +# then curl a lookup — see docs/external-api-curls.md +``` + +## Unit / service specs + +| Spec | Focus | +|------|-------| +| `src/fanavaran/fanavaran-auth.service.spec.ts` | Token cache / midnight / backoff | +| `src/claim-request-management/fanavaran-policy-selection.spec.ts` | Latest active policy selection | + +Prefer mocks for Fanavaran HTTP in unit tests; use live calls only in controlled integration. + +## Manual E2E (Parsian template) + +1. Create THIRD_PARTY claim with guilty party national code that has an **active** Fanavaran policy. +2. Confirm history `FANAVARAN_EARLY_AUTO_SUBMIT_SUCCEEDED` and `claimId`/`claimNo`. +3. Select outer parts → `dmgCaseId` set. +4. Upload images → attachment file ids under `fanavaranSync.attachments`. +5. Submit expert pricing → `expertiseId`. +6. Cross-check `fanavaranAuditLogs` for each stage. + +Preview first if debugging: + +```http +GET /v2/fanavaran/parsian/claim-cases/{id}/base-claim/preview?debug=true +GET /v2/fanavaran/parsian/claim-cases/{id}/damage-case/preview +GET /v2/fanavaran/parsian/claim-cases/{id}/attachments/preview +GET /v2/fanavaran/parsian/claim-cases/{id}/expertise/preview +``` + +## Success scenarios + +| Scenario | Expect | +|----------|--------| +| Happy path Parsian | All four stages succeed | +| Re-preview after PolicyId cached | No new policy inquiry | +| Soft-ensure | Damage submit creates base if missing | +| Skip duplicate base | Second auto-submit skipped when claimId exists | + +## Error scenarios + +| Scenario | Expect | +|----------|--------| +| Expired policy | Clear BadRequest; no create | +| Wrong FileTypeId (e.g. 70 on Parsian) | Attachment fail message about lookup | +| Transient try-later | Backoff; delayed retry; no login storm | +| Fanavaran down on auto-submit | Local claim continues; history FAILED; manual retry path in warning | + +## Proven reference case (Parsian) + +| Local | Fanavaran | +|-------|-----------| +| `CL68535` / `A00153` / `_id` `6a707a3a8f4c6fbd851cfa75` | — | +| Base | `claimId=4909952`, `claimNo=1632`, `policyId=13764408` | +| Damage | `dmgCaseId=427594`, `DriverId=2426953` | +| Attachments | FileTypeId **63**; file ids `4629737`… | +| Expertise | `expertiseId=403144`, assessor `29` | + +Defaults used: GEN.03 expert `154`, GEN.08 `29`, Location `210050`, InsuranceCorpId `329`, VehicleKindId `6704`. + +## Mocks + +- Mock `HttpService` / axios for auth + submit in unit tests. +- Offline plate/driver seeds for local payload builds without live inquiry (used in proven Parsian offline+live mix). +- Do not commit live tokens. + +## Curl catalogue + +Operational curl sequences (auth, lookups, sample submits): [`docs/external-api-curls.md`](../external-api-curls.md). diff --git a/docs/fanavaran/11-onboard-new-client.md b/docs/fanavaran/11-onboard-new-client.md new file mode 100644 index 0000000..95d1e42 --- /dev/null +++ b/docs/fanavaran/11-onboard-new-client.md @@ -0,0 +1,76 @@ +--- +last_updated: 2026-08-08 +tags: [fanavaran, onboarding, checklist] +source: fanavaran-module-docs +--- + +# 11 — Onboard a new insurance client + +Use **Parsian** as the behavioral template. API shapes stay the same; only tenant config + lookup ids change. + +## Checklist + +### 1. Register tenant key + +- [ ] Add key to `FanavaranClientKey` / `FANAVARAN_CLIENT_KEYS` in `fanavaran-client.config.ts` +- [ ] Add `SEED_FANAVARAN_CLIENT_PROFILES[key]` with auth + defaults +- [ ] Boot app once so `FanavaranClientConfigService` seeds Mongo if missing + +### 2. Auth verification + +- [ ] `scripts/fanavaran-auth.sh ` succeeds +- [ ] Login returns `authenticationToken` +- [ ] Business call with CorpId/ContractId/Location succeeds (any small lookup) + +### 3. Warm lookups + +- [ ] Fetch `file-types`, `vehicle-kinds`, `insurance-corp`, `car-components`, `inspection-place`, `accident-level`, expert-related lists +- [ ] Confirm cache under `files/fanavaran-lookups//` + +### 4. Choose tenant-specific ids + +| Field | How to pick | +|-------|-------------| +| `ClaimExpertId` (GEN.03) | Financial case owner role for that insurer | +| `ExpertiseClaimExpertId` (GEN.08) | Assessor role — **different** from GEN.03 | +| `ClaimFileTypeId` | Must exist in **that** tenant’s `file-types.json` | +| Shared codebook defaults | Start from `SHARED_FANAVARAN_DEFAULTS`; override if Fanavaran rejects | + +### 5. Deploy env + +```bash +FANAVARAN_CLIENT= +INSURANCE_CORP_ID='' +``` + +### 6. Dry-run on a test claim + +- [ ] Preview base → PolicyId resolves +- [ ] Submit base → `claimId`/`claimNo` +- [ ] Outer parts → `dmgCaseId` +- [ ] Upload → attachments with correct FileTypeId +- [ ] Expertise → `expertiseId` +- [ ] Review `fanavaranAuditLogs` and history events + +### 7. Document deltas + +- [ ] Add a short section under [04-tenant-matrix.md](./04-tenant-matrix.md) for the new key +- [ ] Note any non-Parsian business rules (validation, required fields) + +## Do / Don’t + +| Do | Don’t | +|----|-------| +| Copy orchestration from existing code | Copy Parsian expert/file-type ids blindly | +| Verify FileTypeId in tenant lookup | Use template sample `70` without checking | +| Keep null fields in payloads | Strip nulls from GEN.03/12 templates | +| Soft-fail auto-submit | Block user UX on Fanavaran outage | + +## Acceptance for “docs-only onboarding” + +A backend engineer should be able to complete the checklist above using only: + +1. This docs set (`docs/fanavaran/`) +2. `docs/external-api-curls.md` +3. Seed/config + System Settings for credentials +4. Parsian proven values as the reference baseline diff --git a/docs/fanavaran/README.md b/docs/fanavaran/README.md new file mode 100644 index 0000000..3df20b5 --- /dev/null +++ b/docs/fanavaran/README.md @@ -0,0 +1,99 @@ +--- +last_updated: 2026-08-08 +tags: [fanavaran, documentation, parsian, third-party-claim] +source: fanavaran-module-docs +--- + +# Fanavaran Integration — Technical Reference + +مرجع فنی یکپارچه‌سازی یارا با سرویس‌های فناوران برای ثبت خسارت مالی ثالث خودرو. + +**Template tenant:** `parsian` (proven end-to-end, 2026-08-03 — claim `CL68535` / publicId `A00153`) +**Also configured:** `tejaratno` (production shape), `moallem` (auth seeded; expert/file-type ids TBD) + +## Goals + +1. Document every Fanavaran API used in claim registration +2. Clarify per-insurer dependencies +3. Identify reusable pieces +4. Map YARA ↔ Fanavaran integration points +5. Enable onboarding a new insurer from this docs set alone + +## Document index + +| # | Document | Covers | +|---|----------|--------| +| 1 | [01-write-apis.md](./01-write-apis.md) | Auth + GEN.03 / GEN.12 / GEN.07 / GEN.08 write APIs | +| 2 | [02-read-apis-lookups.md](./02-read-apis-lookups.md) | Policy inquiry, driver inquiry, lookups | +| 3 | [03-constants.md](./03-constants.md) | Shared vs tenant constants | +| 4 | [04-tenant-matrix.md](./04-tenant-matrix.md) | Shared ✅ / tenant-specific ✅ matrix | +| 5 | [05-claim-flow.md](./05-claim-flow.md) | Full claim flow + sequence diagrams | +| 6 | [06-yara-integration.md](./06-yara-integration.md) | Module / service / controller / function map | +| 7 | [07-data-mapping.md](./07-data-mapping.md) | YARA field → Fanavaran field | +| 8 | [08-dependencies.md](./08-dependencies.md) | Mongo, files, env, SMS, audit | +| 9 | [09-error-handling.md](./09-error-handling.md) | Errors, retry, backoff, logging | +| 10 | [10-testing.md](./10-testing.md) | Test scenarios, scripts, proven case | +| 11 | [11-onboard-new-client.md](./11-onboard-new-client.md) | Checklist to add a new insurer | + +## Related sources (code) + +| Path | Role | +|------|------| +| `src/core/config/fanavaran-client.config.ts` | Tenant keys, seed auth + defaults | +| `src/fanavaran/` | Auth, lookup, audit, YARA HTTP surface | +| `src/claim-request-management/claim-request-management.service.ts` | Payload build + staged submit orchestration | +| `src/claim-request-management/fanavaran-policy-selection.ts` | Latest active policy selection | +| `src/lookups/` | Local lookup HTTP façade over Fanavaran | +| `.agents/skills/fanavaran-apis/references/third-party-cases.md` | Agent-oriented implementation rules | +| `docs/external-api-curls.md` | Ready-to-run curl sequences | +| `scripts/fanavaran-auth.sh` | Token helper | + +## Architecture (one glance) + +```text +YARA claim flow (THIRD_PARTY only) + │ + ├─ auto / manual stage triggers + │ + ▼ +ClaimRequestManagementService + ├─ FanavaranAuthService (GetAppToken → Login, cache until Tehran midnight) + ├─ FanavaranLookupService (lookups + insurance-corp resolve) + ├─ FanavaranAuditService (fanavaranAuditLogs) + └─ FanavaranClientConfigService (Mongo fanavaranClientConfigs) + │ + ▼ +Fanavaran API Manager + https://apimanager.iraneit.com/BimeApiManager/api +``` + +## Stages (order) + +| Stage | Fanavaran doc | Local ids stored | +|-------|---------------|------------------| +| Auth | EITAuthentication | token cache (`fanavaranAuthTokens`) | +| Policy inquiry | inquiry-my-policies | `fanavaranSync.baseClaim.policyId` | +| Base claim | GEN.03 | `claimId`, `claimNo` | +| Damage case | GEN.12 | `dmgCaseId`, `driverId`, … | +| Attachments | GEN.07 | `fanavaranSync.attachments.files[]` | +| Expertise | GEN.08 | `expertiseId` | + +Soft-ensure: later stages create earlier ones if missing (damage → base; expertise → damage → base). + +## Secrets policy + +This documentation **does not** embed live secrets. Auth values (`appName`, `secret`, `username`, `password`) live in: + +1. Mongo collection `fanavaranClientConfigs` (runtime source of truth after boot seed) +2. Seed fallback: `SEED_FANAVARAN_CLIENT_PROFILES` in `fanavaran-client.config.ts` + +Use `scripts/fanavaran-auth.sh ` or System Settings admin APIs to inspect/update tenant config. + +## Activate a tenant + +```bash +FANAVARAN_CLIENT=parsian # or tejaratno | moallem +INSURANCE_CORP_ID='...' # Persian caption matching Fanavaran insurance-corp lookup +``` + +Optional: `CLIENT_ID=8` maps to `parsian` when `FANAVARAN_CLIENT` is unset.