9.1 KiB
Kiến Trúc Hệ Thống: Tính Năng Lập Kế Hoạch Du Lịch (Travel Planning Feature)
Tài liệu này mô tả kiến trúc tổng thể, mô hình dữ liệu và các giải pháp kỹ thuật cho tính năng lập kế hoạch du lịch đa người dùng thuộc nền tảng Travel.
1. Kiến Trúc Tổng Quan (System Overview)
Hệ thống được thiết kế theo mô hình Client-Server kết hợp với kiến trúc Modular Monolith hoặc Microservices (tùy quy mô triển khai), chia làm 3 tầng chính:
- Frontend (Presentation Layer): Đảm nhiệm việc tương tác trực tiếp với người dùng, hiển thị bản đồ trực quan, quản lý luồng tạo tour/chặng và xử lý tải ảnh/hiển thị album.
- Backend (Business Logic Layer): Xử lý xác thực bảo mật, tính toán chi phí (quy tắc phân chia tiền), định tuyến đường đi ngắn nhất, lập lịch kiểm tra task (Cron job/Event-driven) và kiểm tra quyền truy cập (RBAC).
- Database & Storage (Data Layer): Lưu trữ dữ liệu quan hệ (PostgreSQL với extension PostGIS để xử lý tọa độ địa lý) và lưu trữ tệp tin hình ảnh riêng biệt (Object Storage như AWS S3 hoặc MinIO).
2. Công Nghệ Đề Xuất (Tech Stack)
| Thành phần | Công nghệ đề xuất | Lý do lựa chọn |
|---|---|---|
| Frontend | React / Next.js + TailwindCSS | Tối ưu cho ứng dụng Single Page (SPA), quản lý trạng thái tốt, hỗ trợ SSR cho SEO nếu cần. |
| State Management | Zustand / Redux Toolkit | Quản lý state phức tạp của Tour, Chặng (Leg) và Chi phí. |
| Map Engine | Mapbox GL JS / Google Maps API / Leaflet | Hỗ trợ hiển thị bản đồ trực quan, marker kéo thả và tính toán định tuyến (Routing). |
| Backend | Node.js (NestJS hoặc Express) | Xử lý bất đồng bộ tốt, phù hợp hệ thống nhiều I/O và tích hợp mDNS/IoT nếu mở rộng sau này. |
| Database | PostgreSQL + PostGIS | Hệ quản trị cơ sở dữ liệu mạnh mẽ, PostGIS giúp tính toán khoảng cách và tọa độ địa lý chính xác. |
| File Storage | AWS S3 / MinIO | Lưu trữ ảnh tách biệt hoàn toàn khỏi Database để tối ưu hiệu năng. |
3. Mô Hình Dữ Liệu (Database Schema)
Dưới đây là các thực thể cốt lõi phục vụ tính năng:
3.1. User (Người dùng)
Lưu trữ thông tin định danh và trạng thái quản trị. Toàn bộ ID sử dụng định dạng UUID.
User:id,email,passwordHash,name,avatar,isAdmin,isBlocked,createdAt.
3.2. Tour & Phân quyền (RBAC)
Hệ thống sử dụng bảng trung gian để quản lý thành viên cho từng chuyến đi.
Tour:id,title,startDate,endDate,totalCost(Decimal),createdById(FK -> User).TourParticipant: Quản lý vai trò thành viên trong Tour qua enumParticipantRole:OWNER: Toàn quyền quản lý.MANAGER: Quản lý nội dung và thành viên.MEMBER: Thành viên chính thức (Xem được chi phí).MEMBER_NO_FINANCE: Thành viên không được xem thông tin tài chính.VIEWER_ONLY: Chỉ xem lộ trình và ảnh.
3.3. Lộ trình (Leg & Location)
Một Tour được chia thành nhiều chặng di chuyển (Leg), mỗi chặng chứa danh sách các điểm đến (Location).
Leg:id,tourId(FK),sequence(Thứ tự chặng),note.Location: Tích hợp tính năng theo dõi tiến độ (Thay thế khái niệmTaskcũ).- Tọa độ:
latitude,longitude. - Thời gian:
plannedStart,plannedEnd,actualStart,actualEnd. - Trạng thái (
LocationStatus):PENDING(Chờ),COMPLETED(Hoàn thành). - Loại địa điểm (
LocationType):MOVE,VISIT,REST,EAT.
- Tọa độ:
3.4. Chi phí (Expense)
Quản lý tài chính cho từng chặng hoặc gắn trực tiếp vào một địa điểm cụ thể.
Expense:id(UUID, PK),leg_id(UUID, FK),location_id(UUID, FK, Nullable),category(Enum:ACCOMMODATION,FOOD,TRANSPORT,TICKET,OTHER),amount(Decimal),description(Text).
3.5. Album Ảnh (Photo)
Lưu trữ tài nguyên đa phương tiện gắn với bối cảnh chuyến đi.
Photo:id,tourId(FK),locationId(FK, nullable),uploaderId(FK),imageUrl,privacy.- Cấp độ bảo mật (
PrivacyLevel):PUBLIC,TOUR_ONLY,PRIVATE.
- Cấp độ bảo mật (
4. Giải Pháp Kiến Trúc Cho Các Tính Năng Core
4.1. Thuật Toán Tìm Đường Ngắn Nhất (Shortest Path Routing)
- Cơ chế: Khi người dùng thêm các địa điểm vào một chặng, Frontend sẽ gửi danh sách tọa độ hình học (Lat, Lng) về Backend.
- Xử lý: Backend tích hợp với Mapbox Direction API hoặc chạy một instance OSRM (Open Source Routing Machine) cục bộ để giải bài toán Người đi giao hàng (TSP - Travelling Salesman Problem). Hệ thống sẽ sắp xếp lại thứ tự
sequence_in_legcủa cácplacesđể tối ưu tổng quãng đường hoặc thời gian di chuyển, sau đó trả về mảng tọa độ đường đi (Polyline) để Frontend vẽ lên bản đồ.
4.2. Engine Tính Toán Chi Phí & Chia Tiền (Expense Splitting Engine)
- Công thức tự động: * Tổng chi phí Tour (
T) =\sum \text{Expenses}của tất cả các chặng.- Hệ thống cho phép cấu hình số lượng Người lớn (
N_{adult}) và Trẻ em (N_{child}), kèm phần trăm giảm giá của trẻ em (P_{child\_discount}). - Gọi
Xlà chi phí của 1 người lớn:T = N_{adult} \times X + N_{child} \times \left( X \times (1 - P_{child\_discount}) \right) - Từ đó Backend tự động giải phương trình để tìm ra chi phí trung bình của người lớn (
X) và trẻ em, hiển thị báo cáo chi tiết ở cuối mỗi chặng và kết thúc tour.
- Hệ thống cho phép cấu hình số lượng Người lớn (
4.3. Theo Dõi Tiến Độ & Tính Toán Độ Lệch Thời Gian (Time Variance Tracking)
- Tự động (Auto-trigger): Một Worker/Cron-job chạy ngầm mỗi phút quét các
taskscó cài đặtAUTO_BY_TIME. Nếucurrent_time >= planned_timestampvà chưa hoàn thành, hệ thống tự động chuyểnis_completed = truevà ghi nhậncompleted_at = planned_timestamp. - Thủ công (Manual-trigger): Khi user bấm tích chọn hoàn thành, hệ thống ghi nhận ngay
completed_at = current_time. - Báo cáo thời gian (Time Summary): Backend tính toán hiệu số:
\Delta t = \text{completed\_at} - \text{planned\_timestamp}Đồng thời group dữ liệu theo loại hoạt động để xuất ra tổng thời gian: Di chuyển (dựa trên khoảng cách bản đồ), Tham quan (thời gian ở các địa điểm giải trí), Nghỉ ngơi (thời gian ở chỗ nghỉ).
4.4. Bảo Mật & Tách Biệt Album Ảnh (Photo Album Isolation)
- Tách biệt logic: Cơ sở dữ liệu ảnh liên kết qua mã
tour_idvàplace_idnhưng API endpoint kiểm tra quyền (/api/v1/tours/:id/photos) hoạt động độc lập với endpoint kế hoạch (/api/v1/tours/:id/plans). - Bảo mật phân quyền (Privacy Middleware): Trước khi trả về dữ liệu hình ảnh hoặc kế hoạch, hệ thống sẽ chạy qua một tầng Middleware để check quyền trong bảng
tour_members:// Giả lập Logic kiểm tra quyền truy cập thông tin tài chính/kế hoạch if (member.role === 'MEMBER_PHOTO_ONLY' && request.path.includes('/plans')) { throw new ForbiddenException("Bạn không có quyền xem kế hoạch và chi phí của tour này."); }
5. Thiết Kế Luồng Đi (Workflow Diagrams)
Luồng tạo chặng và tính toán đường đi (Frontend <=> Backend)
- User tìm kiếm/chọn địa điểm trên bản đồ -> Frontend cập nhật state cục bộ.
- User nhấn "Tối ưu đường đi" -> Frontend gửi danh sách
coords[]lên/api/v1/routing/optimize. - Backend gọi Mapbox/OSRM API -> Sắp xếp lại thứ tự tối ưu -> Lưu vào DB -> Trả về JSON chứa
optimized_placesvàpolyline_geometry. - Frontend render lại danh sách địa điểm theo thứ tự mới và vẽ nét đứt/đường đi trên Map.
Luồng chia sẻ hình ảnh và kiểm tra bảo mật
- User tải ảnh lên tại một địa điểm trong Tour.
- Frontend gửi file đến dịch vụ lưu trữ (S3) nhận về
image_url, sau đó lưu thông tin vào DB kèm metadata (ngày giờ, địa điểm). - Khi một User khác truy cập link Tour:
- Hệ thống check
tour_members. - Nếu thuộc diện External Viewer hoặc Photo Only: Ẩn hoàn toàn tab "Kế hoạch chặng hành trình" và "Tổng số tiền", chỉ hiển thị giao diện Grid hình ảnh (
album).
- Hệ thống check