fanavaran sales integration docs

This commit is contained in:
2026-08-08 15:53:35 +03:30
parent 91028f999c
commit 5a4a511e84
13 changed files with 1429 additions and 0 deletions

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