PTX Channel Manager — System Introduction
Version: 2.9.x
Last updated: 2026-04-24
Audience: sales demo, partner onboarding, internal stakeholders
1. System in one sentence
PTX Channel Manager (PTX-CM) là channel manager + CRM vận hành tập trung cho property owner đang bán phòng trên nhiều OTA (Booking.com, Agoda, Traveloka, Expedia) ở Việt Nam, Indonesia, Malaysia. Ngăn overbooking bằng cách sync tồn kho đa OTA trong 60 giây, đồng thời thống nhất quy trình booking — customer — tài chính vào một nơi.
2. Đối tượng sử dụng
| Role | Quan tâm chính |
|---|---|
| Property Manager / Owner | Tồn kho chính xác, doanh thu, tránh overbooking |
| CS / Front-desk | Xử lí booking, chat nội bộ, escalation |
| Accounting | Thanh toán, đối soát OTA, hoa hồng |
| Operations | SLA, workflow, alert, audit |
| Admin / HQ | Multi-country access, quyền hạn, báo cáo hệ thống |
3. Kiến trúc tổng thể
┌────────────────┐ ┌──────────────────┐ ┌────────────────┐
│ Next.js Web │────▶│ NestJS API │────▶│ PostgreSQL 16 │
│ (App Router, │ │ (REST + WS) │ │ Prisma ORM │
│ TS strict) │ └───────┬──────────┘ └────────────────┘
└────────────────┘ │ ▲
▲ ├──▶ Redis (pub/sub, BullMQ)│
│ │ │
│ └──▶ OTA Adapters ──────────┘
│ (Booking.com, Agoda,
│ Traveloka, Expedia)
│
▼
┌────────────────┐
│ Cloudflare R2 │ attachments, evidence, export bundles
└────────────────┘Tech stack
- Frontend: Next.js 15 (App Router), React 19, TypeScript strict, Tailwind
- Backend: NestJS 11, Prisma 7, BullMQ jobs, Socket-compatible WS gateway
- Infra: PostgreSQL 16, Redis 7, Cloudflare R2, Docker Compose (dev), Kubernetes-ready pods
- i18n:
en,vi(light-weight custom context, không dùng lib ngoài)
4. Module map
Mỗi mục = 1 folder trong apps/web/app/(dashboard)/ và có service tương ứng bên apps/api/src/modules/.
| Module | Chức năng chính |
|---|---|
| Bookings | Danh sách booking đa OTA, booking detail, workflow 4-axis (CS / Payment / Source / Accounting), escalation, comment thread nội bộ |
| OTA Accounts | Kết nối OTA (encrypted credentials AES-256-GCM), test session, 2FA (TOTP / manual), map room type → rate plan |
| Properties | Quản lí property, room types, phân quyền manager |
| Rates | Base rates, bulk apply, bulk ops, rate rules (markup / discount / seasonal) |
| Availability | Real-time inventory grid, overbooking alert |
| Customers / Suppliers | CRM nhẹ cho khách + đối tác, đa quốc gia |
| Sync Jobs | Lịch sử sync OTA (polling mỗi 150s), retry, failure drill-down |
| Alerts | Overbooking, session expired, SLA breach, missing deposit, unconfirmed check-in |
| Workflows | BPM engine: phase gate, status transition, designer UI, visibility rule |
| Chat | DM + booking comment thread, realtime WS, mentions, attachments |
| Notifications | In-app inbox + email; Chat mention, booking event, alert, system |
| Master Data | Countries, booking statuses (CS/payment/source/accounting), OTA status mapping, formula templates |
| Logs | Audit log, activity log |
| Settings / Profile | User profile, password, locale, date format, escalation tier |
5. Luồng dùng điển hình
5.1 Kết nối OTA mới
- Manager vào OTA Accounts → Connect
- Nhập credentials (mã hóa trước khi lưu)
- Hệ thống test session → ghi nhận
active | expired | error | requires_2fa - Map room type → OTA rate plan
- Bật sync — cron
ota-pollingchạy 150s/lần
5.2 Booking đến từ OTA
- Poller pull booking mới từ OTA extranet
- Enqueue
pull_bookings→ service normalize → Prisma tạoBooking+Customer - Emit alert nếu tồn kho chạm trần →
alerts.overbooking - Push availability mới lên tất cả OTA còn lại trong cùng property
- User nhận in-app notification qua WS, có thể escalate + chat nội bộ
5.3 Đổi rate cho nhiều property cùng lúc
- Rates → Bulk Apply — chọn properties + date range + rule
- Preview diff → confirm
- System gọi OTA adapter
push_ratestheo job queue - Ghi vào
activity_logđể audit
6. Ảnh demo
TODO — bổ sung ảnh vào thư mục
docs/images/cms-introduction/với các shot sau. Hiện chưa có capture trong repo, dùng placeholder.
| # | Màn hình | Gợi ý file |
|---|---|---|
| 1 | Dashboard tổng quan | docs/images/cms-introduction/01-dashboard.png |
| 2 | Danh sách Booking + filter OTA | docs/images/cms-introduction/02-bookings-list.png |
| 3 | Booking detail + 4-axis workflow | docs/images/cms-introduction/03-booking-detail.png |
| 4 | OTA Accounts → Connect flow | docs/images/cms-introduction/04-ota-connect.png |
| 5 | Availability grid (inventory) | docs/images/cms-introduction/05-availability.png |
| 6 | Rates Bulk Apply | docs/images/cms-introduction/06-rates-bulk.png |
| 7 | Alerts center + thread | docs/images/cms-introduction/07-alerts.png |
| 8 | Workflow Designer | docs/images/cms-introduction/08-workflow-designer.png |
Cú pháp chèn ảnh:
7. Tính năng khác biệt
- Overbooking prevention < 60s — sync cross-OTA trong một job chain
- Multi-country scoped access — staff VN chỉ thấy property VN; manager switch quốc gia
- Encrypted credentials — AES-256-GCM + optional TOTP 2FA; không lưu password plain-text
- Unified booking status — một booking có 4 trục status (CS / Payment / Source / Accounting) thay vì 1 giá trị dễ mơ hồ
- Extensible BPM engine — workflow designer kéo thả, dùng chung cho onboarding + booking + operations
- Realtime chat — DM + booking comment, Redis pub/sub fanout, in-app notifications đính kèm
- Formula templates — tính net/gross rate khác nhau theo từng OTA (promote % + commission %)
8. Gợi ý tích hợp OTA Review
User muốn: thêm luồng pull reviews từ OTA để nội bộ phản hồi / phân tích sentiment / gửi lại OTA.
Hiện PTX-CM sync booking + availability + rates, chưa sync reviews. Dưới đây là API cần đăng kí ở mỗi sàn. Tất cả đều cần partner certification — không có API public cho end-user property.
8.1 Booking.com Connectivity
| Endpoint | Mục đích | Yêu cầu |
|---|---|---|
GET /reviews | Pull review theo hotel_id, filter date range | Connectivity Partner level |
POST /reviews/{id}/response | Reply review của property | Có quyền reviews.write |
GET /review-scores | Score tổng hợp + breakdown 6 tiêu chí | Partner portal |
Webhook review.new | Push event khi có review mới (thay vì poll) | Phải đăng kí subscription |
Docs: Booking.com Connectivity Portal → Reviews API v2.
8.2 Agoda YCS
| Endpoint | Mục đích |
|---|---|
GET /api/ycs/reviews | List review theo property id |
POST /api/ycs/reviews/{id}/reply | Respond |
GET /api/ycs/reviews/summary | Aggregate score |
Agoda yêu cầu đăng kí YCS (Yield Control System) partner; review API nằm trong bundle property management, không phải affiliate API.
8.3 Expedia EQC / Rapid
| Endpoint | Mục đích |
|---|---|
GET /v1/properties/{propertyId}/reviews | List review (Rapid API) |
POST /v1/properties/{propertyId}/reviews/{reviewId}/response | Reply |
Webhook review.posted | Realtime push |
Expedia cần EPC (Expedia Partner Central) credential hoặc Rapid API key. Reviews nằm trong scope marketing.read.
8.4 Traveloka TravelokaConnect
Review API của Traveloka còn beta, thường qua portal export:
| Endpoint | Mục đích |
|---|---|
GET /tva/reviews | Export review CSV/JSON theo property |
POST /tva/reviews/{id}/respond | Reply |
Nếu API unavailable → fallback scraping portal với session (giống flow OTA credential hiện tại).
8.5 Data model đề xuất (mở rộng Prisma)
model OtaReview {
id String @id @default(uuid()) @db.Uuid
otaAccountId String @map("ota_account_id") @db.Uuid
propertyId String @map("property_id") @db.Uuid
bookingId String? @map("booking_id") @db.Uuid // nếu mapped được
otaReviewId String @map("ota_review_id") @db.VarChar(100) // id bên OTA
otaType OtaType
guestName String? @db.VarChar(255)
score Decimal @db.Decimal(3, 1) // 0.0–10.0
title String? @db.VarChar(500)
body String? @db.Text
language String? @db.VarChar(10)
stayDate DateTime? @map("stay_date") @db.Date
postedAt DateTime @map("posted_at") @db.Timestamptz
response String? @db.Text
respondedAt DateTime? @map("responded_at") @db.Timestamptz
sentiment String? @db.VarChar(20) // positive | neutral | negative
pulledAt DateTime @default(now()) @map("pulled_at") @db.Timestamptz
otaAccount OtaAccount @relation(fields: [otaAccountId], references: [id], onDelete: Cascade)
property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade)
booking Booking? @relation(fields: [bookingId], references: [id], onDelete: SetNull)
@@unique([otaType, otaReviewId], name: "uq_ota_review")
@@index([propertyId, postedAt(sort: Desc)])
@@index([sentiment])
@@map("ota_reviews")
}8.6 Sync flow đề xuất
BullMQ queue "ota-reviews-pull"
├─ every 1h (per active OtaAccount)
├─ adapter.listReviews(since=lastPulledAt)
├─ upsert OtaReview rows
├─ classify sentiment
└─ emit WS event "review.new" → notification center8.7 Roadmap rollout
| Phase | Scope |
|---|---|
| 1 | Schema + Booking.com adapter (thị trường lớn nhất) |
| 2 | Agoda + Expedia adapters |
| 3 | Reply flow + audit log |
| 4 | Sentiment analysis + dashboard analytics |
| 5 | Traveloka (bị động, deferred nếu API beta chưa ổn) |
9. Vận hành hiện tại
- Realtime: Redis pub/sub cross-pod, WS stateless API replicas
- Background jobs: BullMQ cho
ota-polling,push-availability, email notifications - Monitoring: Structured JSON logs, metrics qua logger event (
metric.*) - Disaster recovery: playbook trong
docs/disaster-recovery.md - Testing: Jest (api), vitest + RTL (web), chaos tests cho chat subsystem
10. Tham khảo thêm
- Full PDR:
project-overview-pdr.md - Architecture diagrams + ERD:
system-architecture.md,DB_DESIGN.md - API contract:
API_SPEC.md - UI Spec:
UI_SPEC.md - Runbooks:
runbooks/
Unresolved questions
- Cần clarify: OTA review có phải feature ưu tiên Q2/Q3 không? Ảnh hưởng schema + roadmap.
- Booking.com Connectivity Partner application — bạn đã có cert chưa, hay cần bắt đầu?
- Sentiment analysis: Lựa chọn giải pháp phân tích và chi phí + privacy (review chứa guest name).
- Ảnh demo — screenshot từ staging hay production? Cần team marketing cung cấp.