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
| Field | Indexing | Example |
|---|---|---|
index_hanh_khach | 1-based | 1, 2, 3 |
index_chang_bay | 1-based | 1, 2 |
index_chuyen_bay | 0-based | 0, 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:
-
Hold Booking →
05-HOLD-BOOKING.md- Include
dich_vuandcho_ngoiin request
- Include
-
Issue Ticket →
06-ISSUE-TICKET.md- Include
dich_vuandcho_ngoiin request
- Include
📝 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_khachandindex_chang_bayare 1-basedindex_chuyen_bayis 0-based- Can book with any combination: services only, seats only, or both
- Empty arrays (
[]) are valid for no services/seats