Merge pull request 'main' (#256) from s.hajizadeh/yara724api:main into main

Reviewed-on: Yara724/api#256
This commit is contained in:
2026-08-08 15:59:50 +03:30
14 changed files with 1431 additions and 14 deletions

View File

@@ -1,15 +1,3 @@
# api ## Documentation
Current JWT payload: - [Fanavaran integration](docs/fanavaran/README.md)
```json
{
"username": "saman_insurer@gmail.com",
"sub": "6a144979799f3c63aa63f67c",
"fullName": "بیمه گر سامان",
"role": "company",
"userType": "UserType",
"clientKey": "67f0fd0e53868dc1ff8a2738",
"iat": 1781339791,
"exp": 1781343391
}
```

View File

@@ -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`.

View File

@@ -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`.

View File

@@ -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)).

View File

@@ -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).

View File

@@ -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).

View File

@@ -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`.

View File

@@ -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 |

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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).

View File

@@ -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 <key>` 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/<key>/`
### 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=<key>
INSURANCE_CORP_ID='<exact Caption from insurance-corp lookup>'
```
### 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

99
docs/fanavaran/README.md Normal file
View File

@@ -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 <client>` 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.