Files
yara724-api/docs/panel-roles-reference.html
2026-09-01 15:03:08 +03:30

618 lines
51 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Panel Roles Reference</title>
<style>
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: -apple-system, "Segoe UI", system-ui, sans-serif;
font-size: 14px;
line-height: 1.6;
background: #ffffff;
color: #1f2328;
padding: 24px;
}
h1 { font-size: 20px; font-weight: 700; margin-bottom: 4px; }
.subtitle { font-size: 13px; color: #57606a; margin-bottom: 28px; }
h2 {
font-size: 15px; font-weight: 700;
margin-bottom: 10px; margin-top: 32px;
border-bottom: 1px solid #e5e7eb; padding-bottom: 6px;
}
h3 {
font-size: 12px; font-weight: 700;
text-transform: uppercase; letter-spacing: 0.05em;
color: #57606a; margin-bottom: 8px; margin-top: 14px;
}
.section-intro {
font-size: 13px; color: #57606a;
margin-bottom: 14px; line-height: 1.5;
}
/* Role header strip */
.role-header {
display: flex;
align-items: baseline;
gap: 10px;
margin-bottom: 6px;
}
.role-name {
font-size: 15px;
font-weight: 700;
}
.role-enum {
font-family: monospace;
font-size: 11px;
color: #3b82d4;
background: #f0f7ff;
border: 1px solid #bfdbfe;
border-radius: 4px;
padding: 1px 6px;
}
.badge {
display: inline-block;
font-size: 11px; font-weight: 600;
padding: 1px 7px; border-radius: 10px;
margin-right: 4px; margin-bottom: 3px;
}
.badge-blue { background: #dbeafe; color: #1d4ed8; }
.badge-green { background: #dcfce7; color: #166534; }
.badge-purple { background: #ede9fe; color: #5b21b6; }
.badge-orange { background: #ffedd5; color: #9a3412; }
.badge-teal { background: #ccfbf1; color: #0f766e; }
.badge-indigo { background: #e0e7ff; color: #3730a3; }
.badge-gray { background: #f1f5f9; color: #475569; border: 1px solid #e2e8f0; }
.badge-red { background: #fee2e2; color: #991b1b; }
/* Cards */
.card {
border: 1px solid #e5e7eb;
border-radius: 6px;
padding: 16px;
background: #f7f8fa;
margin-bottom: 16px;
}
.card.card-blue { border-left: 4px solid #3b82f6; }
.card.card-green { border-left: 4px solid #22c55e; }
.card.card-purple { border-left: 4px solid #8b5cf6; }
.card.card-orange { border-left: 4px solid #f97316; }
.card.card-teal { border-left: 4px solid #14b8a6; }
.card.card-indigo { border-left: 4px solid #6366f1; }
.card.card-gray { border-left: 4px solid #94a3b8; }
/* Endpoint tables */
table {
border-collapse: collapse;
width: 100%;
font-size: 12px;
margin-top: 4px;
}
th {
background: #f1f5f9; font-weight: 600;
text-align: left; padding: 5px 8px;
border: 1px solid #e5e7eb;
}
td {
padding: 4px 8px; border: 1px solid #e5e7eb;
vertical-align: top;
}
tr:nth-child(even) td { background: #ffffff; }
code {
font-family: monospace; font-size: 11px; color: #3b82d4;
}
.method {
font-family: monospace; font-size: 11px;
font-weight: 700; white-space: nowrap;
}
.method.get { color: #059669; }
.method.post { color: #2563eb; }
.method.put { color: #d97706; }
.method.patch { color: #7c3aed; }
.method.delete { color: #dc2626; }
.dep { color: #94a3b8; font-style: italic; font-size: 11px; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 860px) { .grid-2 { grid-template-columns: 1fr; } }
.note {
font-size: 11px; color: #57606a; font-style: italic;
margin-top: 6px;
}
.toc {
background: #f7f8fa; border: 1px solid #e5e7eb;
border-radius: 6px; padding: 14px 18px;
margin-bottom: 28px;
}
.toc-title { font-size: 13px; font-weight: 700; margin-bottom: 8px; }
.toc ol { padding-left: 18px; }
.toc li { font-size: 13px; margin-bottom: 3px; }
.toc a { color: #3b82d4; text-decoration: none; }
.toc a:hover { text-decoration: underline; }
footer {
text-align: center; font-size: 12px; color: #57606a;
border-top: 1px solid #e5e7eb;
margin-top: 40px; padding-top: 12px;
}
.max-wrap { max-width: 760px; margin: 0 auto; }
/* Role overview table */
.overview-table { font-size: 12px; margin-bottom: 24px; }
.overview-table th { white-space: nowrap; }
.overview-table td:first-child { font-weight: 600; white-space: nowrap; }
</style>
</head>
<body>
<div class="max-wrap">
<h1>Panel Roles Reference</h1>
<p class="subtitle">
What every actor role can see and do — endpoints, responsibilities, and
process steps. Super-admin excluded.
</p>
<!-- Table of Contents -->
<div class="toc">
<div class="toc-title">Roles covered</div>
<ol>
<li><a href="#insurer">Insurer (COMPANY) — the insurance-company tenant admin</a></li>
<li><a href="#blame-expert">Blame Expert (EXPERT) — disagreement review queue</a></li>
<li><a href="#damage-expert">Damage Expert (DAMAGE_EXPERT) — claim pricing</a></li>
<li><a href="#field-expert">Field Expert (FIELD_EXPERT) — on-scene in-person filing</a></li>
<li><a href="#file-maker">File Maker (FILE_MAKER) — V4/V5 party narrative</a></li>
<li><a href="#file-reviewer">File Reviewer (FILE_REVIEWER) — V4/V5 damage assessment</a></li>
<li><a href="#registrar">Registrar (REGISTRAR) — office-based filing</a></li>
<li><a href="#call-center">Call Center (CALL_CENTER) — V6 phone-initiated filing</a></li>
</ol>
</div>
<!-- ── Role overview table ────────────────────────────────────── -->
<h2>Role Overview</h2>
<table class="overview-table">
<tr>
<th>Role enum</th>
<th>Login panel</th>
<th>Scope</th>
<th>Primary job</th>
</tr>
<tr>
<td><code>company</code></td>
<td>Insurer portal</td>
<td>Tenant-wide</td>
<td>View all files; manage branches, experts; run reports; rate experts</td>
</tr>
<tr>
<td><code>expert</code></td>
<td>Blame expert panel</td>
<td>Tenant DISAGREEMENT queue</td>
<td>Lock blame cases, review party submissions, submit verdict or request resend</td>
</tr>
<tr>
<td><code>damage_expert</code></td>
<td>Claim/damage panel</td>
<td>Tenant claim queue</td>
<td>Lock claims, price damage, validate repair factors, request resend/visit</td>
</tr>
<tr>
<td><code>field_expert</code></td>
<td>Field expert panel</td>
<td>Own created files</td>
<td>V2/V3 in-person blame + claim filing; also sees blame/claim review panels</td>
</tr>
<tr>
<td><code>file_maker</code></td>
<td>FileMaker panel</td>
<td>Own created files</td>
<td>V4/V5 party narrative (OTPs, inquiries, details, signatures); V5 claim approval</td>
</tr>
<tr>
<td><code>file_reviewer</code></td>
<td>FileReviewer panel</td>
<td>Assigned files</td>
<td>V4/V5 damage assessment (accident fields, parts, captures; mixed-factor priced-line acceptance when needed)</td>
</tr>
<tr>
<td><code>registrar</code></td>
<td>Registrar panel</td>
<td>Own created files</td>
<td>Office-based in-person blame + claim filing on behalf of parties</td>
</tr>
<tr>
<td><code>call_center</code></td>
<td>Call-center panel</td>
<td>Own created files</td>
<td>V6 phone-initiated blame: run inquiry, send link; user completes the rest</td>
</tr>
</table>
<!-- ═══════════════════════════════════════════════════════════ -->
<h2 id="insurer">1 — Insurer <span class="role-enum">company</span></h2>
<p class="section-intro">
One <code>company</code> actor per insurance-company tenant. The insurer portal is the
management layer: it can see everything under its tenant, manage the expert roster,
manage branches, configure per-tenant media settings, and pull statistical reports.
The insurer never touches blame/claim steps directly — it only observes and rates.
</p>
<div class="card card-blue">
<h3>File management — <code>expert-insurer/</code></h3>
<table>
<tr><th style="width:70px">Method</th><th>Route</th><th>What it does</th></tr>
<tr><td><span class="method get">GET</span></td><td><code>expert-insurer/files</code></td><td>List all blame + claim files for the tenant (merged by publicId). Filterable by status, file type, search, sort, page.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>expert-insurer/files/:publicId</code></td><td>Full detail for one file by publicId.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>expert-insurer/files/:publicId/timeline</code></td><td>Chronological activity timeline (all history events: source, type, actor, metadata).</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>expert-insurer/files/:publicId/report</code></td><td>Structured report data for PDF generation (owner, driver, insurance, vehicle, accident sections).</td></tr>
<tr><td><span class="method put">PUT</span></td><td><code>expert-insurer/files/:publicId/rating</code></td><td>Rate the experts on a file (1–5 per dimension: collision method, timeliness, cause accuracy, guilty-ID accuracy, bot rating).</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>expert-insurer/report/unified-file-statuses</code></td><td>Unified status catalog + per-status counts for the whole tenant portfolio. Filterable by fileType and date range.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>expert-insurer/report/status-counts</code></td><td class="dep">Deprecated — prefer unified-file-statuses.</td></tr>
</table>
</div>
<div class="card card-blue">
<h3>Branch management — <code>expert-insurer/branches</code></h3>
<table>
<tr><th style="width:70px">Method</th><th>Route</th><th>What it does</th></tr>
<tr><td><span class="method get">GET</span></td><td><code>expert-insurer/branches</code></td><td>List all branches for this insurer. Query: search, from/to date, isActive filter.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>expert-insurer/branches</code></td><td>Add a new branch (name, code, address, city, phone, etc.).</td></tr>
<tr><td><span class="method put">PUT</span></td><td><code>expert-insurer/branches/:branchId/status</code></td><td>Activate or deactivate a branch.</td></tr>
</table>
</div>
<div class="card card-blue">
<h3>Expert roster management — <code>expert-insurer/experts</code></h3>
<table>
<tr><th style="width:70px">Method</th><th>Route</th><th>What it does</th></tr>
<tr><td><span class="method post">POST</span></td><td><code>expert-insurer/experts/blame</code></td><td>Create a new blame-expert account under this insurer.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>expert-insurer/experts/claim</code></td><td>Create a new damage-expert (claim) account under this insurer.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>expert-insurer/experts/file-maker</code></td><td>Create a new FileMaker account under this insurer.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>expert-insurer/experts/file-reviewer</code></td><td>Create a new FileReviewer account under this insurer.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>expert-insurer/experts/list</code></td><td>Paginated list of all expert accounts on this tenant.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>expert-insurer/experts/top</code></td><td>Top blame vs claim experts ranked by overall average rating (up to 10 each).</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>expert-insurer/top-experts</code></td><td>Alias for experts/top (frontend compat).</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>expert-insurer/:expertId</code></td><td>Files handled by one expert (slim summary rows — blame or claim depending on expert type).</td></tr>
</table>
</div>
<div class="card card-blue">
<h3>Statistics &amp; reports</h3>
<table>
<tr><th style="width:70px">Method</th><th>Route</th><th>What it does</th></tr>
<tr><td><span class="method get">GET</span></td><td><code>expert-insurer/statistics</code></td><td>KPI cards: totalFilesReviewed, averageUserRating, inPersonCount, filesThisMonth, objectionPercentage, etc. Filterable by date range.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>expert-insurer/top-files</code></td><td>Top 10 highest-rated claim files (combined insurer + user score).</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>expert-insurer/expert-work-log</code></td><td>Per-expert work log: totalHandled, currentlyChecking, distinctFilesCheckedInPeriod. Filterable by expertKind and date range.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>reports/report/insurer/requests</code></td><td>Claim + blame status bucket counts + unified file count for the tenant.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>reports/report/insurer/per-month-requests</code></td><td>Same summary, broken down by the last 5 calendar months.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>reports/report/insurer/checked-requests</code></td><td>Same summary filtered by optional createdAt date range.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>reports/report/insurer/expert-work-log</code></td><td>Expert work log (blame + damage expert collections, not field experts).</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>reports/report/insurer/expert-work-log/per-month</code></td><td>Same work log per calendar month (last 5).</td></tr>
</table>
</div>
<div class="card card-blue">
<h3>Tenant settings — <code>client-panel/</code></h3>
<table>
<tr><th style="width:70px">Method</th><th>Route</th><th>What it does</th></tr>
<tr><td><span class="method get">GET</span></td><td><code>client-panel/settings</code></td><td>Get per-tenant media limits (video/image/voice maxBytes) and CAR_BODY accident window (days).</td></tr>
<tr><td><span class="method patch">PATCH</span></td><td><code>client-panel/settings</code></td><td>Update those settings (partial). Cannot exceed system-level route ceilings.</td></tr>
</table>
</div>
<!-- ═══════════════════════════════════════════════════════════ -->
<h2 id="blame-expert">2 — Blame Expert <span class="role-enum">expert</span></h2>
<p class="section-intro">
Reviews blame files in the DISAGREEMENT queue — cases where the two parties do not
agree on who is at fault. After reviewing submitted documents and party statements
the expert locks the case, then either submits a verdict, asks the parties to resend
documents, or records an in-person visit outcome. All endpoints are under
<code>v2/expert-blame/</code>.
</p>
<div class="card card-orange">
<h3>Process</h3>
<p class="note">
1 Browse list → 2 Assign (lock) the case → 3 Review party evidence (videos, voices, documents) →
4a Submit verdict <em>or</em> 4b Request document resend <em>or</em> 4c Record in-person visit.
</p>
</div>
<div class="card card-orange">
<h3>Endpoints — <code>v2/expert-blame/</code></h3>
<table>
<tr><th style="width:70px">Method</th><th>Route</th><th>What it does</th></tr>
<tr><td><span class="method get">GET</span></td><td><code>v2/expert-blame/</code></td><td>List blame cases in the DISAGREEMENT queue (available, locked by me, or decided by me). Query: search, sortBy, sortOrder, page, limit, unifiedStatus, fileType.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>v2/expert-blame/:id</code></td><td>Full detail for one blame case (party statements, photos, voices, videos).</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>v2/expert-blame/:id/assign</code></td><td>Check availability and lock the case to this expert. Returns <code>assigned</code>, <code>already_assigned_to_you</code>, or 409 if someone else holds it.</td></tr>
<tr><td><span class="method put">PUT</span></td><td><code>v2/expert-blame/reply/submit/:id</code></td><td>Submit verdict (accidentWay, accidentReason, accidentType, guilty party decision). Unlocks the case and moves it to COMPLETED.</td></tr>
<tr><td><span class="method put">PUT</span></td><td><code>v2/expert-blame/reply/resend/:id</code></td><td>Request parties to re-upload documents. Sets blame to WAITING_FOR_RESEND. One resend request per lifecycle.</td></tr>
<tr><td><span class="method put">PUT</span></td><td><code>v2/expert-blame/reply/inPerson/:id</code></td><td>Record that an in-person visit was made and submit verdict.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>v2/expert-blame/report/unified-file-statuses</code></td><td>Status catalog + per-status counts for this expert's portfolio.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>v2/expert-blame/report/status-counts</code></td><td class="dep">Deprecated — prefer unified-file-statuses.</td></tr>
<tr><td><span class="method put">PUT</span></td><td><code>v2/expert-blame/lock/:id</code></td><td class="dep">Deprecated lock endpoint — use POST assign.</td></tr>
</table>
</div>
<!-- ═══════════════════════════════════════════════════════════ -->
<h2 id="damage-expert">3 — Damage Expert <span class="role-enum">damage_expert</span></h2>
<p class="section-intro">
Reviews claim files after the user has submitted their damage evidence. The expert
prices each damaged part, optionally calculates a price-drop (depreciation), and
can ask the user to resend documents, come in person, or upload repair factor invoices
when workshop pricing is needed. All endpoints are under <code>v2/expert-claim/</code>.
</p>
<div class="card card-red">
<h3>Process</h3>
<p class="note">
1 Browse list → 2 Assign (lock) the claim → 3 Review damage photos and documents →
4 Optionally edit selected parts or calculate price-drop →
5a Submit priced reply <em>or</em> 5b Request resend <em>or</em> 5c Request in-person visit →
6 If factor parts present: validate uploaded factor invoices.
</p>
</div>
<div class="card card-red">
<h3>Endpoints — <code>v2/expert-claim/</code></h3>
<table>
<tr><th style="width:70px">Method</th><th>Route</th><th>What it does</th></tr>
<tr><td><span class="method get">GET</span></td><td><code>v2/expert-claim/requests</code></td><td>List claims in <code>WAITING_FOR_DAMAGE_EXPERT</code> queue + factor-validation queue. Query: search, sortBy, page, limit, unifiedStatus, fileType.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>v2/expert-claim/request/:claimRequestId</code></td><td>Full claim detail: damaged parts, captured images, documents, priceDrop, blameCase party data, video URLs.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>v2/expert-claim/assign/:claimRequestId</code></td><td>Lock claim to this expert. Returns <code>assigned</code>, <code>already_assigned_to_you</code>, or 409.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>v2/expert-claim/request/:claimRequestId/price-drop</code></td><td>Price-drop context: severity labels, coefficient catalog, damaged parts + mapping, suggested car year from blame inquiry.</td></tr>
<tr><td><span class="method put">PUT</span></td><td><code>v2/expert-claim/request/:claimRequestId/price-drop</code></td><td>Calculate and persist price-drop: carPrice × yearCoeff × sumOfCoeffs ÷ 400.</td></tr>
<tr><td><span class="method put">PUT</span></td><td><code>v2/expert-claim/reply/submit/:claimRequestId</code></td><td>Submit damage assessment reply (priced parts list, daghi, branchId). Cap: total ≤ 53 000 000 Toman. A priced-only claim completes immediately; factor claims continue through factor collection/validation. No final owner signature or automatic Fanavaran submission.</td></tr>
<tr><td><span class="method put">PUT</span></td><td><code>v2/expert-claim/reply/resend/:claimRequestId</code></td><td>Request user to resend documents/photos. One resend per claim lifecycle; returns 422 if already fulfilled.</td></tr>
<tr><td><span class="method patch">PATCH</span></td><td><code>v2/expert-claim/:claimRequestId/visit</code></td><td>Ask user to come in person. Unlocks claim, sets claimStatus to NEEDS_REVISION.</td></tr>
<tr><td><span class="method patch">PATCH</span></td><td><code>v2/expert-claim/validate-factors/:claimRequestId</code></td><td>Validate uploaded repair factor invoices. Approve or reject each factor line with totalPayment. Cap applies across all lines (≤ 53 000 000 Toman). Auto-completes when all lines are decided.</td></tr>
<tr><td><span class="method patch">PATCH</span></td><td><code>v2/expert-claim/request/:claimRequestId/damaged-parts</code></td><td>Edit selected damaged parts while the claim is locked by this expert (EXPERT_REVIEWING).</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>v2/expert-claim/outer-parts-catalog</code></td><td>Fanavaran outer car-components catalog (shared with user flow).</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>v2/expert-claim/inner-parts-catalog</code></td><td>Static inner car-parts catalog JSON.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>v2/expert-claim/branches</code></td><td>Insurer branches for this expert's tenant (for daghi/branch selection in reply payload).</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>v2/expert-claim/stream/:id/video</code></td><td>Stream claim video (car-capture walk-around or accident video). Query: <code>query=car-capture|accident</code>.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>v2/expert-claim/report/unified-file-statuses</code></td><td>Status catalog + counts for this expert's claim portfolio.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>v2/expert-claim/report/status-counts</code></td><td class="dep">Deprecated — prefer unified-file-statuses.</td></tr>
<tr><td><span class="method put">PUT</span></td><td><code>v2/expert-claim/lock/:claimRequestId</code></td><td class="dep">Deprecated lock endpoint — use POST assign.</td></tr>
</table>
</div>
<!-- ═══════════════════════════════════════════════════════════ -->
<h2 id="field-expert">4 — Field Expert <span class="role-enum">field_expert</span></h2>
<p class="section-intro">
Goes to the accident scene and fills both parties' forms in-person (V2 mirror / V3 flows).
The field expert also has read access to the expert-blame and expert-claim panels
(scoped to their own files). They are the only role that spans both
<strong>blame filing</strong> and <strong>claim filing</strong> in the same session.
</p>
<div class="card card-green">
<h3>Blame filing — <code>v2/expert-initiated/blame-request-management/</code></h3>
<p class="note">Mirror of the user blame API. Frontend reuses same pages by swapping prefix only.</p>
<table>
<tr><th style="width:70px">Method</th><th>Route</th><th>What it does</th></tr>
<tr><td><span class="method post">POST</span></td><td><code>POST /</code></td><td>Create IN_PERSON blame file.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>send-party-otp/:id</code></td><td>Send OTP to one party by phone number (no invite link).</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>verify-party-otp/:id</code></td><td>Verify one party's OTP and bind their account.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>blame-confession/:id</code></td><td>Record party's blame confession.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>car-body-form/:id</code></td><td>[CAR_BODY only] Accident type form.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>run-inquiries/:id</code> / <code>run-inquiries-vin/:id</code></td><td>Initial form / plate or VIN inquiry for current party.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>upload-video/:id</code></td><td>Upload first-party video.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>add-detail-location/:id</code></td><td>Add GPS location for current party.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>upload-voice/:id</code></td><td>Upload voice recording for current party.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>add-detail-description/:id</code></td><td>Add description for current party.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>add-second-party/:phone/:id/</code></td><td>Advance to second party (no SMS link sent).</td></tr>
<tr><td><span class="method put">PUT</span></td><td><code>sign/:id</code></td><td>Upload party signature (FIRST then SECOND, partyRole param).</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>accident-fields/:id</code></td><td>Save accident fields and complete blame immediately (no expert queue).</td></tr>
</table>
</div>
<div class="card card-green">
<h3>V3 blame + claim filing — <code>v3/expert-initiated/blame-request-management/</code></h3>
<p class="note">Reorganised step order: all party narrative first, then damage assessment. Blame and claim both handled in this single controller.</p>
<table>
<tr><th style="width:70px">Method</th><th>Route</th><th>What it does</th></tr>
<tr><td><span class="method post">POST</span></td><td><code>POST /</code> → <code>send-party-otp</code> → <code>verify-party-otp</code> → <code>run-inquiries</code> → <code>add-detail-*</code> → <code>sign</code> (×2)</td><td>Party narrative phase (steps 1–8) — identical endpoints to mirror, same contract.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>accident-fields/:id</code></td><td>Step 9: save accident fields after both parties have signed.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>claim-id/:requestId</code></td><td>Step 10: get auto-created claim ID.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>upload-document/:claimId</code></td><td>Step 11: upload licence / car card documents.</td></tr>
<tr><td><span class="method patch">PATCH</span></td><td><code>select-outer-parts/:claimId</code> / <code>select-other-parts/:claimId</code></td><td>Steps 12–13: select damaged parts.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>capture-part/:claimId</code></td><td>Step 14: capture part photos + angles.</td></tr>
<tr><td><span class="method patch">PATCH</span></td><td><code>car-capture/:claimId</code></td><td>Step 15: walk-around video.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>upload-video/:requestId</code></td><td>Step 16: blame accident video (final) → WAITING_FOR_EXPERT (THIRD_PARTY) or COMPLETED (CAR_BODY).</td></tr>
</table>
</div>
<div class="card card-green">
<h3>Expert-blame + expert-claim panel (read + action on own files)</h3>
<p class="note">
FIELD_EXPERT sees <code>v2/expert-blame/</code> scoped to their own created files (not the disagreement queue).
They also see <code>v2/expert-claim/</code> for claims linked to their blame files.
Same endpoints as blame-expert and damage-expert panels above.
</p>
</div>
<!-- ═══════════════════════════════════════════════════════════ -->
<h2 id="file-maker">5 — File Maker <span class="role-enum">file_maker</span></h2>
<p class="section-intro">
The first actor in the V4/V5 split. FileMaker handles the party narrative on-site:
OTPs, inquiries, location/description/voice, and signatures for both parties.
They also upload the initial claim documents (licences, car cards). After the second
signature the file is "sealed" for FileReviewer pickup. In V5, FileMaker comes
back at the end to approve or reject the completed claim. After approval, an
expert submits the case to Fanavaran manually.
</p>
<div class="card card-purple">
<h3>Blame filing — <code>v4/file-maker/blame-request-management/</code> and <code>v5/…</code></h3>
<p class="note">V4 and V5 endpoints are identical — only the prefix changes. V5 sets <code>requiresFileMakerApproval=true</code> at creation.</p>
<table>
<tr><th style="width:70px">Method</th><th>Route</th><th>What it does</th></tr>
<tr><td><span class="method post">POST</span></td><td><code>POST /</code></td><td>Create IN_PERSON blame file.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>my-files</code></td><td>List all blame files created by this FileMaker.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>my-files/:requestId</code></td><td>Full detail for one file (parties, workflow, linked claim ID).</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>claim-id/:requestId</code></td><td>Get the auto-created claim ID after guilty-party run-inquiries.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>send-party-otp/:id</code> / <code>verify-party-otp/:id</code></td><td>Send + verify OTP for one party at a time (guilty first, then damaged).</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>car-body-form/:id</code></td><td>[CAR_BODY only] Accident type form.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>run-inquiries/:id</code> / <code>run-inquiries-vin/:id</code></td><td>Run plate or VIN inquiry. First call = guilty (+ auto-creates claim). Second call = damaged (THIRD_PARTY only).</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>add-detail-location/:id</code> / <code>add-detail-description/:id</code> / <code>upload-voice/:id</code></td><td>Add location, description, and voice for current party (partyRole param selects FIRST/SECOND).</td></tr>
<tr><td><span class="method put">PUT</span></td><td><code>sign/:id</code></td><td>Upload party signature (partyRole=FIRST then SECOND). After second signature, file is sealed.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>upload-document/:claimId</code></td><td>Upload licences / car cards against the auto-created claim.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>capture-requirements/:claimId</code></td><td>Step-aware capture requirements (phases: pre-capture docs vs damaged parts + chassis/engine).</td></tr>
</table>
</div>
<div class="card card-purple">
<h3>V5 claim approval — <code>v5/file-maker/claim-approval/</code></h3>
<p class="note">Used only in V5. After damage expert review and any required factor validation, claim enters <code>WAITING_FOR_FILE_MAKER_APPROVAL</code>; no final owner signature is needed.</p>
<table>
<tr><th style="width:70px">Method</th><th>Route</th><th>What it does</th></tr>
<tr><td><span class="method post">POST</span></td><td><code>approve/:claimId</code></td><td>Approve the completed claim → claim becomes <code>COMPLETED</code>. An expert submits to Fanavaran manually when ready.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>reject/:claimId</code></td><td>Reject back to FileReviewer → claim returns to WAITING_FOR_DAMAGE_EXPERT. Limit: max 2 rejections per claim; 3rd attempt returns 422 <code>FILE_MAKER_REJECTION_LIMIT_EXCEEDED</code>.</td></tr>
</table>
</div>
<!-- ═══════════════════════════════════════════════════════════ -->
<h2 id="file-reviewer">6 — File Reviewer <span class="role-enum">file_reviewer</span></h2>
<p class="section-intro">
The second actor in the V4/V5 split. FileReviewer picks up sealed files (after
FileMaker is done) and performs the full damage assessment pass: accident fields,
capture requirements lookup, document upload (chassis/engine), part selection,
part photos and walk-around video. The blame is marked COMPLETED
by car-capture. FileReviewer also has read access to the expert-claim panel for
claims they are reviewing.
</p>
<div class="card card-teal">
<h3>Damage assessment — <code>v4/file-reviewer/blame-request-management/</code> and <code>v5/…</code></h3>
<p class="note">V4 and V5 endpoints are identical — only the prefix changes.</p>
<table>
<tr><th style="width:70px">Method</th><th>Route</th><th>What it does</th></tr>
<tr><td><span class="method get">GET</span></td><td><code>my-files</code></td><td>List FileMaker-sealed files available to claim in this reviewer’s insurer, plus files already assigned to this FileReviewer.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>my-files/:requestId</code></td><td>Full detail for one available or assigned file in this reviewer’s insurer (parties, workflow, expert fields, linked claim ID).</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>claim-id/:requestId</code></td><td>Get the auto-created claim ID (from FileMaker's guilty-party inquiry).</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>accident-fields/:requestId</code></td><td>Step 1 (FileReviewer): save accident fields (accidentWay, accidentReason, accidentType).</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>capture-requirements/:claimId</code></td><td>Step-aware capture requirements (pre-capture docs phase vs capture-parts phase).</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>upload-document/:claimId</code></td><td>Upload chassis / engine / metal-plate documents.</td></tr>
<tr><td><span class="method patch">PATCH</span></td><td><code>select-outer-parts/:claimId</code></td><td>Select outer (body) damaged parts.</td></tr>
<tr><td><span class="method patch">PATCH</span></td><td><code>select-other-parts/:claimId</code></td><td>Select other (non-body) damaged parts.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>capture-part/:claimId</code></td><td>Capture part photos + angles for each selected damaged part.</td></tr>
<tr><td><span class="method patch">PATCH</span></td><td><code>car-capture/:claimId</code></td><td>Walk-around video (final FileReviewer capture step). Claim → <code>WAITING_FOR_DAMAGE_EXPERT</code>, blame → <code>COMPLETED</code>.</td></tr>
<tr><td><span class="method put">PUT</span></td><td><code>claim-sign/:claimId</code></td><td>For mixed priced/factor claims only: record acceptance of priced lines before factor uploads. A final owner signature is no longer required.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>upload-video/:requestId</code></td><td class="dep">No-op in V4/V5 — blame already COMPLETED by car-capture. Returns idempotent success.</td></tr>
</table>
</div>
<div class="card card-teal">
<h3>Expert-claim panel access</h3>
<p class="note">
FILE_REVIEWER is in the allowed roles for <code>v2/expert-claim/</code>.
They can view claim details and run the assign/lock flow for claims associated
with their files. They cannot initiate a damage-expert resend independently.
</p>
</div>
<!-- ═══════════════════════════════════════════════════════════ -->
<h2 id="registrar">7 — Registrar <span class="role-enum">registrar</span></h2>
<p class="section-intro">
Office-based role that files in-person blame and claim on behalf of parties.
Uses a bulk-OTP flow (both parties' OTPs sent and verified in one call each)
rather than the one-at-a-time OTP used by field experts. After blame, the
registrar mirrors the user claim API to fill part selection, documents, and
captures. The file then enters the normal damage-expert review lifecycle.
</p>
<div class="card card-gray">
<h3>Blame filing — <code>registrar-initiated-blame/</code></h3>
<p class="note">Note: <code>@ApiExcludeController</code> — routes exist but not surfaced in Swagger docs.</p>
<table>
<tr><th style="width:70px">Method</th><th>Route</th><th>What it does</th></tr>
<tr><td><span class="method post">POST</span></td><td><code>registrar-initiated-blame/create</code></td><td>Create IN_PERSON blame file.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>registrar-initiated-blame/my-files</code></td><td>List all blame files created by this registrar.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>registrar-initiated-blame/blame/:requestId</code></td><td>Full detail for one blame file.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>registrar-initiated-blame/send-party-otps/:id</code></td><td>Send OTPs to both parties simultaneously.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>registrar-initiated-blame/verify-party-otps/:id</code></td><td>Verify both parties' OTPs in one call.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>registrar-initiated-blame/complete-blame-data/:id</code></td><td>Submit all blame form data for both parties in one payload.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>registrar-initiated-blame/upload-video/:id</code></td><td>Upload blame video.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>registrar-initiated-blame/upload-voice/:id</code></td><td>Upload voice recording.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>registrar-initiated-blame/add-accident-fields/:id</code></td><td>Save accident fields and complete blame.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>registrar-initiated-blame/upload-party-signature/:id</code></td><td>Upload a party's signature (partyRole=FIRST/SECOND).</td></tr>
</table>
</div>
<div class="card card-gray">
<h3>Claim filing — <code>v2/registrar/claim-request-management/</code></h3>
<p class="note">Mirror of the user claim API. Frontend reuses same claim pages by swapping prefix only.</p>
<table>
<tr><th style="width:70px">Method</th><th>Route</th><th>What it does</th></tr>
<tr><td><span class="method post">POST</span></td><td><code>create-from-blame/:blameId</code></td><td>Create claim from a completed blame file.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>outer-parts-catalog</code> / <code>car-other-part</code></td><td>Parts catalogs (outer body parts + other parts JSON).</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>branches/:insuranceId</code></td><td>Insurer branch list (for branch selection in claim sign step).</td></tr>
<tr><td><span class="method patch">PATCH</span></td><td><code>select-outer-parts/:claimId</code></td><td>Select outer damaged parts.</td></tr>
<tr><td><span class="method patch">PATCH</span></td><td><code>select-other-parts/:claimId</code></td><td>Select other damaged parts + bank info.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>upload-document/:claimId</code></td><td>Upload claim documents (licences, car card).</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>capture-part/:claimId</code></td><td>Capture part photos + angles.</td></tr>
<tr><td><span class="method patch">PATCH</span></td><td><code>car-capture/:claimId</code></td><td>Walk-around video (final step) → WAITING_FOR_DAMAGE_EXPERT.</td></tr>
</table>
</div>
<!-- ═══════════════════════════════════════════════════════════ -->
<h2 id="call-center">8 — Call Center <span class="role-enum">call_center</span></h2>
<p class="section-intro">
Handles V6 phone-initiated blame filing. The agent collects the guilty party's
data over the phone, runs the insurance inquiry, and sends the blame link via
SMS. The user then completes the rest of the form through the standard V2 flow
(with the initial-form/inquiry step skipped). The call-center agent's job ends
after send-link; they can monitor progress via the read endpoints.
</p>
<div class="card card-indigo">
<h3>Endpoints — <code>v6/call-center-blame/</code></h3>
<table>
<tr><th style="width:70px">Method</th><th>Route</th><th>What it does</th></tr>
<tr><td><span class="method post">POST</span></td><td><code>create</code></td><td>Create a LINK blame file. Body: <code>{ type: "THIRD_PARTY" | "CAR_BODY" }</code>.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>run-inquiry/:requestId</code></td><td>Run plate + national-code insurance inquiry for the guilty party. Stores result on blame document.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>run-inquiry-vin/:requestId</code></td><td>VIN/chassis alternative to run-inquiry. Uses ESG chassis lookup.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>send-link/:requestId</code></td><td>Register user if needed, store as first party, send blame invite link via SMS. Body: <code>{ phoneNumber }</code>.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>my-files</code></td><td>List all blame files started by this agent.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>blame/:requestId</code></td><td>Current status and workflow step for one file (to check if user has opened the link and progressed).</td></tr>
</table>
<p class="note" style="margin-top:8px;">
After <code>send-link</code> the user completes the form via
<code>v2/blame-request-management/</code> (standard V2 flow).
The initial-form / inquiry step is automatically skipped
(<code>skipInitialFormStep=true</code>). Downstream claim flow is the
standard V2 claim flow.
</p>
</div>
<!-- ═══════════════════════════════════════════════════════════ -->
<h2>Shared: Actor Authentication</h2>
<p class="section-intro">
All panel actors (every role except <code>user</code>) authenticate through the same
<code>POST actor/login</code> endpoint with captcha. Password reset is via email OTP.
Profile reads and edits are also shared.
</p>
<div class="card card-gray">
<h3>Endpoints — <code>actor/</code></h3>
<table>
<tr><th style="width:70px">Method</th><th>Route</th><th>What it does</th></tr>
<tr><td><span class="method get">GET</span></td><td><code>actor/captcha</code></td><td>Issue a new login captcha challenge (returns captchaId + SVG image).</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>actor/login</code></td><td>Authenticate any actor role. Body: role, username/email/nationalCode, password, captchaId, captcha. Returns JWT access + refresh tokens.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>actor/forget-password</code></td><td>Send password-reset OTP to email.</td></tr>
<tr><td><span class="method post">POST</span></td><td><code>actor/forget-password-verify</code></td><td>Verify OTP and set new password.</td></tr>
<tr><td><span class="method get">GET</span></td><td><code>actor/profile</code></td><td>Get current actor's profile.</td></tr>
<tr><td><span class="method patch">PATCH</span></td><td><code>actor/profile</code></td><td>Update current actor's profile.</td></tr>
</table>
</div>
<footer>Made by Sepehr</footer>
</div>
</body>
</html>