Danh mục:
1. Vì sao phải thiết kế bài bản?
Giỏ hàng (Cart) và đơn hàng (Order) là trái tim của hệ thống thương mại điện tử:
- Mọi luồng thanh toán, tồn kho, logistics, marketing đều xoay quanh chúng
- Nếu thiết kế sai, rất dễ gây lỗi số lượng, lỗi thanh toán, khó mở rộng sau này
- Đây là vùng giao dịch (transactional domain) quan trọng, cần đảm bảo tính nhất quán dữ liệu cao
2. Tổng quan luồng nghiệp vụ
[Người dùng thêm SP vào giỏ]
↓
[Giỏ hàng tạm thời (Cart)]
↓ → (Xác thực tồn kho, tính phí)
[Chuyển sang đơn hàng (Order Draft)]
↓
[Xác nhận thanh toán → Order Confirmed]
↓
[Xử lý giao hàng → Order Shipped]
↓
[Hoàn tất → Order Completed]
Giỏ hàng thường không ràng buộc tính pháp lý, trong khi đơn hàng là bản ghi chính thức để giao dịch.
3. Thiết kế module Giỏ hàng (Cart)
Cấu trúc dữ liệu
cart_id, user_id (có thể null nếu chưa đăng nhập)
cart_items[]: { product_id, variant_id, quantity, price_snapshot, added_at }
discounts, voucher_codes, shipping_option, taxes
expires_at: thời điểm hết hạn giỏ hàng
Logic nghiệp vụ
- Tạo mới giỏ khi người dùng thêm sản phẩm đầu tiên
- Lưu price_snapshot để không bị thay đổi nếu giá gốc thay đổi
- Kiểm tra tồn kho sơ bộ khi tăng số lượng
- Đồng bộ giỏ hàng tạm (guest) vào tài khoản sau khi đăng nhập
Lưu trữ
- Lưu vào Redis (in-memory) để thao tác nhanh
- Định kỳ flush giỏ cũ sang DB hoặc xóa nếu hết hạn
4. Thiết kế module Đơn hàng (Order)
Cấu trúc dữ liệu
order_id, user_id, status (draft, confirmed, shipped, completed, cancelled)
order_items[]: { product_id, variant_id, quantity, unit_price, total }
shipping_address, billing_address
payment_method, payment_status
shipping_status, tracking_code
discounts, taxes, voucher_applied
created_at, updated_at
Luồng nghiệp vụ
- Tạo đơn hàng draft từ giỏ
- Xác thực tồn kho + giá cuối
- Khóa tồn kho (stock reservation) → tránh oversell
- Chờ thanh toán (pending) → nếu thanh toán thành công → confirmed
- Xử lý giao hàng → shipped
- Hoàn tất / trả hàng / hủy đơn
Tránh dùng giỏ hàng = đơn hàng vì dễ lẫn lộn trạng thái.
5. Các vấn đề kỹ thuật cần lưu ý
Tính nhất quán dữ liệu
- Dùng transaction hoặc Saga pattern khi thao tác nhiều bảng
- Với microservices: truyền sự kiện qua message broker (Kafka / RabbitMQ)
Hiệu năng
- Caching giỏ hàng bằng Redis
- Dùng CQRS pattern để tách đọc/ghi đơn hàng nếu tải lớn
Bảo mật
- Chỉ người sở hữu mới được xem/chỉnh giỏ và đơn
- Xác thực thanh toán bằng token và chữ ký số (HMAC)
6. Gợi ý mở rộng
- Hỗ trợ đa loại sản phẩm (digital, physical, subscription)
- Tích hợp chương trình khách hàng thân thiết (tích điểm)
- Hỗ trợ split shipment: chia đơn nhiều nhà kho
- Cho phép pre-order, backorder
7. Kết luận
- Thiết kế chuẩn module giỏ hàng & đơn hàng là bước nền cực quan trọng khi xây dựng hệ thống thương mại điện tử hiện đại.
- Giỏ hàng: tạm thời, linh hoạt, hiệu năng cao
- Đơn hàng: chính thức, bền vững, đảm bảo tính toàn vẹn dữ liệu
Hãy xem chúng như hai domain riêng biệt có lifecycle khác nhau, thay vì gộp chung một bảng.