11 KiB
راهنمای فرانتاند: ثبت پاسخ کارشناس خسارت (V2)
این مستند قرارداد API زیر را توضیح میدهد، بهویژه اعتبارسنجی مبلغها و ساختار خطاهایی که باید در فرم نمایش داده شوند.
PUT /v2/expert-claim/reply/submit/:claimRequestId
Authorization: Bearer <actor-token>
Content-Type: application/json
اگر محیط شما API را زیر پیشوند /api منتشر میکند، مسیر نهایی بهصورت /api/v2/expert-claim/reply/submit/:claimRequestId است.
پیشنیازها
- کاربر باید نقش کارشناس مجاز داشته باشد.
- پرونده باید پیش از ارسال توسط همین کارشناس قفل شده باشد.
partIdهر ردیف باید ازdamagedParts[].partIdدر جزئیات پرونده انتخاب شود؛ شناسه دلخواه ارسال نکنید.- دستکم یک ردیف در
partsلازم است.
بدنه درخواست
تمام مبلغها باید string باشند. ارقام فارسی/انگلیسی و جداکننده هزارگان پذیرفته میشوند؛ برای نمونه هر دو مقدار "100000" و "۱۰۰,۰۰۰" معتبرند.
{
"description": "تعویض درب جلو لازم است",
"parts": [
{
"partId": 201,
"typeOfDamage": "تعویض",
"price": "2500000",
"salary": "400000",
"totalPayment": "2900000",
"factorNeeded": false,
"daghi": {
"option": "ارزش لوازم بازیافتی",
"price": "300000"
}
}
]
}
فیلدهای سطح بالا
| فیلد | الزامی | توضیح |
|---|---|---|
description |
خیر | یادداشت متنی کارشناس. میتواند ارسال نشود. |
parts |
بله | آرایهای با حداقل یک ردیف قیمتگذاری. |
فیلدهای هر ردیف parts[i]
| فیلد | الزامی | مقدار و قاعده |
|---|---|---|
partId |
بله | عدد صحیح؛ باید متعلق به قطعات آسیبدیده همان پرونده باشد. |
typeOfDamage |
بله | دقیقاً یکی از "تعمیر" یا "تعویض". |
price |
برای "تعویض" بله؛ برای "تعمیر" اختیاری |
در صورت ارسال، مبلغ بین 100,000 تا 10,000,000,000 تومان. |
salary |
بله | مبلغ بین 100,000 تا 10,000,000,000 تومان. |
totalPayment |
بله | مبلغ بین 1,000,000 تا 100,000,000,000 ریال. فقط در جریان V1، مجموع این فیلدها در کل پرونده نباید از 530,000,000 ریال بیشتر شود. |
factorNeeded |
بله | مقدار Boolean واقعی (true یا false)؛ رشته ارسال نکنید. |
daghi |
برای "تعویض" بله |
برای "تعمیر" لازم نیست و در ثبت نهایی حذف میشود. |
daghi.option |
در صورت وجود daghi بله |
یکی از "ارزش لوازم بازیافتی"، "تحویل داغی"، "فاقد ارزش" یا "با احتساب داغی". |
daghi.price |
فقط وقتی option برابر "ارزش لوازم بازیافتی" است |
مبلغ بین 100,000 تا 10,000,000,000 تومان. |
daghi.branchId |
فقط وقتی option برابر "تحویل داغی" است |
Mongo ObjectId معتبرِ شعبه. |
نکتهها:
- مقدار
0برای هیچ مبلغ ارسالی این endpoint معتبر نیست؛ حداقل مبلغ 100,000 تومان است. - محدودیت هر فیلد مبلغ مستقل است؛ سقف 530 میلیون ریال فقط برای مجموع
totalPaymentتمام ردیفهای پرونده V1 اعمال میشود. جریانهای V2 تا V6 سقف مجموع ندارند. - فیلدهای ناشناخته در body حذف میشوند. فرانتاند نباید برای انتقال داده به آنها تکیه کند.
پاسخ موفق
پاسخ 200 شامل مسیر بعدی workflow است. نمونه:
{
"claimRequestId": "66c...",
"status": "COMPLETED",
"claimStatus": "APPROVED",
"currentStep": "CLAIM_COMPLETED",
"workflowNextStep": "CLAIM_COMPLETED",
"factorNeeded": false,
"mixedPricingAndFactors": false,
"allPartsFactorNeeded": false,
"isFinalReplyAfterObjection": false
}
مقادیر status و step به این وابستهاند که ردیف factor داشته باشید یا نه؛ فرانتاند باید از مقادیر پاسخ استفاده کند، نه اینکه مسیر بعدی را فقط از payload حدس بزند.
قرارداد خطا
همه خطاهای این endpoint JSON هستند و NestJS مقدار statusCode را نیز به پاسخ اضافه میکند. برای نمایش پیام به کاربر از message استفاده کنید و برای منطق برنامه از code استفاده کنید؛ متن فارسی را با متن ثابت در فرانتاند جایگزین نکنید.
1. خطای ساختار DTO — 400
برای نبودن فیلد الزامی، نوع اشتباه، enum نامعتبر، آرایه خالی، یا فرمت مبلغ نامعتبر، پاسخ زیر برمیگردد:
{
"statusCode": 400,
"message": "اطلاعات ارسالی پاسخ کارشناسی معتبر نیست.",
"error": "EXPERT_REPLY_VALIDATION_ERROR",
"code": "EXPERT_REPLY_VALIDATION_ERROR",
"validationErrors": [
{
"field": "parts[0].salary",
"message": "باید مبلغ صحیح و غیرمنفی به تومان باشد."
},
{
"field": "parts[0].factorNeeded",
"message": "باید درست یا نادرست باشد."
}
]
}
validationErrors ممکن است چند خطا داشته باشد. کلید field دقیقاً برای اتصال به کنترل فرم است؛ مانند parts[0].daghi.price یا parts[2].partId.
2. خطای قواعد مبلغ و قیمتگذاری — 400
این خطاها پس از اعتبارسنجی ساختار و پیش از تغییر وضعیت پرونده بررسی میشوند. برای مثال، مبلغ کمتر از حداقل:
{
"statusCode": 400,
"message": "قیمت قطعه 201 باید حداقل ۱۰۰٬۰۰۰ و حداکثر ۱۰٬۰۰۰٬۰۰۰٬۰۰۰ تومان باشد.",
"error": "EXPERT_REPLY_VALIDATION_ERROR",
"code": "EXPERT_REPLY_VALIDATION_ERROR",
"field": "parts[0].price",
"partId": "201",
"rule": "amount_out_of_range",
"minAmount": 100000,
"maxAmount": 10000000000
}
rule یکی از این مقادیر است:
| مقدار | معنی |
|---|---|
required |
فیلد لازم ارسال نشده است. |
invalid_value |
مقدار enum یا شناسه معتبر نیست. |
invalid_amount |
مبلغ، عدد صحیح غیرمنفی به تومان نیست. |
amount_out_of_range |
مبلغ خارج از بازه minAmount و maxAmount است. |
در صورت amount_out_of_range، برای نمایش محدوده از اعداد minAmount و maxAmount استفاده کنید، نه از parse کردن متن message.
3. سقف مجموع مبلغها — 400
{
"statusCode": 400,
"message": "مجموع مبلغ قطعات (۵۴۰٬۰۰۰٬۰۰۰) از سقف مجاز (۵۳۰٬۰۰۰٬۰۰۰) ریال بیشتر است.",
"error": "PRICE_CAP_ERROR",
"code": "PRICE_CAP_ERROR",
"totalPrice": 540000000,
"priceCap": 530000000
}
این خطا فقط برای پروندههای V1 رخ میدهد و به یک ردیف مشخص وصل نیست. آن را در بالای جدول قیمتها نمایش دهید و از priceCap جزئیات پرونده/خطا برای پیام UI استفاده کنید. مقدار priceCap: null یعنی پرونده سقف مجموع ندارد.
4. خطاهای قواعد پرونده و workflow
این خطاها ساختار مشترک زیر را دارند:
{
"statusCode": 400,
"message": "قطعه با شناسه 201 در فهرست قطعات آسیبدیده پرونده وجود ندارد.",
"error": "EXPERT_REPLY_SUBMISSION_ERROR",
"code": "PART_NOT_ON_CLAIM",
"field": "partId",
"partId": 201
}
کدهای مهم:
| HTTP | code |
رفتار پیشنهادی فرانتاند |
|---|---|---|
| 404 | CLAIM_NOT_FOUND |
پیام خطا و بازگشت به فهرست پروندهها. |
| 400 | CLAIM_NOT_REVIEWABLE |
جزئیات پرونده را refresh کنید؛ ثبت در وضعیت فعلی مجاز نیست. |
| 403 | CLAIM_NOT_LOCKED |
کاربر باید ابتدا پرونده را قفل کند. |
| 403 | CLAIM_LOCKED_BY_ANOTHER_EXPERT |
فرم را read-only کنید و پیام مناسب نمایش دهید. |
| 400 | PART_NOT_ON_CLAIM |
داده قطعات را refresh کنید و ردیف خطادار را اصلاح/حذف کنید. |
| 400 | PART_INVALID / PART_ID_INVALID |
ردیف دارای partId را اصلاح کنید. |
| 400 | DUPLICATE_PART |
ردیف تکراری را حذف کنید. |
| 400 | DAGHI_OPTION_REQUIRED |
فیلد daghi.option همان ردیف را نشاندار کنید. |
| 400 | DAGHI_PRICE_REQUIRED |
فیلد daghi.price همان ردیف را نشاندار کنید. |
| 400 | DAGHI_BRANCH_REQUIRED / DAGHI_BRANCH_INVALID |
فیلد daghi.branchId همان ردیف را نشاندار کنید. |
| 409 | FINAL_REPLY_ALREADY_SUBMITTED |
ثبت مجدد ممنوع است؛ داده پرونده را refresh کنید. |
برای خطاهای داغی که از سرویس برمیگردند، field به شکل parts[<index>].daghi.<property> است.
الگوی پیشنهادی هندل کردن خطا در فرانتاند
type ApiErrorBody = {
message?: string;
code?: string;
field?: string;
validationErrors?: Array<{ field: string; message: string }>;
minAmount?: number;
maxAmount?: number;
priceCap?: number;
};
function applySubmitError(body: ApiErrorBody) {
if (body.validationErrors?.length) {
for (const issue of body.validationErrors) {
setFieldError(issue.field, issue.message);
}
return;
}
if (body.field) {
setFieldError(body.field, body.message ?? "مقدار واردشده معتبر نیست.");
return;
}
setFormError(body.message ?? "ثبت پاسخ کارشناسی انجام نشد.");
}
قبل از ارسال، فرانتاند میتواند همین بازه مبلغ را برای تجربه کاربری بهتر بررسی کند؛ با این حال اعتبار نهایی همیشه پاسخ API است. جمع totalPayment را فقط وقتی priceCap جزئیات پرونده عدد است با سقف مقایسه کنید؛ null یعنی V2 تا V6 و بدون سقف مجموع.