Skip to main content

Select Services & Seats - Chọn Dịch Vụ & Ghế


📋 Overview

Sau khi lấy danh sách services/seats từ API danh-sach-phu-tro-tim-ve, cần prepare data để thêm vào booking request.

No API call in this step - Just data preparation.


🎯 Select Services (Baggage & Food)

Step 1: Get Available Services

From 03-GET-SERVICES.md response:

const services = response.data["0"].dich_vu["0"];

Step 2: Filter by Type

// Baggage only
const baggage = services.filter((s) => s.loai_dich_vu === 2 && s.gia_net > 0);

// Food only
const food = services.filter((s) => s.loai_dich_vu === 1);

Step 3: Select Items

// Example: Select 30kg baggage
const selectedBaggage = baggage.find((b) => b.so_kg === "30");

// Example: Select Combo 1 food
const selectedFood = food.find((f) => f.ten.includes("Combo 1"));

Step 4: Build dich_vu Array for Booking

const dich_vu = [];

// Add baggage
if (selectedBaggage) {
dich_vu.push({
uuid_dich_vu: selectedBaggage.uuid,
index_hanh_khach: 1, // Passenger index (1-based)
index_chang_bay: 1, // Segment index (1-based)
});
}

// Add food
if (selectedFood) {
dich_vu.push({
uuid_dich_vu: selectedFood.uuid,
index_hanh_khach: 1,
index_chang_bay: 1,
});
}

Result:

{
"dich_vu": [
{
"uuid_dich_vu": "7a3251f4-aee4-11f0-bd8c-86d224031662",
"index_hanh_khach": 1,
"index_chang_bay": 1
},
{
"uuid_dich_vu": "7a35fd6e-aee4-11f0-bd8c-86d224031662",
"index_hanh_khach": 1,
"index_chang_bay": 1
}
]
}

💺 Select Seats

Step 1: Get Seat Map

From 03-GET-SERVICES.md response:

const seatMap = response.data["0"].cho_ngoi;

Step 2: Flatten Seat Map

const allSeats = [];
Object.keys(seatMap).forEach((row) => {
Object.keys(seatMap[row]).forEach((col) => {
const seat = seatMap[row][col];
if (seat) {
allSeats.push(seat);
}
});
});

Step 3: Filter Available Seats

const availableSeats = allSeats.filter(
(s) =>
s.hop_le === true && // Valid seat
s.trang_thai === false, // Not occupied
);

Step 4: Select a Seat

// Example: Select seat 12C
const selectedSeat = availableSeats.find((s) => s.ma_ghe === "12C");

// Or: Select random available seat
const randomSeat =
availableSeats[Math.floor(Math.random() * availableSeats.length)];

Step 5: Build cho_ngoi Array for Booking

const cho_ngoi = [];

if (selectedSeat) {
cho_ngoi.push({
ma_cho_ngoi: selectedSeat.ma_cho_ngoi,
uuid_cho_ngoi: selectedSeat.uuid,
index_hanh_khach: 1, // Passenger index (1-based)
index_chang_bay: 1, // Segment index (1-based)
index_chuyen_bay: selectedSeat.index_chuyen_bay,
});
}

Result:

{
"cho_ngoi": [
{
"ma_cho_ngoi": "encoded-seat-code",
"uuid_cho_ngoi": "7a5a7b02-aee4-11f0-bd8c-86d224031662",
"index_hanh_khach": 1,
"index_chang_bay": 1,
"index_chuyen_bay": 0
}
]
}

📝 Complete Booking Request Body

After selecting services & seats, include in Hold/Issue request:

{
"api": "VJ",
"nhieu_chang": 0,
"chuyen_bay": [
{
"index": 1,
"uuid": "flight-uuid-from-search",
"phi_dai_ly": 0,
"index_hang_cho": 0,
"loai_phi_dai_ly": "Cơ bản"
}
],
"hanh_khach": [
{
"index": 1,
"ho": "NGUYEN VAN",
"ten": "TEST",
"email": "test@example.com",
"so_dien_thoai": "0987654321",
"ngay_sinh": "01-01-1990",
"the_thanh_vien": "",
"loai_hanh_khach": 1,
"danh_xung": 1,
"cha_me_id": null,
"ho_chieu": null
}
],
"thong_tin_booker": {
"ho": "TRAN THI",
"ten": "BOOKER",
"email": "booker@example.com",
"so_dien_thoai": "0912345678"
},
"dich_vu": [
{
"uuid_dich_vu": "7a3251f4-aee4-11f0-bd8c-86d224031662",
"index_hanh_khach": 1,
"index_chang_bay": 1
},
{
"uuid_dich_vu": "7a35fd6e-aee4-11f0-bd8c-86d224031662",
"index_hanh_khach": 1,
"index_chang_bay": 1
}
],
"cho_ngoi": [
{
"ma_cho_ngoi": "encoded-seat-code",
"uuid_cho_ngoi": "7a5a7b02-aee4-11f0-bd8c-86d224031662",
"index_hanh_khach": 1,
"index_chang_bay": 1,
"index_chuyen_bay": 0
}
],
"ma_khuyen_mai": "",
"trang_thai": 0,
"xac_nhan_ve_dup": "",
"xac_nhan_thay_doi_gia": "",
"tong_gia_ve": 0,
"xac_nhan_cho_du_bi": ""
}

⚠️ Important Notes

1. Index Conventions

FieldIndexingExample
index_hanh_khach1-based1, 2, 3
index_chang_bay1-based1, 2
index_chuyen_bay0-based0, 1

2. Multiple Passengers

For 2 passengers:

{
"dich_vu": [
{
"uuid_dich_vu": "baggage-uuid",
"index_hanh_khach": 1, // Passenger 1
"index_chang_bay": 1
},
{
"uuid_dich_vu": "baggage-uuid-2",
"index_hanh_khach": 2, // Passenger 2
"index_chang_bay": 1
}
],
"cho_ngoi": [
{
"uuid_cho_ngoi": "seat-1A-uuid",
"index_hanh_khach": 1
},
{
"uuid_cho_ngoi": "seat-1B-uuid",
"index_hanh_khach": 2
}
]
}

3. UUID Freshness

Get fresh UUIDs immediately before booking:

// ❌ Bad: Get services → wait 10 minutes → book
await getServices();
await sleep(600000); // 10 minutes
await bookWithServices(); // UUIDs expired!

// ✅ Good: Get services → immediately book
await getServices();
await bookWithServices(); // UUIDs still valid

4. Optional Fields

Can book without services/seats:

{
"dich_vu": [], // No services
"cho_ngoi": [] // No seats
}

5. Service Types

Can mix baggage and food:

dich_vu = [
{ uuid_dich_vu: "baggage-uuid", ... }, // Baggage
{ uuid_dich_vu: "food-uuid", ... } // Food
]

🎯 Practical Examples

Example 1: Book with Baggage Only

const dich_vu = [
{
uuid_dich_vu: selectedBaggage.uuid,
index_hanh_khach: 1,
index_chang_bay: 1,
},
];

const cho_ngoi = []; // No seat selection

Example 2: Book with Seat Only

const dich_vu = []; // No services

const cho_ngoi = [
{
ma_cho_ngoi: selectedSeat.ma_cho_ngoi,
uuid_cho_ngoi: selectedSeat.uuid,
index_hanh_khach: 1,
index_chang_bay: 1,
index_chuyen_bay: 0,
},
];

Example 3: Book with Everything

const dich_vu = [
{ uuid_dich_vu: baggage.uuid, index_hanh_khach: 1, index_chang_bay: 1 },
{ uuid_dich_vu: food.uuid, index_hanh_khach: 1, index_chang_bay: 1 },
];

const cho_ngoi = [
{
ma_cho_ngoi: seat.ma_cho_ngoi,
uuid_cho_ngoi: seat.uuid,
index_hanh_khach: 1,
index_chang_bay: 1,
index_chuyen_bay: 0,
},
];

🔗 Next Steps

After preparing dich_vu and cho_ngoi arrays:

  1. Hold Booking05-HOLD-BOOKING.md

    • Include dich_vu and cho_ngoi in request
  2. Issue Ticket06-ISSUE-TICKET.md

    • Include dich_vu and cho_ngoi in request

📝 Notes

  • This is a data preparation step, no API call
  • Get fresh services/seats immediately before booking
  • UUIDs expire in ~5-10 minutes
  • index_hanh_khach and index_chang_bay are 1-based
  • index_chuyen_bay is 0-based
  • Can book with any combination: services only, seats only, or both
  • Empty arrays ([]) are valid for no services/seats