forked from Yara724/api
Compare commits
3 Commits
85fc83b564
...
3bd6bc6e9d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bd6bc6e9d | ||
|
|
26c80512ba | ||
|
|
f09f5b79f0 |
596
docs/external-integrations-reference.fa.html
Normal file
596
docs/external-integrations-reference.fa.html
Normal file
@@ -0,0 +1,596 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fa" dir="rtl">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>مرجع یکپارچهسازیهای خارجی</title>
|
||||||
|
<style>
|
||||||
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
body {
|
||||||
|
font-family: "Vazirmatn", "Tahoma", "Segoe UI", system-ui, sans-serif;
|
||||||
|
font-size: 14px; line-height: 1.8;
|
||||||
|
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.03em;
|
||||||
|
color: #57606a; margin-bottom: 8px; margin-top: 14px;
|
||||||
|
}
|
||||||
|
.section-intro {
|
||||||
|
font-size: 13px; color: #57606a;
|
||||||
|
margin-bottom: 14px; line-height: 1.7;
|
||||||
|
}
|
||||||
|
.card {
|
||||||
|
border: 1px solid #e5e7eb; border-radius: 6px;
|
||||||
|
padding: 16px; background: #f7f8fa; margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
.card.card-blue { border-right: 4px solid #3b82f6; }
|
||||||
|
.card.card-green { border-right: 4px solid #22c55e; }
|
||||||
|
.card.card-purple { border-right: 4px solid #8b5cf6; }
|
||||||
|
.card.card-orange { border-right: 4px solid #f97316; }
|
||||||
|
.card.card-teal { border-right: 4px solid #14b8a6; }
|
||||||
|
.card.card-indigo { border-right: 4px solid #6366f1; }
|
||||||
|
.card.card-gray { border-right: 4px solid #94a3b8; }
|
||||||
|
.card.card-red { border-right: 4px solid #ef4444; }
|
||||||
|
.card.card-yellow { border-right: 4px solid #eab308; }
|
||||||
|
table {
|
||||||
|
border-collapse: collapse; width: 100%;
|
||||||
|
font-size: 12px; margin-top: 4px; direction: rtl;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background: #f1f5f9; font-weight: 600;
|
||||||
|
text-align: right; 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;
|
||||||
|
direction: ltr; unicode-bidi: embed;
|
||||||
|
}
|
||||||
|
.method {
|
||||||
|
font-family: monospace; font-size: 11px;
|
||||||
|
font-weight: 700; white-space: nowrap;
|
||||||
|
direction: ltr; unicode-bidi: embed;
|
||||||
|
}
|
||||||
|
.method.get { color: #059669; }
|
||||||
|
.method.post { color: #2563eb; }
|
||||||
|
.method.put { color: #d97706; }
|
||||||
|
.method.patch { color: #7c3aed; }
|
||||||
|
.note { font-size: 11px; color: #57606a; font-style: normal; margin-top: 6px; }
|
||||||
|
.warn { font-size: 11px; color: #9a3412; font-style: normal; margin-top: 6px; }
|
||||||
|
.status-badge {
|
||||||
|
display: inline-block; font-size: 11px; font-weight: 600;
|
||||||
|
padding: 1px 7px; border-radius: 10px;
|
||||||
|
}
|
||||||
|
.status-live { background: #dcfce7; color: #166534; }
|
||||||
|
.status-partial { background: #ffedd5; color: #9a3412; }
|
||||||
|
.status-disabled { background: #fee2e2; color: #991b1b; }
|
||||||
|
.status-internal { background: #f1f5f9; color: #475569; border: 1px solid #e2e8f0; }
|
||||||
|
.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-right: 18px; padding-left: 0; }
|
||||||
|
.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; }
|
||||||
|
.flow-box {
|
||||||
|
background: #ffffff; border: 1px solid #e5e7eb; border-radius: 4px;
|
||||||
|
padding: 10px 14px; font-size: 12px; margin-top: 8px;
|
||||||
|
}
|
||||||
|
.flow-step {
|
||||||
|
display: flex; gap: 10px; align-items: flex-start; margin-bottom: 6px;
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
.flow-num {
|
||||||
|
flex-shrink: 0; width: 20px; height: 20px; border-radius: 50%;
|
||||||
|
background: #3b82d4; color: #fff; font-size: 11px; font-weight: 700;
|
||||||
|
display: flex; align-items: center; justify-content: center;
|
||||||
|
}
|
||||||
|
.flow-text { flex: 1; padding-top: 2px; }
|
||||||
|
.decision-tree {
|
||||||
|
font-size: 12px; background: #ffffff;
|
||||||
|
border: 1px solid #e5e7eb; border-radius: 4px; padding: 12px 16px;
|
||||||
|
margin-top: 8px; line-height: 1.9;
|
||||||
|
}
|
||||||
|
.decision-tree ul { padding-right: 20px; padding-left: 0; }
|
||||||
|
.decision-tree li { margin-bottom: 2px; }
|
||||||
|
.env-table th:last-child { width: 220px; }
|
||||||
|
pre {
|
||||||
|
font-family: monospace; font-size: 11px;
|
||||||
|
background: #f1f5f9; border: 1px solid #e5e7eb;
|
||||||
|
border-radius: 4px; padding: 10px 12px;
|
||||||
|
white-space: pre-wrap; word-break: break-all;
|
||||||
|
margin-top: 6px; color: #1f2328;
|
||||||
|
direction: ltr; unicode-bidi: embed;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="max-wrap">
|
||||||
|
<h1>مرجع یکپارچهسازیهای خارجی</h1>
|
||||||
|
<p class="subtitle">
|
||||||
|
تمام یکپارچهسازیهای خروجی: کاربرد، زمان فعالشدن، نحوه احراز هویت،
|
||||||
|
رفتار retry، fallbackها و تمام متغیرهای محیطی. سرویسهای داخلی
|
||||||
|
(کپچا، دادههای پرسوجوی آفلاین) برای کاملبودن گنجانده شدهاند.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- TOC -->
|
||||||
|
<div class="toc">
|
||||||
|
<div class="toc-title">فهرست</div>
|
||||||
|
<ol>
|
||||||
|
<li><a href="#inquiry-routing">درخت تصمیم مسیریابی پرسوجو</a></li>
|
||||||
|
<li><a href="#fanavaran">فناوران — پلتفرم خسارت بیمه</a></li>
|
||||||
|
<li><a href="#sanhub">SandHub — درگاه پرسوجوی قدیمی</a></li>
|
||||||
|
<li><a href="#tejarat">پرسوجوی تجارت — درگاه block-inquiry (V2+)</a></li>
|
||||||
|
<li><a href="#esg">ESG — ارائهدهنده پرسوجوی تنانت پارسیان</a></li>
|
||||||
|
<li><a href="#sms">پیامک — درگاههای کاوهنگار و پارسیان</a></li>
|
||||||
|
<li><a href="#ai">سرویس هوش مصنوعی — تشخیص خسارت خودرو</a></li>
|
||||||
|
<li><a href="#car-pricing">سرویس قیمت خودرو — جستجوی ارزش بازار</a></li>
|
||||||
|
<li><a href="#offline-inquiry">پرسوجوی آفلاین — دادههای fallback</a></li>
|
||||||
|
<li><a href="#env-ref">مرجع متغیرهای محیطی</a></li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||||
|
<h2 id="inquiry-routing">۱ — درخت تصمیم مسیریابی پرسوجو</h2>
|
||||||
|
<p class="section-intro">
|
||||||
|
هر فایل تقصیر با فراخوانی "run-inquiries" آغاز میشود که بیمهنامه طرف مقصر
|
||||||
|
را از یک ارائهدهنده خارجی دریافت میکند. اینکه کدام ارائهدهنده واقعاً فراخوانی
|
||||||
|
میشود به سه عامل بستگی دارد: تنانت (<code>CLIENT_ID</code>)، نوع فایل
|
||||||
|
(THIRD_PARTY در مقابل CAR_BODY) و اینکه آیا حالت API زنده در تنظیمات سیستم
|
||||||
|
فعال است یا خیر. لایه دادههای پرسوجوی آفلاین در جلوی هر سه ارائهدهنده قرار دارد.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="card card-indigo">
|
||||||
|
<h3>انتخاب ارائهدهنده</h3>
|
||||||
|
<div class="decision-tree">
|
||||||
|
<strong>برای هر پرسوجوی مبتنی بر پلاک:</strong>
|
||||||
|
<ul>
|
||||||
|
<li>۱. بررسی دادههای آفلاین (MongoDB) — اگر داده مطابق یافت شد، آن را برگردانده و تمام HTTP را رد کن.</li>
|
||||||
|
<li>۲. اگر <code>CLIENT_ID=8</code> (تنانت پارسیان/ESG) → مسیریابی به <strong>ESG</strong> <code>/inquiry/policyByPlate</code> یا <code>/inquiry/policyByChassis</code>.</li>
|
||||||
|
<li>۳. در غیر این صورت → مسیریابی به <strong>پرسوجوی تجارت</strong> <code>/block-inquiry-tejarat</code> (THIRD_PARTY) یا <code>/block-inquiry-tejarat/badane</code> (CAR_BODY).</li>
|
||||||
|
<li>۴. اگر <code>system_settings.externalApis.sandHubUseLiveApi = false</code> (پیشفرض) → پاسخ mock برگردانده شود به جای انجام فراخوانیهای HTTP.</li>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
<strong>برای بررسیهای هویت شخصی، گواهینامه، مالکیت و شبا:</strong>
|
||||||
|
<ul>
|
||||||
|
<li>اگر <code>CLIENT_ID=8</code> → ESG <code>/inquiry/person</code> و <code>/inquiry/sheba</code>.</li>
|
||||||
|
<li>در غیر این صورت → تجارت/SandHub <code>/personal-inquiry/tejarat-no</code>، <code>/driver-license-check</code>، <code>/ownership</code>، <code>/sheba/sheba-tejaratno</code>.</li>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
<strong>تفاوت کلیدی — فرمت تاریخ تولد:</strong>
|
||||||
|
SandHub/تجارت تاریخ تولد <em>میلادی</em> انتظار دارند (داخلی از جلالی تبدیل میشود).
|
||||||
|
ESG مستقیماً تاریخ <em>جلالی</em> انتظار دارد.
|
||||||
|
</div>
|
||||||
|
<p class="note" style="margin-top:8px;">
|
||||||
|
اندپوینتهای SandHub فقط در مسیرهای قدیمی کد استفاده میشوند. تمام جریانهای فعال تقصیر V2+ از طریق ارائهدهندگان تجارت یا ESG میروند.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||||
|
<h2 id="fanavaran">۲ — فناوران <span class="status-badge status-live">فعال</span></h2>
|
||||||
|
<p class="section-intro">
|
||||||
|
فناوران (<code>apimanager.iraneit.com</code>) پلتفرم ملی پرونده خسارت بیمه است.
|
||||||
|
پس از اینکه کارشناس خسارت ارزیابی خود را ارسال میکند، سیستم بهصورت خودکار
|
||||||
|
یک خسارت ساختاریافته را از طریق یک پروتکل چهار مرحلهای به فناوران ارسال میکند.
|
||||||
|
فناوران همچنین بهعنوان منبع جستجوی code-listها (انواع تصادف، اجزای خودرو،
|
||||||
|
کدهای شهر و غیره) در سراسر پلتفرم عمل میکند.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="card card-blue">
|
||||||
|
<h3>چرخه حیات احراز هویت</h3>
|
||||||
|
<div class="flow-box">
|
||||||
|
<div class="flow-step"><div class="flow-num">۱</div><div class="flow-text"><strong>GET AppToken</strong> — <code>POST /EITAuthentication/GetAppToken</code> با هدرهای <code>appname</code> + <code>secret</code>. هدر <code>apptoken</code> را برمیگرداند.</div></div>
|
||||||
|
<div class="flow-step"><div class="flow-num">۲</div><div class="flow-text"><strong>Login</strong> — <code>POST /EITAuthentication/Login</code> با هدرهای <code>appToken</code> + <code>userName</code> + <code>password</code>. هدر <code>authenticationToken</code> را برمیگرداند.</div></div>
|
||||||
|
<div class="flow-step"><div class="flow-num">۳</div><div class="flow-text"><strong>Cache</strong> — توکن در حافظه <em>و</em> پایدار در MongoDB (<code>fanavaran_auth_tokens</code>) ذخیره میشود. تا نیمهشب <strong>Asia/Tehran</strong> معتبر است — اولین فراخوانی پس از ۰۰:۰۰ یک توکن تازه دریافت میکند.</div></div>
|
||||||
|
<div class="flow-step"><div class="flow-num">۴</div><div class="flow-text"><strong>تمام فراخوانیهای بعدی</strong> چهار هدر شامل میشوند: <code>authenticationToken</code>، <code>CorpId</code>، <code>ContractId</code>، <code>Location</code> — مختص تنانت، hardcoded به ازای هر کلید <code>FANAVARAN_CLIENT</code>.</div></div>
|
||||||
|
</div>
|
||||||
|
<p class="note" style="margin-top:8px;">
|
||||||
|
یک اثر انگشت پیکربندی (هش appName + secret + username + password + corpId + contractId + location)
|
||||||
|
یک ورود تازه را زمانی که هر مدرکی تغییر کند، حتی قبل از نیمهشب، مجبور میکند.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-blue">
|
||||||
|
<h3>پروتکل ارسال خسارت (۴ مرحله)</h3>
|
||||||
|
<div class="flow-box">
|
||||||
|
<div class="flow-step"><div class="flow-num">۱</div><div class="flow-text"><strong>خسارت پایه (GEN.03)</strong> — <code>POST /car/third-party-car-financial-claims</code>. دادههای مالک، راننده، بیمه، وسیله نقلیه و تصادف را ارسال میکند. یک <code>claimId</code> و <code>claimNo</code> فناوران برمیگرداند. پیامک با هر دو شناسه برای مالک ارسال میشود.</div></div>
|
||||||
|
<div class="flow-step"><div class="flow-num">۲</div><div class="flow-text"><strong>موارد خسارت (GEN.05)</strong> — <code>POST /car/third-party-car-financial-claims/{claimId}/dmg-cases</code>. یک ورودی به ازای هر قطعه آسیبدیده با شناسه کامپوننت، شدت و قیمت. سقف: کل ≤ ۵۳،۰۰۰،۰۰۰ تومان.</div></div>
|
||||||
|
<div class="flow-step"><div class="flow-num">۳</div><div class="flow-text"><strong>پیوستها (GEN.07)</strong> — <code>POST /car/third-party-car-financial-claims/{claimId}/files</code>. اسناد، تصاویر car-capture و ویدیوها که با شناسه فایل ارجاع داده شدهاند.</div></div>
|
||||||
|
<div class="flow-step"><div class="flow-num">۴</div><div class="flow-text"><strong>کارشناسی (GEN.08)</strong> — <code>POST /car/third-party-car-financial-claims/{claimId}/expertise</code>. متادیتای ارزیابی کارشناس (نقش کارشناس، تاریخ، نتیجه). ارسال را نهایی میکند.</div></div>
|
||||||
|
</div>
|
||||||
|
<p class="note" style="margin-top:8px;">
|
||||||
|
هر چهار مرحله در مجموعه <code>fanavaran_audit_logs</code> با بدنه کامل درخواست/پاسخ، وضعیت HTTP، مدت زمان و کد ردیابی برای اشکالزدایی ثبت میشوند.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-blue">
|
||||||
|
<h3>اندپوینتهای Lookup</h3>
|
||||||
|
<p class="note">همه زیر <code>https://apimanager.iraneit.com/BimeApiManager/api/BimeApi/v2.0/</code>. نتایج روی دیسک (به ازای کلید مشتری) و در مجموعه MongoDB <code>lookups</code> کش میشوند. تنانت پارسیان قبل از درخواست API از DB میخواند؛ دیگران ابتدا به API میروند.</p>
|
||||||
|
<table>
|
||||||
|
<tr><th>کاربرد</th><th>مسیر</th></tr>
|
||||||
|
<tr><td>گزینههای dropdown برای accidentReason (نگاشت شده به شناسههای محلی)</td><td><code>/car/base-info/accident-causes</code></td></tr>
|
||||||
|
<tr><td>گزینههای accidentWay</td><td><code>/car/code-list/accident-report-type</code></td></tr>
|
||||||
|
<tr><td>طبقهبندی استفاده از وسیله نقلیه</td><td><code>/car/base-info/vehicle-use-types</code></td></tr>
|
||||||
|
<tr><td>روش پرداخت خسارت</td><td><code>/car/code-list/dmg-pay-method</code></td></tr>
|
||||||
|
<tr><td>گزینههای نوع گواهینامه</td><td><code>/car/base-info/driving-licence-types</code></td></tr>
|
||||||
|
<tr><td>طبقهبندی طرف مقصر</td><td><code>/car/code-list/accident-culprit-type</code></td></tr>
|
||||||
|
<tr><td>گزینههای محل بازرسی</td><td><code>/car/code-list/inspection-place</code></td></tr>
|
||||||
|
<tr><td>کدهای وضعیت کاهش قیمت</td><td><code>/car/code-list/drop-amount-status</code></td></tr>
|
||||||
|
<tr><td>کاتالوگ کامپوننت (نگاشت به قطعات بیرونی/داخلی)</td><td><code>/car/base-info/car-components</code></td></tr>
|
||||||
|
<tr><td>گزینههای شدت تصادف</td><td><code>/car/code-list/accident-level</code></td></tr>
|
||||||
|
<tr><td>تطبیق <code>INSURANCE_CORP_ID</code> ← corpId فناوران</td><td><code>/common/code-list/insurance-corp</code></td></tr>
|
||||||
|
<tr><td>انتخابگرهای شهر/استان</td><td><code>/common/base-info/cities</code>، <code>/common/base-info/Provinces</code></td></tr>
|
||||||
|
<tr><td>دریافت بیمهنامه کامل بر اساس شناسه پس از استعلام</td><td><code>/car/third-party-car-policies/{policyId}</code></td></tr>
|
||||||
|
<tr><td>جستجوی وسیله نقلیه بر اساس VIN</td><td><code>/car/vehicles/inquiry-by-vin?vin=…</code></td></tr>
|
||||||
|
<tr><td>فهرست بیمهنامهها برای یک کد ملی</td><td><code>/common/Policies/inquiry-my-policies</code></td></tr>
|
||||||
|
<tr><td>دریافت رکورد مشتری بر اساس شناسه</td><td><code>/common/customers/{customerId}</code></td></tr>
|
||||||
|
<tr><td>جستجوی طرف بر اساس کد ملی + تاریخ تولد</td><td><code>/common/parties/inquiry-by-unique-identifier</code></td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-blue">
|
||||||
|
<h3>مدیریت خطا و انعطافپذیری</h3>
|
||||||
|
<table>
|
||||||
|
<tr><th>توضیح</th><th>مکانیزم</th></tr>
|
||||||
|
<tr><td>۳ تلاش، ۵۰۰ ms ← ۱۰۰۰ ms backoff نمایی در تمام فراخوانیهای HTTP.</td><td>Retry</td></tr>
|
||||||
|
<tr><td>وقتی فناوران پیام فارسی "دوباره تلاش کنید" (یا tracking-code 500) برمیگرداند، یک مکث ۵ دقیقهای در سطح تنانت فعال میشود. تمام فراخوانیها در این پنجره بلافاصله <code>503 ServiceUnavailable</code> دریافت میکنند — بدون فشار.</td><td>Backoff گذرا</td></tr>
|
||||||
|
<tr><td>در ۴۰۱، توکن از حافظه و MongoDB پاک میشود؛ فراخوانی بعدی GetAppToken + Login تازه را فعال میکند.</td><td>ابطال توکن</td></tr>
|
||||||
|
<tr><td>درخواستهای همزمان ورود برای همان تنانت به یک Promise در حال پرواز جمع میشوند.</td><td>حذف تکراری Inflight</td></tr>
|
||||||
|
<tr><td>هر مرحله (GET_APP_TOKEN، LOGIN و هر چهار مرحله ارسال) در <code>fanavaran_audit_logs</code> با وضعیت STARTED / SUCCESS / FAILURE، هدرهای کامل، بدنه و مدت زمان نوشته میشود.</td><td>لاگ Audit</td></tr>
|
||||||
|
<tr><td>۲۰–۳۰ ثانیه به ازای هر فراخوانی HTTP.</td><td>Timeout</td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-blue">
|
||||||
|
<h3>پروفایلهای تنانت (<code>FANAVARAN_CLIENT</code>)</h3>
|
||||||
|
<p class="section-intro" style="margin-top:6px; margin-bottom:8px;">سه پروفایل تنانت از پیش تعیینشده وجود دارد. پروفایل فعال توسط متغیر محیطی <code>FANAVARAN_CLIENT</code> انتخاب میشود. هر پروفایل <code>appName</code>، <code>secret</code>، <code>username</code>، <code>password</code>، <code>CorpId</code>، <code>ContractId</code> و <code>Location</code> هدرهای خود را به علاوه پیشفرضهای payload (AccidentCityId و غیره) دارد.</p>
|
||||||
|
<table>
|
||||||
|
<tr><th>شرکت بیمه</th><th>کلید</th></tr>
|
||||||
|
<tr><td>بیمه پارسیان</td><td><code>parsian</code></td></tr>
|
||||||
|
<tr><td>بیمه تجارت نو</td><td><code>tejaratno</code></td></tr>
|
||||||
|
<tr><td>بیمه معلم</td><td><code>moallem</code></td></tr>
|
||||||
|
</table>
|
||||||
|
<p class="note" style="margin-top:8px;">
|
||||||
|
<code>INSURANCE_CORP_ID</code> یک رشته عنوان نمایشی است (مثلاً <em>"بیمه پارسیان"</em>) که در برابر فهرست زنده فناوران <code>insurance-corp</code> تطبیق داده میشود تا <code>corpId</code> عددی مورد استفاده در ارسالها را تولید کند. شناسه تطبیقیافته روی دیسک کش میشود.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||||
|
<h2 id="sanhub">۳ — SandHub <span class="status-badge status-partial">قدیمی</span></h2>
|
||||||
|
<p class="section-intro">
|
||||||
|
SandHub درگاه پرسوجوی اصلی است. هنوز در کدبیس حضور دارد اما تمام جریانهای
|
||||||
|
فعال تقصیر (V2+) به ارائهدهنده پرسوجوی تجارت منتقل شدهاند. اندپوینتهای
|
||||||
|
SandHub قابل فراخوانی هستند اما فقط از طریق مسیرهای قدیمی کد قابل دسترسی هستند.
|
||||||
|
حالت mock آن توسط همان تنظیم سیستم <code>sandHubUseLiveApi</code> کنترل میشود.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="card card-gray">
|
||||||
|
<h3>احراز هویت</h3>
|
||||||
|
<p class="note">
|
||||||
|
<code>POST {SANHUB_BASE_URL}/user/login</code> با بدنه JSON نام کاربری + رمز عبور.
|
||||||
|
توکن در حافظه برای <strong>۵۵ دقیقه</strong> کش میشود. در ۴۰۱، توکن پاک میشود و یک تلاش مجدد انجام میشود.
|
||||||
|
۳ تلاش با ۱۰۰۰ ms ← ۲۰۰۰ ms backoff نمایی.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-gray">
|
||||||
|
<h3>اندپوینتها</h3>
|
||||||
|
<table>
|
||||||
|
<tr><th style="width:70px">متد</th><th>مسیر</th><th>توضیح</th></tr>
|
||||||
|
<tr><td><span class="method post">POST</span></td><td><code>/block-inquiry-tejarat</code></td><td>پرسوجوی بیمهنامه مبتنی بر پلاک (THIRD_PARTY). بدنه: <code>leftTwoDigits</code>، <code>serialLetter</code>، <code>threeDigits</code>، <code>rightTwoDigits</code>، <code>nationalCode</code>.</td></tr>
|
||||||
|
<tr><td><span class="method post">POST</span></td><td><code>/block-inquiry-tejarat/badane</code></td><td>پرسوجوی بیمهنامه CAR_BODY. Timeout ۵۰ ثانیه (طولانیتر از استاندارد).</td></tr>
|
||||||
|
<tr><td><span class="method post">POST</span></td><td><code>/personal-inquiry/tejarat-no</code></td><td>بررسی هویت شخصی. بدنه: <code>nationalCode</code> + <code>birthDate</code> <em>میلادی</em> (داخلی از جلالی تبدیل میشود).</td></tr>
|
||||||
|
<tr><td><span class="method post">POST</span></td><td><code>/driver-license-check</code></td><td>اعتبارسنجی گواهینامه. پرچم <code>IsSucceed</code> را برمیگرداند.</td></tr>
|
||||||
|
<tr><td><span class="method post">POST</span></td><td><code>/ownership</code></td><td>بررسی مالکیت وسیله نقلیه. پرچم <code>IsSuccess</code> را برمیگرداند.</td></tr>
|
||||||
|
<tr><td><span class="method post">POST</span></td><td><code>/sheba/sheba-tejaratno</code></td><td>اعتبارسنجی شبا / حساب بانکی. <code>ReturnValue</code> + <code>HasError</code> را برمیگرداند.</td></tr>
|
||||||
|
</table>
|
||||||
|
<p class="note" style="margin-top:8px;">
|
||||||
|
تمام اندپوینتها پاسخهای mock کامل را زمانی که <code>sandHubUseLiveApi=false</code> در تنظیمات سیستم (پیشفرض) پشتیبانی میکنند. دادههای mock قطعی هستند و بهصورت محلی بدون هیچ فراخوانی HTTP تولید میشوند.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||||
|
<h2 id="tejarat">۴ — پرسوجوی تجارت <span class="status-badge status-live">فعال</span></h2>
|
||||||
|
<p class="section-intro">
|
||||||
|
درگاه فعال block-inquiry برای تمام تنانتهای غیر ESG. در هر فراخوانی V2+
|
||||||
|
<code>run-inquiries</code> که <code>CLIENT_ID ≠ 8</code> استفاده میشود.
|
||||||
|
URL پایه قابل پیکربندی است؛ در تولید به همان هاست SandHub اشاره میکند اما از
|
||||||
|
اعتبارنامههای جداگانه استفاده میکند.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="card card-teal">
|
||||||
|
<h3>احراز هویت</h3>
|
||||||
|
<p class="note">
|
||||||
|
<code>POST {TEJARAT_INQUIRY_BASE_URL}/user/login</code> با بدنه JSON ایمیل + رمز عبور.
|
||||||
|
توکن برای <strong>۵۵ دقیقه</strong> کش میشود. ۲ تلاش با ۵۰۰ ms ← ۱۰۰۰ ms backoff.
|
||||||
|
جدا از اعتبارنامههای SandHub — از <code>TEJARAT_INQUIRY_EMAIL</code> / <code>TEJARAT_INQUIRY_PASSWORD</code> استفاده میکند.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-teal">
|
||||||
|
<h3>اندپوینتها</h3>
|
||||||
|
<table>
|
||||||
|
<tr><th style="width:70px">متد</th><th>مسیر</th><th>توضیح</th></tr>
|
||||||
|
<tr><td><span class="method post">POST</span></td><td><code>/block-inquiry-tejarat</code></td><td>پرسوجوی پلاک THIRD_PARTY. بدنه: فیلدهای پلاک + <code>nationalCode</code>. ابتدا داده آفلاین بررسی میشود.</td></tr>
|
||||||
|
<tr><td><span class="method post">POST</span></td><td><code>/block-inquiry-tejarat/badane</code></td><td>پرسوجوی پلاک CAR_BODY. بدنه: <code>part1–part4</code> (عددی) + <code>nationalCode</code>. همیشه زنده میشود (mock برای مسیر badane وجود ندارد).</td></tr>
|
||||||
|
</table>
|
||||||
|
<p class="note" style="margin-top:8px;">
|
||||||
|
وقتی <code>sandHubUseLiveApi=false</code>، مسیر THIRD_PARTY یک پاسخ mock بدون HTTP برمیگرداند. مسیر CAR_BODY همیشه API زنده را صرفنظر از این پرچم فراخوانی میکند.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||||
|
<h2 id="esg">۵ — ESG <span class="status-badge status-live">فعال (CLIENT_ID=8)</span></h2>
|
||||||
|
<p class="section-intro">
|
||||||
|
ESG یک درگاه API بیمه داخلی است که منحصراً توسط تنانت پارسیان
|
||||||
|
(<code>CLIENT_ID=8</code>) استفاده میشود. برای تمام انواع پرسوجو زمانی که
|
||||||
|
این تنانت فعال است، جایگزین تجارت/SandHub میشود. شکل پاسخ متفاوتی دارد،
|
||||||
|
TTL توکن پویا دارد و تاریخ تولد را در فرمت <strong>جلالی</strong> انتظار دارد
|
||||||
|
(نه میلادی، برخلاف SandHub/تجارت).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="card card-purple">
|
||||||
|
<h3>احراز هویت</h3>
|
||||||
|
<p class="note">
|
||||||
|
<code>POST {ESG_URL}/auth/login</code> با بدنه JSON <code>{ username, password }</code>.
|
||||||
|
TTL توکن از فیلد <code>expiresIn</code> پاسخ خوانده میشود (پیشفرض ۱۴ دقیقه).
|
||||||
|
۲ تلاش با ۵۰۰ ms ← ۱۰۰۰ ms backoff. در ۴۰۱، توکن پاک و یک تلاش مجدد.
|
||||||
|
URL پیشفرض: <code>http://192.168.20.22:8085</code> (شبکه داخلی).
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-purple">
|
||||||
|
<h3>اندپوینتها</h3>
|
||||||
|
<table>
|
||||||
|
<tr><th style="width:70px">متد</th><th>مسیر</th><th>توضیح</th></tr>
|
||||||
|
<tr><td><span class="method post">POST</span></td><td><code>/inquiry/policyByPlate</code></td><td>جستجوی بیمهنامه مبتنی بر پلاک (THIRD_PARTY). بدنه: <code>nationalCode</code>، <code>plk1–plk4</code>. پاسخ قبل از ذخیره به فرمت قدیمی تجارت نگاشت میشود.</td></tr>
|
||||||
|
<tr><td><span class="method post">POST</span></td><td><code>/inquiry/policyByChassis</code></td><td>جایگزین مبتنی بر VIN/شاسی برای پرسوجوی پلاک. توسط اندپوینتهای <code>run-inquiries-vin</code> فراخوانی میشود. از جستجوی شاسی ESG استفاده میکند (نه مسیر SandHub). بدنه: <code>nationalCode</code>، <code>chassis</code>.</td></tr>
|
||||||
|
<tr><td><span class="method post">POST</span></td><td><code>/inquiry/person</code></td><td>بررسی هویت شخصی. بدنه: <code>nationalCode</code>، <code>birthDate</code> (جلالی، نه میلادی).</td></tr>
|
||||||
|
<tr><td><span class="method post">POST</span></td><td><code>/inquiry/sheba</code></td><td>اعتبارسنجی شبا / حساب بانکی.</td></tr>
|
||||||
|
</table>
|
||||||
|
<p class="note" style="margin-top:8px;">
|
||||||
|
ESG هر پاسخ را به صورت <code>{ success: boolean, data: … }</code> میپیچد. یک بدنه <code>success=false</code> به یک خطای فارسی "استعلام در دسترس نیست" ترجمه میشود.
|
||||||
|
بررسی داده آفلاین-پرسوجو هنوز ابتدا اجرا میشود، قبل از هر فراخوانی HTTP ESG.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||||
|
<h2 id="sms">۶ — پیامک <span class="status-badge status-live">فعال</span></h2>
|
||||||
|
<p class="section-intro">
|
||||||
|
دو ارائهدهنده پیامک پشتیبانی میشوند: <strong>کاوهنگار</strong> (پیشفرض)
|
||||||
|
و <strong>درگاه پیامک پارسیان</strong>. ارائهدهنده فعال توسط متغیر محیطی
|
||||||
|
<code>SMS_PROVIDER</code> (یا <code>SMS</code>) انتخاب میشود. هر دو ارائهدهنده
|
||||||
|
رابط درگاه داخلی یکسانی را پیادهسازی میکنند بنابراین لایه ارکستراسیون
|
||||||
|
مستقل از ارائهدهنده است.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="card card-green">
|
||||||
|
<h3>انتخاب ارائهدهنده</h3>
|
||||||
|
<table>
|
||||||
|
<tr><th>ارائهدهنده فعال</th><th>مقدار</th><th>متغیر محیطی</th></tr>
|
||||||
|
<tr><td>کاوهنگار — <code>api.kavenegar.com</code></td><td><code>kavenegar</code> (پیشفرض)</td><td><code>SMS_PROVIDER</code> (یا <code>SMS</code>)</td></tr>
|
||||||
|
<tr><td>درگاه پیامک پارسیان — <code>PARSIAN_SMS_URL</code></td><td><code>parsian</code></td><td><code>SMS_PROVIDER</code> (یا <code>SMS</code>)</td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-green">
|
||||||
|
<h3>اندپوینتهای کاوهنگار</h3>
|
||||||
|
<p class="note">URL پایه: <code>https://api.kavenegar.com/v1/{SMS_API_KEY}/</code></p>
|
||||||
|
<table>
|
||||||
|
<tr><th style="width:70px">متد</th><th>مسیر</th><th>زمان استفاده</th></tr>
|
||||||
|
<tr><td><span class="method post">POST</span></td><td><code>sms/send.json</code></td><td>پیامهای متن ساده (مثلاً متنهای اطلاعرسانی مبتنی بر کلید ذخیرهشده در مجموعه <code>sms_texts</code>).</td></tr>
|
||||||
|
<tr><td><span class="method get">GET</span></td><td><code>verify/lookup.json</code></td><td>تمام پیامهای مبتنی بر قالب (OTPها، لینکهای دعوت، اطلاعرسانی کارشناس). پارامترها: <code>receptor</code>، <code>token</code>[، <code>token2</code>، <code>token3</code>، <code>token10</code>]، <code>template</code>.</td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-green">
|
||||||
|
<h3>درگاه پیامک پارسیان</h3>
|
||||||
|
<p class="note">URL پایه از <code>PARSIAN_SMS_URL</code>. احراز هویت: هدر <code>X-PACKAGE-API-KEY</code> + <code>Authorization: Basic {PARSIAN_BASIC_TOKEN}</code>. بهصورت GET با پارامترهای URL-encoded <code>ReceiverNumbers</code> و <code>Message</code> ارسال میکند. پیامهای قالب قبل از ارسال به یک بدنه متن ساده پیشرندر میشوند (معادل verify/lookup ندارد).</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-green">
|
||||||
|
<h3>قالبهای پیامک در حال استفاده</h3>
|
||||||
|
<table>
|
||||||
|
<tr><th>توکنها</th><th>ماشه</th><th>نام قالب</th></tr>
|
||||||
|
<tr><td><code>token</code> = کد OTP</td><td>ورود OTP کاربر / اکتور، فراموشی رمز، OTPهای طرف</td><td><code>AUTH_SMS_TEMPLATE</code> (محیطی)</td></tr>
|
||||||
|
<tr><td><code>token</code> = publicId، <code>token2</code> = لینک</td><td>طرف دوم لینک دعوت تقصیر را از طریق پیامک دریافت میکند</td><td><code>yara724-invite-link</code></td></tr>
|
||||||
|
<tr><td><code>token</code> = نوع فایل، <code>token2</code> = نام خانوادگی کارشناس، <code>token3</code> = لینک</td><td>کارشناس میدانی لینک را برای یک طرف ارسال میکند</td><td><code>yara-field-expert-link</code></td></tr>
|
||||||
|
<tr><td><code>token</code> = publicId، <code>token2</code> = لینک</td><td>اطلاع به طرف که طرف دیگر با رأی کارشناس موافقت کرده است</td><td><code>yara-blame-agreement</code></td></tr>
|
||||||
|
<tr><td><code>token</code> = publicId، <code>token2</code> = لینک</td><td>طرف زیاندیده مطلع میشود که جریان خسارت را پس از تکمیل تقصیر باز کند</td><td><code>yara-claim-link</code></td></tr>
|
||||||
|
<tr><td><code>token</code> = "تصادف"/"خسارت"، <code>token2</code> = publicId، <code>token3</code> = نام خانوادگی کارشناس</td><td>کارشناس یک فایل تقصیر یا خسارت را قفل میکند</td><td><code>yara-expert-lock</code></td></tr>
|
||||||
|
<tr><td><code>token</code> = نوع فایل، <code>token2</code> = publicId، <code>token3</code> = لینک</td><td>کارشناس درخواست ارسال مجدد اسناد میدهد</td><td><code>yara-resend-documents</code></td></tr>
|
||||||
|
<tr><td><code>token</code> = نوع فایل، <code>token2</code> = publicId، <code>token3</code> = نام خانوادگی کارشناس، <code>token10</code> = لینک</td><td>طرف مطلع میشود که ارزیابی خسارت کارشناس را امضا کند</td><td><code>yara-signature</code></td></tr>
|
||||||
|
<tr><td><code>token</code> = publicId، <code>token2</code> = claimId فناوران، <code>token3</code> = claimNo فناوران</td><td>ارسال فناوران تأیید شد — با شماره و شناسه خسارت فناوران برای مالک خسارت ارسال میشود</td><td><code>yara-fanavaran-claim</code></td></tr>
|
||||||
|
</table>
|
||||||
|
<p class="note" style="margin-top:8px;">
|
||||||
|
تمام فراخوانیهای پیامک fire-and-forget هستند — هرگز throw نمیکنند. شکستها log میشوند اما جریان اصلی را مسدود نمیکنند.
|
||||||
|
یک مجموعه MongoDB <code>sms_send_logs</code> هر پیام خروجی را با نوع آن (OTP در مقابل TEMPLATE)، ارائهدهنده، نام قالب و وضعیت موفقیت/شکست ثبت میکند.
|
||||||
|
پیامهای متنی اطلاعرسانی (اختلاف طرفین، امضای یک طرف و غیره) در راهاندازی در مجموعه <code>sms_texts</code> seed میشوند و در زمان اجرا قابل ویرایش هستند.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||||
|
<h2 id="ai">۷ — سرویس هوش مصنوعی <span class="status-badge status-disabled">غیرفعال (کد موجود)</span></h2>
|
||||||
|
<p class="section-intro">
|
||||||
|
یک سرویس تشخیص خسارت خودرو مبتنی بر تصویر در کدبیس یکپارچهسازی شده است اما
|
||||||
|
فراخوانیهای HTTP آن <strong>کاملاً comment شدهاند</strong>. ماژول در راهاندازی
|
||||||
|
مقداردهی اولیه میشود، تلاش برای ورود میکند (در صورت شکست به صورت خاموش
|
||||||
|
بلعیده میشود)، و یک متد <code>aiRequestImage</code> را expose میکند — اما
|
||||||
|
فراخوانیهای axios زیرین غیرفعال هستند. سرویس هیچ جریان تولیدی را تحت تأثیر
|
||||||
|
قرار نمیدهد.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="card card-yellow">
|
||||||
|
<h3>رابط مورد نظر (زمانی که دوباره فعال شود)</h3>
|
||||||
|
<table>
|
||||||
|
<tr><th style="width:70px">متد</th><th>مسیر</th><th>توضیح</th></tr>
|
||||||
|
<tr><td><span class="method post">POST</span></td><td><code>{AI_URL_V2}/auth/login</code></td><td>احراز هویت با نام کاربری + رمز عبور. <code>accessToken</code> را برمیگرداند.</td></tr>
|
||||||
|
<tr><td><span class="method get">GET</span></td><td><code>{AI_URL_V2}/auth/profile</code></td><td>دریافت <code>apiKey.key</code> مورد نیاز بهعنوان هدر درخواست <code>gateway-api-key</code>.</td></tr>
|
||||||
|
<tr><td><span class="method post">POST</span></td><td><code>{AI_URL_V2}/services/car-damage/detector?version=ai-v7</code></td><td>ارسال تصویر قطعه خودرو (multipart). <code>downloadLink</code> با نتیجه حاشیهنویسیشده را برمیگرداند.</td></tr>
|
||||||
|
</table>
|
||||||
|
<p class="warn" style="margin-top:8px;">
|
||||||
|
وضعیت: هر سه فراخوانی در بلوکهای <code>axios.request(…)</code> comment-شده پیچیده شدهاند.
|
||||||
|
<code>CW_URL</code> در <code>.env.example</code> نیست. برای فعالسازی مجدد، فراخوانیهای axios login، getApiKey و aiRequestImage را uncomment کنید و <code>AI_URL_V2</code>، <code>AI_USERNAME</code>، <code>AI_PASSWORD</code> را پیکربندی کنید.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||||
|
<h2 id="car-pricing">۸ — سرویس قیمت خودرو <span class="status-badge status-partial">نیمهفعال</span></h2>
|
||||||
|
<p class="section-intro">
|
||||||
|
فقط در طول محاسبه کاهش قیمت کارشناس-خسارت استفاده میشود. وقتی یک کارشناس
|
||||||
|
مقادیر شدت برای هر قطعه ارائه میدهد، سیستم قیمتهای بازار بلادرنگ برای مدل
|
||||||
|
خودروی آسیبدیده را دریافت میکند، سپس کاهش قیمت را با استفاده از فرمول
|
||||||
|
محاسبه میکند: <strong>قیمت خودرو × ضریب سال × مجموع ضرایب قطعات ÷ ۴۰۰</strong>.
|
||||||
|
سرویس دو منبع داده (اندپوینت) دارد که بهصورت موازی امتحان میشوند.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="card card-orange">
|
||||||
|
<h3>اندپوینتها</h3>
|
||||||
|
<table>
|
||||||
|
<tr><th style="width:70px">متد</th><th>مسیر</th><th>توضیح</th></tr>
|
||||||
|
<tr><td><span class="method get">GET</span></td><td><code>{CW_URL}price?akharin</code></td><td>دریافت قیمتهای بازار خودرو از منبع "آخرین". آرایه <code>{ carName, marketPrice }</code> را برمیگرداند.</td></tr>
|
||||||
|
<tr><td><span class="method get">GET</span></td><td><code>{CW_URL}price?hamrah</code></td><td>دریافت قیمتهای بازار خودرو از منبع "همراه". همان شکل پاسخ.</td></tr>
|
||||||
|
</table>
|
||||||
|
<p class="note" style="margin-top:8px;">
|
||||||
|
هر دو اندپوینت امتحان میشوند؛ نتایج ادغام و حذف تکراری میشوند. بهترین تطابق برای
|
||||||
|
نام خودروی آسیبدیده با استفاده از <strong>فاصله Levenshtein</strong> (تطابق رشته فازی) پیدا میشود.
|
||||||
|
اگر هر دو اندپوینت شکست بخورند یا خالی برگردانند، محاسبه کاهش قیمت رد میشود (ناقص علامتگذاری میشود) — ارسال خسارت را مسدود نمیکند.
|
||||||
|
</p>
|
||||||
|
<p class="warn" style="margin-top:6px;">
|
||||||
|
<strong><code>CW_URL</code> در <code>.env.example</code> مستندسازی نشده است.</strong>
|
||||||
|
این سرویس در صورت تنظیم نشدن متغیر، بهصورت خاموش هیچ کاهش قیمتی تولید نخواهد کرد.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||||
|
<h2 id="offline-inquiry">۹ — پرسوجوی آفلاین <span class="status-badge status-internal">داخلی / fallback</span></h2>
|
||||||
|
<p class="section-intro">
|
||||||
|
لایه پرسوجوی آفلاین فراخوانیهای پرسوجوی مبتنی بر پلاک را قبل از اینکه هر
|
||||||
|
HTTP خارجی انجام شود رهگیری میکند. عمدتاً برای توسعه و تست (پلاکهای شناختهشده
|
||||||
|
از پیش seed شده) استفاده میشود اما همچنین بهعنوان fallback انعطافپذیری
|
||||||
|
زمانی که سرویسهای پرسوجوی زنده در دسترس نیستند عمل میکند. توسط یک پرچم
|
||||||
|
پایگاهداده زمان اجرا کنترل میشود، نه یک متغیر محیطی.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="card card-gray">
|
||||||
|
<h3>نحوه کار</h3>
|
||||||
|
<table>
|
||||||
|
<tr><th>جزئیات</th><th>جنبه</th></tr>
|
||||||
|
<tr><td>مجموعه MongoDB <code>offline-inquiries</code>. اسناد شامل <code>clientKey</code>، فیلدهای نرمالشده پلاک، <code>nationalCode</code> و پاسخ از پیش ساختهشده <code>raw</code> + <code>mapped</code> برای برگرداندن هستند.</td><td>ذخیرهسازی</td></tr>
|
||||||
|
<tr><td><code>system_settings.offlineInquiry.enabled</code> — پیشفرض <code>true</code>. تغییر از طریق <code>PATCH /super-admin/system-settings/offline-inquiry</code>.</td><td>سوئیچ اصلی</td></tr>
|
||||||
|
<tr><td>پلاک نرمالشده (فقط ارقام، عربی→فارسی) + کد ملی + کلید مشتری فناوران باید همه مطابقت داشته باشند. اگر پیدا شد، بلافاصله برگردانده میشود؛ هیچ فراخوانی HTTP انجام نمیشود.</td><td>ترتیب جستجو</td></tr>
|
||||||
|
<tr><td>فقط برای پرسوجوی block مبتنی بر پلاک (THIRD_PARTY) اعمال میشود. پرسوجوی CAR_BODY (<code>/badane</code>) همیشه API زنده را میزند.</td><td>محدوده</td></tr>
|
||||||
|
<tr><td><code>system_settings.externalApis.sandHubUseLiveApi</code> — وقتی <code>false</code> (پیشفرض)، حتی اگر هیچ داده آفلاینی مطابقت نداشته باشد، یک پاسخ mock داخلی برگردانده میشود به جای فراخوانی تجارت/ESG.</td><td>پرچم API زنده</td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||||
|
<h2 id="env-ref">۱۰ — مرجع متغیرهای محیطی</h2>
|
||||||
|
<p class="section-intro">
|
||||||
|
تمام متغیرهای محیطی در سراسر تمام یکپارچهسازیها، گروهبندیشده بر اساس سرویس.
|
||||||
|
متغیرهای علامتگذاریشده با <strong>*</strong> در <code>.env.example</code> وجود ندارند.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="card card-blue">
|
||||||
|
<h3>فناوران</h3>
|
||||||
|
<table class="env-table">
|
||||||
|
<tr><th>شرح</th><th>متغیر</th></tr>
|
||||||
|
<tr><td>کلید پروفایل تنانت فعال: <code>parsian</code> | <code>tejaratno</code> | <code>moallem</code></td><td><code>FANAVARAN_CLIENT</code></td></tr>
|
||||||
|
<tr><td>عنوان نمایشی شرکت بیمهگر (مثلاً <em>"بیمه پارسیان"</em>) — در راهاندازی در برابر فهرست insurance-corp فناوران به یک corpId عددی تطبیق داده میشود.</td><td><code>INSURANCE_CORP_ID</code></td></tr>
|
||||||
|
</table>
|
||||||
|
<p class="note" style="margin-top:8px;">اعتبارنامههای هر تنانت (appName، secret، username، password، CorpId، ContractId، Location) در <code>src/core/config/fanavaran-client.config.ts</code> زیر <code>SEED_FANAVARAN_CLIENT_PROFILES</code> hardcoded شدهاند.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-gray">
|
||||||
|
<h3>SandHub (قدیمی)</h3>
|
||||||
|
<table class="env-table">
|
||||||
|
<tr><th>شرح</th><th>متغیر</th></tr>
|
||||||
|
<tr><td>URL پایه برای SandHub. پیشفرض: <code>http://82.99.202.245:3027</code></td><td><code>SANHUB_BASE_URL</code></td></tr>
|
||||||
|
<tr><td>URL کامل ورود (معمولاً base + <code>/user/login</code>)</td><td><code>SANHUB_URL_LOGIN</code></td></tr>
|
||||||
|
<tr><td>ایمیل ورود SandHub</td><td><code>SANHUB_USERNAME</code></td></tr>
|
||||||
|
<tr><td>رمز عبور ورود SandHub</td><td><code>SANHUB_PASSWORD</code></td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-teal">
|
||||||
|
<h3>پرسوجوی تجارت</h3>
|
||||||
|
<table class="env-table">
|
||||||
|
<tr><th>شرح</th><th>متغیر</th></tr>
|
||||||
|
<tr><td>URL پایه. پیشفرض: <code>http://82.99.202.245:3027</code></td><td><code>TEJARAT_INQUIRY_BASE_URL</code></td></tr>
|
||||||
|
<tr><td>ایمیل ورود</td><td><code>TEJARAT_INQUIRY_EMAIL</code></td></tr>
|
||||||
|
<tr><td>رمز عبور ورود</td><td><code>TEJARAT_INQUIRY_PASSWORD</code></td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-purple">
|
||||||
|
<h3>ESG (فقط CLIENT_ID=8)</h3>
|
||||||
|
<table class="env-table">
|
||||||
|
<tr><th>شرح</th><th>متغیر</th></tr>
|
||||||
|
<tr><td>به <code>8</code> تنظیم کنید تا ارائهدهنده پرسوجوی ESG برای تنانت پارسیان فعال شود.</td><td><code>CLIENT_ID</code></td></tr>
|
||||||
|
<tr><td>URL پایه ESG. پیشفرض: <code>http://192.168.20.22:8085</code> (شبکه داخلی)</td><td><code>ESG_URL</code></td></tr>
|
||||||
|
<tr><td>نام کاربری ورود ESG</td><td><code>ESG_USERNAME</code></td></tr>
|
||||||
|
<tr><td>رمز عبور ورود ESG</td><td><code>ESG_PASSWORD</code></td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-green">
|
||||||
|
<h3>پیامک</h3>
|
||||||
|
<table class="env-table">
|
||||||
|
<tr><th>شرح</th><th>متغیر</th></tr>
|
||||||
|
<tr><td><code>kavenegar</code> (پیشفرض) یا <code>parsian</code></td><td><code>SMS_PROVIDER</code> (یا <code>SMS</code>)</td></tr>
|
||||||
|
<tr><td>کلید API کاوهنگار (الزامی وقتی provider = kavenegar)</td><td><code>SMS_API_KEY</code></td></tr>
|
||||||
|
<tr><td>نام قالب کاوهنگار برای پیامهای OTP (مثلاً <code>yara-otp</code>)</td><td><code>AUTH_SMS_TEMPLATE</code></td></tr>
|
||||||
|
<tr><td>URL پایه درگاه پیامک پارسیان (الزامی وقتی provider = parsian)</td><td><code>PARSIAN_SMS_URL</code></td></tr>
|
||||||
|
<tr><td>مقدار هدر پیامک پارسیان <code>X-PACKAGE-API-KEY</code></td><td><code>PARSIAN_API_KEY</code></td></tr>
|
||||||
|
<tr><td>اعتبارنامههای رمزگذاریشده Base64 برای هدر <code>Authorization: Basic …</code></td><td><code>PARSIAN_BASIC_TOKEN</code></td></tr>
|
||||||
|
<tr><td>URL پایه فرانتاند — برای ساخت تمام لینکهای دعوت + خسارت تعبیهشده در پیامهای پیامک استفاده میشود</td><td><code>URL</code></td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-yellow">
|
||||||
|
<h3>سرویس هوش مصنوعی</h3>
|
||||||
|
<table class="env-table">
|
||||||
|
<tr><th>شرح</th><th>متغیر</th></tr>
|
||||||
|
<tr><td>URL پایه درگاه هوش مصنوعی. پیشفرض: <code>https://ai-gw.ittalie.ir</code> (استفاده نشده — سرویس غیرفعال است)</td><td><code>AI_URL_V2</code></td></tr>
|
||||||
|
<tr><td>نام کاربری ورود سرویس هوش مصنوعی (استفاده نشده)</td><td><code>AI_USERNAME</code></td></tr>
|
||||||
|
<tr><td>رمز عبور ورود سرویس هوش مصنوعی (استفاده نشده)</td><td><code>AI_PASSWORD</code></td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-orange">
|
||||||
|
<h3>سرویس قیمت خودرو</h3>
|
||||||
|
<table class="env-table">
|
||||||
|
<tr><th>شرح</th><th>متغیر</th></tr>
|
||||||
|
<tr><td>URL پایه برای API قیمت بازار خودرو (مثلاً <code>https://…/</code>). در <code>.env.example</code> نیست. کاهش قیمت بهصورت خاموش رد میشود اگر تنظیم نشده باشد.</td><td><code>CW_URL</code> *</td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card-gray">
|
||||||
|
<h3>عمومی / برنامه</h3>
|
||||||
|
<table class="env-table">
|
||||||
|
<tr><th>شرح</th><th>متغیر</th></tr>
|
||||||
|
<tr><td>پورت HTTP (پیشفرض ۳۰۰۰). توسط fallback insurance-corp فناوران برای فراخوانی اندپوینت جستجوی محلی خودش استفاده میشود.</td><td><code>PORT</code></td></tr>
|
||||||
|
<tr><td><code>true</code> / <code>false</code> — چالش کپچای ورود را فعال/غیرفعال میکند. داخلی، بدون سرویس خارجی.</td><td><code>CAPTCHA_ENABLED</code></td></tr>
|
||||||
|
<tr><td>TTL چالش کپچا به دقیقه.</td><td><code>EXP_CAPTCHA_TIME</code></td></tr>
|
||||||
|
<tr><td>TTL کد یکبار مصرف به دقیقه.</td><td><code>EXP_OTP_TIME</code></td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer>Made by Sepehr</footer>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -10797,16 +10797,41 @@ export class ClaimRequestManagementService {
|
|||||||
}
|
}
|
||||||
claims = [...byId.values()];
|
claims = [...byId.values()];
|
||||||
}
|
}
|
||||||
const list = (claims as any[]).map((c) => ({
|
const blameIdsForList = [
|
||||||
claimRequestId: c._id.toString(),
|
...new Set(
|
||||||
publicId: c.publicId,
|
(claims as any[])
|
||||||
requestNo: c.requestNo,
|
.map((c) => c.blameRequestId?.toString())
|
||||||
status: c.status,
|
.filter((id): id is string => !!id),
|
||||||
claimStatus: c.claimStatus || "PENDING",
|
),
|
||||||
currentStep: c.workflow?.currentStep || "",
|
];
|
||||||
createdAt: c.createdAt,
|
const blamesForList =
|
||||||
blameRequestId: c.blameRequestId?.toString(),
|
blameIdsForList.length > 0
|
||||||
})) as ClaimListItemV2Dto[];
|
? ((await this.blameRequestDbService.find(
|
||||||
|
{ _id: { $in: blameIdsForList.map((id) => new Types.ObjectId(id)) } },
|
||||||
|
{ lean: true, select: "type creationMethod" },
|
||||||
|
)) as any[])
|
||||||
|
: [];
|
||||||
|
const blameByIdForList = new Map<string, any>(
|
||||||
|
blamesForList.map((b) => [String(b._id), b]),
|
||||||
|
);
|
||||||
|
|
||||||
|
const list = (claims as any[]).map((c) => {
|
||||||
|
const blameForItem = c.blameRequestId
|
||||||
|
? blameByIdForList.get(c.blameRequestId.toString())
|
||||||
|
: undefined;
|
||||||
|
return {
|
||||||
|
claimRequestId: c._id.toString(),
|
||||||
|
publicId: c.publicId,
|
||||||
|
requestNo: c.requestNo,
|
||||||
|
status: c.status,
|
||||||
|
claimStatus: c.claimStatus || "PENDING",
|
||||||
|
currentStep: c.workflow?.currentStep || "",
|
||||||
|
createdAt: c.createdAt,
|
||||||
|
blameRequestId: c.blameRequestId?.toString(),
|
||||||
|
blameType: blameForItem?.type ?? undefined,
|
||||||
|
creationMethod: blameForItem?.creationMethod ?? undefined,
|
||||||
|
};
|
||||||
|
}) as ClaimListItemV2Dto[];
|
||||||
|
|
||||||
const paged = applyListQueryV2(
|
const paged = applyListQueryV2(
|
||||||
list,
|
list,
|
||||||
@@ -10856,6 +10881,15 @@ export class ClaimRequestManagementService {
|
|||||||
}
|
}
|
||||||
await this.assertActorCanViewClaimV2(claim, currentUserId, actor);
|
await this.assertActorCanViewClaimV2(claim, currentUserId, actor);
|
||||||
|
|
||||||
|
const blameForDetail = claim.blameRequestId
|
||||||
|
? ((
|
||||||
|
await this.blameRequestDbService.find(
|
||||||
|
{ _id: new Types.ObjectId(claim.blameRequestId.toString()) },
|
||||||
|
{ lean: true, select: "type creationMethod" },
|
||||||
|
)
|
||||||
|
)[0] ?? null)
|
||||||
|
: null;
|
||||||
|
|
||||||
const hasCapture = (data: any, key: string) =>
|
const hasCapture = (data: any, key: string) =>
|
||||||
data && (data instanceof Map ? data.get(key) : data[key]);
|
data && (data instanceof Map ? data.get(key) : data[key]);
|
||||||
|
|
||||||
@@ -11011,6 +11045,8 @@ export class ClaimRequestManagementService {
|
|||||||
nextStep: claim.workflow?.nextStep,
|
nextStep: claim.workflow?.nextStep,
|
||||||
blameRequestId: claim.blameRequestId?.toString(),
|
blameRequestId: claim.blameRequestId?.toString(),
|
||||||
blameRequestNo: claim.blameRequestNo,
|
blameRequestNo: claim.blameRequestNo,
|
||||||
|
blameType: (blameForDetail as any)?.type ?? undefined,
|
||||||
|
creationMethod: (blameForDetail as any)?.creationMethod ?? undefined,
|
||||||
...(ownerData ? { owner: ownerData } : {}),
|
...(ownerData ? { owner: ownerData } : {}),
|
||||||
vehicle: claim.vehicle,
|
vehicle: claim.vehicle,
|
||||||
selectedParts: selectedNormDetails,
|
selectedParts: selectedNormDetails,
|
||||||
|
|||||||
@@ -122,6 +122,18 @@ export class ClaimDetailsV2ResponseDto {
|
|||||||
@ApiPropertyOptional({ description: 'Blame request number' })
|
@ApiPropertyOptional({ description: 'Blame request number' })
|
||||||
blameRequestNo?: string;
|
blameRequestNo?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: 'Blame file type: THIRD_PARTY or CAR_BODY',
|
||||||
|
example: 'THIRD_PARTY',
|
||||||
|
})
|
||||||
|
blameType?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: 'How the blame file was initiated: IN_PERSON or LINK',
|
||||||
|
example: 'IN_PERSON',
|
||||||
|
})
|
||||||
|
creationMethod?: string;
|
||||||
|
|
||||||
@ApiPropertyOptional({
|
@ApiPropertyOptional({
|
||||||
description: 'Claim owner (damaged party): ids for the user and their insurer client scope',
|
description: 'Claim owner (damaged party): ids for the user and their insurer client scope',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -28,6 +28,18 @@ export class ClaimListItemV2Dto {
|
|||||||
|
|
||||||
@ApiProperty({ description: 'Blame request ID this claim originated from' })
|
@ApiProperty({ description: 'Blame request ID this claim originated from' })
|
||||||
blameRequestId?: string;
|
blameRequestId?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: 'Blame file type: THIRD_PARTY or CAR_BODY',
|
||||||
|
example: 'THIRD_PARTY',
|
||||||
|
})
|
||||||
|
blameType?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: 'How the blame file was initiated: IN_PERSON or LINK',
|
||||||
|
example: 'IN_PERSON',
|
||||||
|
})
|
||||||
|
creationMethod?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GetMyClaimsV2ResponseDto {
|
export class GetMyClaimsV2ResponseDto {
|
||||||
|
|||||||
@@ -116,6 +116,8 @@ export class AllRequestDtoV2 {
|
|||||||
lockFile: boolean;
|
lockFile: boolean;
|
||||||
lockTime: string | null;
|
lockTime: string | null;
|
||||||
type: string;
|
type: string;
|
||||||
|
/** IN_PERSON or LINK — how the blame file was created */
|
||||||
|
creationMethod?: string;
|
||||||
blameStatus: string;
|
blameStatus: string;
|
||||||
/** Calculated blame + linked claim lifecycle status */
|
/** Calculated blame + linked claim lifecycle status */
|
||||||
unifiedFileStatus?: string;
|
unifiedFileStatus?: string;
|
||||||
|
|||||||
@@ -762,6 +762,7 @@ export class ExpertBlameService {
|
|||||||
? new Date(workflow.lockedAt as string).toISOString()
|
? new Date(workflow.lockedAt as string).toISOString()
|
||||||
: null,
|
: null,
|
||||||
type: String(doc.type ?? "THIRD_PARTY"),
|
type: String(doc.type ?? "THIRD_PARTY"),
|
||||||
|
creationMethod: doc.creationMethod ? String(doc.creationMethod) : undefined,
|
||||||
blameStatus: String(doc.blameStatus ?? ""),
|
blameStatus: String(doc.blameStatus ?? ""),
|
||||||
partiesInitialForms: {
|
partiesInitialForms: {
|
||||||
firstParty: statementToFormKey(firstParty?.statement) ?? "",
|
firstParty: statementToFormKey(firstParty?.statement) ?? "",
|
||||||
|
|||||||
@@ -52,6 +52,12 @@ export class ClaimDetailV2ResponseDto {
|
|||||||
})
|
})
|
||||||
blameRequestType?: BlameRequestType;
|
blameRequestType?: BlameRequestType;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: "How the blame file was initiated: IN_PERSON or LINK",
|
||||||
|
example: "IN_PERSON",
|
||||||
|
})
|
||||||
|
creationMethod?: string;
|
||||||
|
|
||||||
@ApiPropertyOptional({
|
@ApiPropertyOptional({
|
||||||
description:
|
description:
|
||||||
"CAR_BODY only: first-step flags — another car (`car`) and/or object (`object`)",
|
"CAR_BODY only: first-step flags — another car (`car`) and/or object (`object`)",
|
||||||
|
|||||||
@@ -49,6 +49,12 @@ export class ClaimListItemV2Dto {
|
|||||||
})
|
})
|
||||||
blameRequestType?: BlameRequestType;
|
blameRequestType?: BlameRequestType;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: 'How the blame file was initiated: IN_PERSON or LINK',
|
||||||
|
example: 'IN_PERSON',
|
||||||
|
})
|
||||||
|
creationMethod?: string;
|
||||||
|
|
||||||
@ApiPropertyOptional({
|
@ApiPropertyOptional({
|
||||||
description:
|
description:
|
||||||
'CAR_BODY only: first-step flags — accident involved another car (`car`) and/or fixed object (`object`)',
|
'CAR_BODY only: first-step flags — accident involved another car (`car`) and/or fixed object (`object`)',
|
||||||
|
|||||||
@@ -629,6 +629,7 @@ export class ExpertClaimService {
|
|||||||
*/
|
*/
|
||||||
private blameFileContextForExpert(blame: any): {
|
private blameFileContextForExpert(blame: any): {
|
||||||
blameRequestType?: BlameRequestType;
|
blameRequestType?: BlameRequestType;
|
||||||
|
creationMethod?: string;
|
||||||
carBodyFirstForm?: { car?: boolean; object?: boolean };
|
carBodyFirstForm?: { car?: boolean; object?: boolean };
|
||||||
blameStatus?: string;
|
blameStatus?: string;
|
||||||
} {
|
} {
|
||||||
@@ -636,9 +637,11 @@ export class ExpertClaimService {
|
|||||||
const blameRequestType = blame.type as BlameRequestType;
|
const blameRequestType = blame.type as BlameRequestType;
|
||||||
const out: {
|
const out: {
|
||||||
blameRequestType?: BlameRequestType;
|
blameRequestType?: BlameRequestType;
|
||||||
|
creationMethod?: string;
|
||||||
carBodyFirstForm?: { car?: boolean; object?: boolean };
|
carBodyFirstForm?: { car?: boolean; object?: boolean };
|
||||||
blameStatus?: string;
|
blameStatus?: string;
|
||||||
} = { blameRequestType };
|
} = { blameRequestType };
|
||||||
|
if (blame.creationMethod) out.creationMethod = blame.creationMethod;
|
||||||
out.blameStatus = blame.blameStatus;
|
out.blameStatus = blame.blameStatus;
|
||||||
if (blameRequestType !== BlameRequestType.CAR_BODY) return out;
|
if (blameRequestType !== BlameRequestType.CAR_BODY) return out;
|
||||||
|
|
||||||
@@ -4017,7 +4020,7 @@ export class ExpertClaimService {
|
|||||||
blameIds.length > 0
|
blameIds.length > 0
|
||||||
? ((await this.blameRequestDbService.find(
|
? ((await this.blameRequestDbService.find(
|
||||||
{ _id: { $in: blameIds.map((id) => new Types.ObjectId(id)) } },
|
{ _id: { $in: blameIds.map((id) => new Types.ObjectId(id)) } },
|
||||||
{ lean: true, select: "type parties expert.decision blameStatus status isMadeByFileMaker" },
|
{ lean: true, select: "type creationMethod parties expert.decision blameStatus status isMadeByFileMaker" },
|
||||||
)) as any[])
|
)) as any[])
|
||||||
: [];
|
: [];
|
||||||
const blameById = new Map<string, any>(
|
const blameById = new Map<string, any>(
|
||||||
@@ -4117,7 +4120,7 @@ export class ExpertClaimService {
|
|||||||
blameIds.length > 0
|
blameIds.length > 0
|
||||||
? ((await this.blameRequestDbService.find(
|
? ((await this.blameRequestDbService.find(
|
||||||
{ _id: { $in: blameIds.map((id) => new Types.ObjectId(id)) } },
|
{ _id: { $in: blameIds.map((id) => new Types.ObjectId(id)) } },
|
||||||
{ lean: true, select: "type parties expert.decision blameStatus status" },
|
{ lean: true, select: "type creationMethod parties expert.decision blameStatus status" },
|
||||||
)) as any[])
|
)) as any[])
|
||||||
: [];
|
: [];
|
||||||
const blameById = new Map<string, any>(
|
const blameById = new Map<string, any>(
|
||||||
@@ -4212,7 +4215,7 @@ export class ExpertClaimService {
|
|||||||
{
|
{
|
||||||
lean: true,
|
lean: true,
|
||||||
select:
|
select:
|
||||||
"_id type parties blameStatus status expert.decision assignedFileReviewerId requiresFileMakerApproval",
|
"_id type creationMethod parties blameStatus status expert.decision assignedFileReviewerId requiresFileMakerApproval",
|
||||||
},
|
},
|
||||||
)) as any[];
|
)) as any[];
|
||||||
|
|
||||||
@@ -4303,7 +4306,7 @@ export class ExpertClaimService {
|
|||||||
|
|
||||||
const makerBlames = (await this.blameRequestDbService.find(
|
const makerBlames = (await this.blameRequestDbService.find(
|
||||||
{ isMadeByFileMaker: true, initiatedByFieldExpertId: makerOid },
|
{ isMadeByFileMaker: true, initiatedByFieldExpertId: makerOid },
|
||||||
{ lean: true, select: "_id type parties blameStatus status expert.decision assignedFileReviewerId requiresFileMakerApproval" },
|
{ lean: true, select: "_id type creationMethod parties blameStatus status expert.decision assignedFileReviewerId requiresFileMakerApproval" },
|
||||||
)) as any[];
|
)) as any[];
|
||||||
|
|
||||||
if (makerBlames.length === 0) {
|
if (makerBlames.length === 0) {
|
||||||
|
|||||||
@@ -1498,6 +1498,8 @@ export class ExpertInsurerService {
|
|||||||
(blame as any)?.requestNumber ||
|
(blame as any)?.requestNumber ||
|
||||||
(claim as any)?.requestNumber,
|
(claim as any)?.requestNumber,
|
||||||
type: (blame as any)?.type ?? (blameFull as any)?.type,
|
type: (blame as any)?.type ?? (blameFull as any)?.type,
|
||||||
|
creationMethod:
|
||||||
|
(blame as any)?.creationMethod ?? (blameFull as any)?.creationMethod,
|
||||||
hasClaim: !!claim,
|
hasClaim: !!claim,
|
||||||
blameStatus: (blame as any)?.status ?? (blameFull as any)?.status,
|
blameStatus: (blame as any)?.status ?? (blameFull as any)?.status,
|
||||||
claimStatus: (claim as any)?.status,
|
claimStatus: (claim as any)?.status,
|
||||||
|
|||||||
@@ -6116,6 +6116,7 @@ export class RequestManagementService {
|
|||||||
requestNo: plain.requestNo,
|
requestNo: plain.requestNo,
|
||||||
publicId: plain.publicId,
|
publicId: plain.publicId,
|
||||||
type: plain.type,
|
type: plain.type,
|
||||||
|
creationMethod: plain.creationMethod,
|
||||||
status: plain.status,
|
status: plain.status,
|
||||||
blameStatus: plain.blameStatus,
|
blameStatus: plain.blameStatus,
|
||||||
workflow: plain.workflow,
|
workflow: plain.workflow,
|
||||||
|
|||||||
Reference in New Issue
Block a user