# POST /v2/charter/reservation

# Charter: Insert Bulk Reservations

این اندپوینت برای ایجاد یک یا چند رزرو به صورت همزمان طراحی شده است. ورودی اصلی آن آرایه‌ای از مسافران است. سیستم ابتدا تمام مسافران را اعتبارسنجی کرده، سپس ظرفیت را بررسی می‌کند و در نهایت رزروها را ایجاد می‌کند. این متد بین چارترهای مسیرمحور (مانند پرواز) و اقامتگاهی (هتل) تمایز قائل می‌شود.

<div class="api-docs" id="bkmrk-"></div>## Request Overview

<div class="api-docs" id="bkmrk-url%3A-%2Fv2%2Fcharter%2Fres"><div class="endpoint-info"><div>**URL:** `/v2/charter/reservation`</div><div>**Method:** <span class="method-post">POST</span></div><div>**Controller:** CharterController@insertListCharterReservation</div><div>**Middleware Stack:** authWithJwt</div></div></div>## Access Control

<div class="api-docs" id="bkmrk-%D8%AF%D8%B3%D8%AA%D8%B1%D8%B3%DB%8C-%D9%85%D8%B9%D8%AA%D8%A8%D8%B1-jwt">- دسترسی معتبر JWT

</div>## Request Body (JSON)

<div class="api-docs" id="bkmrk-field-type-descripti"><table class="schema-table" dir="rtl"><thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>main\_id</td><td>integer</td><td>**(الزامی)** شناسه چارتر اصلی</td></tr><tr><td>item\_id</td><td>integer</td><td>**(الزامی)** شناسه آیتم محاسباتی (کلاس پروازی یا نوع اتاق)</td></tr><tr><td>checkin\_date</td><td>string (Y-m-d)</td><td>**(فقط برای اقامتگاه)** تاریخ ورود</td></tr><tr><td>checkout\_date</td><td>string (Y-m-d)</td><td>**(فقط برای اقامتگاه)** تاریخ خروج</td></tr><tr><td>passengers</td><td>array\[object\]</td><td>**(الزامی)** لیست مسافرانی که باید برایشان رزرو ثبت شود.</td></tr></tbody></table>

</div>### ساختار آبجکت Passenger

<div class="api-docs" id="bkmrk-field-type-descripti-1"><table class="schema-table" dir="rtl"><thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>identity.id</td><td>string</td><td>کد ملی برای مسافر ایرانی</td></tr><tr><td>identity.nationality</td><td>string</td><td>کد ۲ حرفی ISO کشور (مثلاً 'IR')</td></tr><tr><td>passport.id</td><td>string</td><td>شماره پاسپورت برای مسافر خارجی</td></tr><tr><td>fullname.first\_name.en</td><td>string</td><td>نام (انگلیسی)</td></tr><tr><td>fullname.last\_name.en</td><td>string</td><td>نام خانوادگی (انگلیسی)</td></tr><tr><td>birth</td><td>string</td><td>تاریخ تولد (Y-m-d)</td></tr><tr><td>mobile / email</td><td>string</td><td>اطلاعات تماس (اختیاری)</td></tr><tr><td>status</td><td>string</td><td>(اختیاری) اگر مقدار آن `refund` باشد، رزرو مستقیماً به عنوان استرداد ۱۰۰٪ ثبت می‌شود.</td></tr><tr><td>financial</td><td>object</td><td>**(اختیاری)** برای ثبت قیمت به صورت دستی. اگر ارسال نشود، قیمت به صورت خودکار محاسبه می‌شود.</td></tr><tr><td colspan="3">- `financial.supplier`: نام تأمین‌کننده
- `financial.sale_price`: مبلغ قابل پرداخت
- `financial.commission`: مبلغ کمیسیون

</td></tr></tbody></table>

</div>## Logic Details

### ۱. اعتبارسنجی گسترده

پیش از هر اقدامی، سیستم تمام مسافران موجود در آرایه `passengers` را بررسی می‌کند. در صورت وجود اولین خطا، عملیات متوقف و کد خطای `422 Unprocessable Entity` بازگردانده می‌شود.

<div class="api-docs" id="bkmrk-%D9%85%D9%84%DB%8C%D8%AA%3A-%D8%A8%D8%A7%DB%8C%D8%AF-%DB%8C%DA%A9-%DA%A9%D8%AF-%D9%85%D8%B9%D8%AA">- **ملیت:** باید یک کد معتبر دو حرفی باشد (کدهای ۳ حرفی به ۲ حرفی تبدیل می‌شوند). (خطای 1019)
- **کد ملی / پاسپورت:** برای ایرانیان الگوریتم کد ملی و برای خارجی‌ها فرمت پاسپورت بررسی می‌شود. (خطای 1011)
- **اطلاعات تماس:** فرمت شماره موبایل و ایمیل بررسی می‌شود. (خطای 1013, 1014)
- **تاریخ تولد:** باید با فرمت `Y-m-d` باشد. (خطای 1021)

</div>### ۲. بررسی ظرفیت

پس از اعتبارسنجی، سیستم تعداد مسافران بزرگسال و کودک را شمارش کرده و با ظرفیت باقی‌مانده آیتم مقایسه می‌کند.   
اگر ظرفیت کافی نباشد، عملیات متوقف و کد خطای `409 Conflict` به همراه پیام "ظرفیت تکمیل است" (کد 1008) بازگردانده می‌شود.

### ۳. تفاوت منطق Route و Accommodation

هسته اصلی این متد بر اساس نوع چارتر عمل می‌کند:

<div class="api-docs" id="bkmrk-%D9%86%D9%88%D8%B9-route-%28%D9%BE%D8%B1%D9%88%D8%A7%D8%B2%D8%8C-%D9%82%D8%B7">- **نوع Route (پرواز، قطار و...):**   
    \- برای هر مسافر در آرایه یک رزرو **جداگانه** ایجاد می‌شود.   
    \- قبل از ایجاد، بررسی می‌شود که آیا مسافر قبلاً برای همین چارتر رزرو فعال دارد یا خیر (جلوگیری از ثبت تکراری). در صورت تکراری بودن، یک آیتم خطا در خروجی نهایی قرار می‌گیرد.
- **نوع Accommodation (هتل):**   
    \- تمام مسافران در آرایه به عنوان مهمانان **یک رزرو واحد** (یک اتاق) در نظر گرفته می‌شوند.   
    \- ابتدا بررسی می‌شود که آیا برای بازه `checkin_date` تا `checkout_date` اتاق خالی وجود دارد یا خیر. در غیر این صورت، خطای `409 Conflict` (کد 1026) بازگردانده می‌شود. - پس از ایجاد رزرو، سیستم به صورت خودکار یک اتاق در دسترس را برای تمام شب‌های اقامت به این رزرو اختصاص می‌دهد.

</div>### ۴. محاسبه مالی و ثبت

برای هر رزرو، اگر آبجکت `financial` در اطلاعات مسافر ارسال شده باشد، قیمت‌ها به صورت دستی ثبت می‌شوند. در غیر این صورت، سیستم با استفاده از `financialCalculation` قیمت نهایی را بر اساس قوانین قیمت‌گذاری (پله‌ای، کارمزد، مارکاپ) محاسبه می‌کند. در نهایت، برای هر رزرو موفق، یک PNR محلی و یک شناسه یکتا تولید و در دیتابیس ذخیره می‌شود.

<div class="api-docs" id="bkmrk--1"></div>## Response Structure

### پاسخ موفق

در صورت موفقیت، کد `201 Created` به همراه آرایه‌ای از نتایج بازگردانده می‌شود. این آرایه می‌تواند شامل آیتم‌های موفق و ناموفق (مثلاً مسافر تکراری) باشد.

```
{
  "items": [
    {
      "status": true,
      "pnr": {
        "local": "XG7H5A2B", // PNR مشترک برای این بچ
        "original": "K9L4M1N0", // Slug یکتای این رزرو
        "id": 10845        // شناسه رزرو + 10000
      },
      // این بخش فقط برای رزرو اقامتگاه وجود دارد
      "accommodation_rooms": [
        {
          "reservation_id": 10845,
          "room_id": 10021,
          "date": "2025-12-25",
          "number": "205"
        }
      ]
    },
    {
      "status": false,
      "item_id": 45,
      "details": "0012345678",
      "code": 1010,
      "message": "برای این مسافر قبلا این آیتم خریداری شده است.",
      "solution": "..."
    }
  ],
  "meta": { "timestamp": 1715000000 }
}
  
```

<div class="api-docs" id="bkmrk--2"></div>## Flowchart

<div class="api-docs" id="bkmrk-start-%28post-%2Freserva"><div class="flowchart"><div class="flow-item">Start (POST /reservation)</div><div class="flow-arrow">↓</div><div class="flow-item" style="background-color: #ffe8e8;">**Validation Loop (Passengers):**  
<small>Nationality → ID/Passport → Contact → Birth Date</small></div><div class="flow-arrow">Fail → Halt &amp; Return 422</div><div class="flow-arrow">Pass ↓</div><div class="flow-item" style="background-color: #fff4e0;">**Capacity Check:**  
<small>Required (ADT+CHD) vs. Available Balance</small></div><div class="flow-arrow">Fail → Halt &amp; Return 409</div><div class="flow-arrow">Pass ↓</div><div class="flow-item">Check Charter Type</div><div style="display: flex; justify-content: space-around; gap: 10px; margin-top: 10px;"><div style="width: 48%; border: 1px dashed #007bff; padding: 10px; border-radius: 8px;">**Type: Route**<div class="flow-item">Loop Each Passenger</div><div class="flow-arrow">↓</div><div class="flow-item">Check for Duplicates</div><div class="flow-arrow">↓</div><div class="flow-item">Create Individual Reservation</div><div class="flow-arrow">↓</div><div class="flow-item">Add to `insertQuery` Array</div></div><div style="width: 48%; border: 1px dashed #28a745; padding: 10px; border-radius: 8px;">**Type: Accommodation**<div class="flow-item" style="background-color: #fff4e0;">Check Room Availability</div><div class="flow-arrow">Fail → Halt &amp; Return 409</div><div class="flow-arrow">Pass ↓</div><div class="flow-item">Create One Reservation for All Guests</div><div class="flow-arrow">↓</div><div class="flow-item">Add to `insertQuery` Array</div></div></div><div class="flow-arrow">↓</div><div class="flow-item" style="background-color: #e2f0d9;">**Final Insertion Loop:**  
<small>Insert DB Record → Handle Refund Status → For Accommodation, Assign Room per Night</small></div><div class="flow-arrow">↓</div><div class="flow-item">Return 201 with Result Array</div></div></div>