Files
yara724-api/docs/inquiry-participants-proposal.md
2026-09-13 10:59:00 +03:30

118 lines
6.6 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 optional `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.
Existing flat fields remain accepted during migration. Responses and file-detail views for operational actors expose normalized `participants`, `participantRoles`, `vehicle.registrationState`, and `vehicle.previousPlateId` 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",
"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.
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"
},
"vin": "NAAM01E15HK123456"
}
}
```
`registrationState` is `CURRENT` by default or `RECENTLY_TRANSFERRED` for this exceptional path. `previousPlate` is required only when `registrationState=RECENTLY_TRANSFERRED`. The current plate remains the vehicle's primary identifier. The inquiry orchestrator should query the current plate first and automatically try the previous plate 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 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 → Vehicle Owner, third-party policy → Third-party Policyholder, car-body policy → Car-body Policyholder;
- 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`.
V2 user/expert routes, V3, V4, V5, and V6 should be adapters over this shared rule set rather than implementing their own relationship logic.
## Compatibility and rollout
1. Accept the new participant object alongside the legacy fields temporarily.
2. Map legacy `nationalCodeOfDriver` to Driver and `nationalCodeOfInsurer` to Third-party Policyholder. When `driverIsInsurer=true`, bind both roles to the same participant.
3. Map the legacy `plate`/`plateId` to Current Plate; leave Previous Plate absent unless it was explicitly collected.
4. Do not guess Vehicle Owner or Car-body Policyholder for old records. Mark unresolved roles as unknown unless stored inquiry evidence identifies them.
5. Update report/detail responses to expose people by role while retaining legacy fields during migration.
6. After all frontends use the new step, require the new contract for newly created cases and deprecate the legacy fields.
## 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.