Vì sao quan trọng? Quy tắc giá, conflict lịch, voucher nằm trong shared/ — frontend và backend không thể “lệch nhau”. Đây là bài học cốt lõi khi dạy backend cho dự án SME.
Một request đặt lịch đi qua Express → PostgreSQL → trạng thái pending/completed
~118 API endpoint — nhóm theo domain
Module
Ví dụ route
Bài học
Users
POST /api/users/login
Auth, hash password, validation
Booking
POST /api/appointments
Conflict check, pricing server-side
Wallet
POST /api/transactions
State machine pending → completed
Reviews
GET /api/reviews/recent
Filter 5★ + join tên dịch vụ
Chat
POST /api/chat/messages
CRUD, read receipt, admin threads
Admin
GET /api/admin/chat/threads
requireOwner, phân quyền
3 pattern code đáng học trên lớp NodeJS
1. Logic dùng chung — shared/priceRound.ts
Giá slot làm tròn lên số nguyên; hóa đơn giữ 2 số thập phân. Một file — client preview và server tính tiền cùng kết quả.
2. Trạng thái lịch — shared/appointmentStatus.ts
countsTowardRevenue() chỉ trả true khi completed. appointmentStatusSync.ts tự chuyển pending khi qua giờ hẹn — giảm phụ thuộc thao tác tay lễ tân.
3. Repository mỏng — server/storage.ts
Route không viết SQL trực tiếp. Ví dụ getRecentReviews(): filter rating = 5, map thêm serviceName từ bảng services.
Migration khi boot server
Dự án dùng CREATE TABLE IF NOT EXISTS và ALTER TABLE ... ADD COLUMN IF NOT EXISTS trong routes.ts — phù hợp deploy single-server (Render, VPS). Học viên hiểu trade-off: nhanh go-live vs migration tool chuyên nghiệp (Prisma migrate, Flyway).