forked from Yara724/api
119 lines
7.2 KiB
Markdown
119 lines
7.2 KiB
Markdown
# Inquiry participant identity proposal
|
|
|
|
Status: implemented on 2026-09-13
|
|
Scope: every user, expert, FileMaker, and call-center inquiry flow
|
|
Persian version: [inquiry-participants-proposal.fa.md](./inquiry-participants-proposal.fa.md)
|
|
|
|
## Implemented interface
|
|
|
|
The role fields and required `vehicle` object shown below are accepted directly in every existing inquiry request body. This covers V2 user and expert/registrar mirror initial forms, V3 expert flow, V4/V5 FileMaker flows, V6 call-center flow, and the one-shot in-person completion paths. Plate and VIN routes share the same participant rules. Flat driver/insurer fields and phone numbers are not inquiry inputs.
|
|
|
|
Responses and file-detail views for operational actors expose normalized `participants`, `participantRoles`, `vehicle.registrationState`, `vehicle.previousPlateId`, and `vehicle.previousPolicyholderNationalCode` where available.
|
|
|
|
## Problem
|
|
|
|
The current inquiry contract mainly models a driver and a value named `insurer`. That is incomplete and the name is misleading: a person is the **policyholder**; the **insurer** is the insurance company.
|
|
|
|
Each vehicle-side `Party` can have these identity roles:
|
|
|
|
| Case type | Required roles |
|
|
| ------------- | ---------------------------------------------------------------------- |
|
|
| `THIRD_PARTY` | Driver, vehicle owner, third-party policyholder |
|
|
| `CAR_BODY` | Driver, vehicle owner, third-party policyholder, car-body policyholder |
|
|
|
|
One person may hold several roles, but the system must not assume that they do.
|
|
|
|
## Recommendation
|
|
|
|
Add a short **participant-identification step before inquiry**. Ask relationship questions and collect details only for distinct people. Do not ask for every person's complete data unconditionally, and do not add pairwise flags such as `driverIsOwner`, `ownerIsPolicyholder`, and `driverIsBodyPolicyholder`; that becomes ambiguous and grows combinatorially.
|
|
|
|
Use explicit role references instead:
|
|
|
|
```json
|
|
{
|
|
"driver": {
|
|
"nationalCode": "0012345678",
|
|
"birthday": "1370/01/01",
|
|
"hasDrivingLicense": true,
|
|
"licenseNumber": "123456789",
|
|
"licenseType": "1"
|
|
},
|
|
"vehicleOwner": { "sameAs": "DRIVER" },
|
|
"thirdPartyPolicyholder": { "sameAs": "VEHICLE_OWNER" },
|
|
"carBodyPolicyholder": {
|
|
"nationalCode": "0098765432",
|
|
"birthday": "1365/02/03"
|
|
}
|
|
}
|
|
```
|
|
|
|
`carBodyPolicyholder` is forbidden for `THIRD_PARTY` and required for `CAR_BODY`. A role is either a new person's identity or a `sameAs` reference, never both. The backend should normalize this input into unique participants plus role assignments.
|
|
|
|
Every policyholder must resolve to a known participant through identity fields or `sameAs`. The removed `unknown` option is rejected for every role, so policy inquiries are never skipped because a policyholder identity is missing.
|
|
|
|
For Driver, `hasDrivingLicense` is required. When it is `true`, both `licenseNumber` and `licenseType` are required; when it is `false`, the licence inquiry is intentionally skipped.
|
|
|
|
## Recent ownership transfer and previous plate
|
|
|
|
Participant roles and vehicle identifiers are separate concerns. When a vehicle has recently been sold or purchased, the current official record or policy may still be connected to its previous plate. Model this explicitly instead of replacing the current plate:
|
|
|
|
```json
|
|
{
|
|
"vehicle": {
|
|
"registrationState": "RECENTLY_TRANSFERRED",
|
|
"currentPlate": {
|
|
"leftDigits": "44",
|
|
"centerAlphabet": "ب",
|
|
"centerDigits": "111",
|
|
"ir": "22"
|
|
},
|
|
"previousPlate": {
|
|
"leftDigits": "55",
|
|
"centerAlphabet": "ج",
|
|
"centerDigits": "222",
|
|
"ir": "33"
|
|
},
|
|
"previousPolicyholderNationalCode": "0098765432",
|
|
"vin": "NAAM01E15HK123456"
|
|
}
|
|
}
|
|
```
|
|
|
|
`registrationState` is `CURRENT` by default or `RECENTLY_TRANSFERRED` for this exceptional path. `previousPlate`, `previousPolicyholderNationalCode`, and `vin` are required when `registrationState=RECENTLY_TRANSFERRED`; the previous-plate fields are forbidden for the normal `CURRENT` path. The current plate remains the vehicle's primary identifier. The inquiry orchestrator queries the current plate with the current policyholder's national code first, then automatically tries the previous plate with `previousPolicyholderNationalCode` when the current result is missing, stale, or does not find the relevant policy.
|
|
|
|
Before accepting a previous-plate result, the backend must correlate it to the same VIN/chassis. A mismatch must stop automatic selection and require correction or manual review. Both identifiers and every attempted inquiry should be retained for audit, but a previous plate must never overwrite the current plate.
|
|
|
|
## Suggested UI sequence
|
|
|
|
1. Collect the current plate and ask whether the vehicle was recently transferred. If yes, collect the previous plate, its policyholder's national code, and VIN/chassis.
|
|
2. Collect driver identity and licence details.
|
|
3. Ask whether the vehicle owner is the driver; collect owner identity only when different.
|
|
4. Ask whether the third-party policyholder is the driver, the owner, or another person; collect identity only for “another person”.
|
|
5. For `CAR_BODY`, ask the same question for the car-body policyholder, allowing any already entered person or another person.
|
|
6. Show a short review, then run the inquiries.
|
|
|
|
This keeps the common case fast while representing all valid combinations.
|
|
|
|
## Backend seam
|
|
|
|
Create one shared participant resolver used by every inquiry route. Its interface should:
|
|
|
|
- validate required roles by case type and reject circular/invalid `sameAs` references;
|
|
- return the resolved person for each role;
|
|
- route the correct identity to each inquiry: driver licence → Driver, ownership and Sheba validation → Vehicle Owner, third-party policy by plate/VIN → Third-party Policyholder, car-body policy by plate/VIN → Car-body Policyholder;
|
|
- require Sheba in the claimant inquiry (`THIRD_PARTY` damaged/SECOND party and `CAR_BODY` first party) and validate it against the resolved Vehicle Owner; the `THIRD_PARTY` guilty/FIRST inquiry does not collect Sheba;
|
|
- choose the current or previous plate deterministically and verify previous-plate results against VIN/chassis;
|
|
- run personal identity inquiry once per distinct person;
|
|
- persist normalized participants and role assignments on the relevant `Party`.
|
|
- expose the persisted `participants` and `participantRoles` unchanged in expert-facing blame and linked-claim details so driver and other role data remain available for review.
|
|
|
|
V2 user/expert routes, V3, V4, V5, and V6 should be adapters over this shared rule set rather than implementing their own relationship logic.
|
|
|
|
## Contract boundary
|
|
|
|
The structured participant and vehicle objects are the only accepted inquiry input. The backend rejects flat fields such as `nationalCodeOfDriver`, `nationalCodeOfInsurer`, `driverIsInsurer`, top-level `plate`/`vin`, and `phoneNumber` with a validation error. Phone-based authentication and party contact flows remain separate from inquiry identity collection.
|
|
|
|
## Decision
|
|
|
|
Prefer **conditional collection plus explicit role assignments**. It provides complete data without burdening most users, prevents contradictory booleans, and gives all inquiry flows one consistent domain model.
|