Skip to content

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

RoleQuan tâm chính
Property Manager / OwnerTồn kho chính xác, doanh thu, tránh overbooking
CS / Front-deskXử lí booking, chat nội bộ, escalation
AccountingThanh toán, đối soát OTA, hoa hồng
OperationsSLA, workflow, alert, audit
Admin / HQMulti-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/.

ModuleChức năng chính
BookingsDanh sách booking đa OTA, booking detail, workflow 4-axis (CS / Payment / Source / Accounting), escalation, comment thread nội bộ
OTA AccountsKết nối OTA (encrypted credentials AES-256-GCM), test session, 2FA (TOTP / manual), map room type → rate plan
PropertiesQuản lí property, room types, phân quyền manager
RatesBase rates, bulk apply, bulk ops, rate rules (markup / discount / seasonal)
AvailabilityReal-time inventory grid, overbooking alert
Customers / SuppliersCRM nhẹ cho khách + đối tác, đa quốc gia
Sync JobsLịch sử sync OTA (polling mỗi 150s), retry, failure drill-down
AlertsOverbooking, session expired, SLA breach, missing deposit, unconfirmed check-in
WorkflowsBPM engine: phase gate, status transition, designer UI, visibility rule
ChatDM + booking comment thread, realtime WS, mentions, attachments
NotificationsIn-app inbox + email; Chat mention, booking event, alert, system
Master DataCountries, booking statuses (CS/payment/source/accounting), OTA status mapping, formula templates
LogsAudit log, activity log
Settings / ProfileUser 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

  1. Manager vào OTA Accounts → Connect
  2. Nhập credentials (mã hóa trước khi lưu)
  3. Hệ thống test session → ghi nhận active | expired | error | requires_2fa
  4. Map room type → OTA rate plan
  5. Bật sync — cron ota-polling chạy 150s/lần

5.2 Booking đến từ OTA

  1. Poller pull booking mới từ OTA extranet
  2. Enqueue pull_bookings → service normalize → Prisma tạo Booking + Customer
  3. Emit alert nếu tồn kho chạm trần → alerts.overbooking
  4. Push availability mới lên tất cả OTA còn lại trong cùng property
  5. 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

  1. Rates → Bulk Apply — chọn properties + date range + rule
  2. Preview diff → confirm
  3. System gọi OTA adapter push_rates theo job queue
  4. 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ìnhGợi ý file
1Dashboard tổng quandocs/images/cms-introduction/01-dashboard.png
2Danh sách Booking + filter OTAdocs/images/cms-introduction/02-bookings-list.png
3Booking detail + 4-axis workflowdocs/images/cms-introduction/03-booking-detail.png
4OTA Accounts → Connect flowdocs/images/cms-introduction/04-ota-connect.png
5Availability grid (inventory)docs/images/cms-introduction/05-availability.png
6Rates Bulk Applydocs/images/cms-introduction/06-rates-bulk.png
7Alerts center + threaddocs/images/cms-introduction/07-alerts.png
8Workflow Designerdocs/images/cms-introduction/08-workflow-designer.png

Cú pháp chèn ảnh:

md
![Dashboard](./images/cms-introduction/01-dashboard.png)

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

EndpointMục đíchYêu cầu
GET /reviewsPull review theo hotel_id, filter date rangeConnectivity Partner level
POST /reviews/{id}/responseReply review của propertyCó quyền reviews.write
GET /review-scoresScore tổng hợp + breakdown 6 tiêu chíPartner portal
Webhook review.newPush 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

EndpointMục đích
GET /api/ycs/reviewsList review theo property id
POST /api/ycs/reviews/{id}/replyRespond
GET /api/ycs/reviews/summaryAggregate 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

EndpointMục đích
GET /v1/properties/{propertyId}/reviewsList review (Rapid API)
POST /v1/properties/{propertyId}/reviews/{reviewId}/responseReply
Webhook review.postedRealtime 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:

EndpointMục đích
GET /tva/reviewsExport review CSV/JSON theo property
POST /tva/reviews/{id}/respondReply

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)

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 center

8.7 Roadmap rollout

PhaseScope
1Schema + Booking.com adapter (thị trường lớn nhất)
2Agoda + Expedia adapters
3Reply flow + audit log
4Sentiment analysis + dashboard analytics
5Traveloka (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


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.

PTX Channel Manager — Internal Documentation