1) Vì sao cần Promotion Engine riêng biệt?

  • Marketing cần triển khai hàng trăm chiến dịch khuyến mãi song song
  • Giảm giá, flash sale, voucher, combo, free shipping… rất đa dạng
  • Phải đảm bảo áp dụng đúng điều kiện, không xung đột, không gây lỗi thanh toán
  • Cần tracking hiệu quả khuyến mãi để ra quyết định kinh doanh
  • Các sàn lớn như Shopee, Lazada… có Promotion Engine riêng tách khỏi hệ thống giỏ hàng/đơn hàng.

2) Tổng quan kiến trúc

[Client: Web/App]
   ↓
[Cart/Checkout Service] 
   ↓
[Promotion Engine]
   ↓
[Pricing Engine] → [Order Service]
   ↓
[Analytics / Campaign Dashboard]
Promotion Engine hoạt động như bộ máy tính toán khuyến mãi độc lập, nhận dữ liệu giỏ hàng + user → trả về danh sách khuyến mãi áp dụng và số tiền giảm.

3) Các loại khuyến mãi phổ biến

Screenshot 2025-09-19 111716.png

4) Thiết kế dữ liệu Promotion

promotion
promotion_id, name, type (percent/fixed/threshold/flash/voucher…)
start_at, end_at, status
conditions: JSON (min_amount, category_id, product_id, user_segment…)
rewards: JSON (discount_percent, fixed_amount, free_shipping…)
max_uses_per_user, total_uses_limit
priority (giải quyết xung đột)
voucher
code, promotion_id, assigned_to_user, used_count, max_use
Dùng JSON schema linh hoạt để marketing tự tạo nhiều loại campaign mà không cần dev thêm field mới.

5) Luồng xử lý tính khuyến mãi

  1. Cart gửi request calculatePromotions(cart_id, user_id)
  2. Promotion Engine:
Lọc các promotion đang active
Kiểm tra điều kiện (conditions) → đủ điều kiện thì áp dụng
Ưu tiên theo priority → tránh trùng hoặc cộng dồn không mong muốn
Trả về danh sách promotion + tổng số tiền giảm
  1. Pricing Engine áp dụng số tiền giảm vào cart
  2. Khi user thanh toán thành công → mark promotion_used
Có thể hỗ trợ “stackable promotions” (cộng dồn) hoặc exclusive (chỉ áp dụng 1).

6) Flash Sale / Limited Stock

  • Mỗi khuyến mãi flash có stock_limit riêng
  • Khi checkout → gọi reservePromotionStock() (giống cơ chế giữ hàng)
  • Dùng Redis + atomic decrement để tránh oversell
  • Hết số lượng → tự động tắt khuyến mãi hoặc chuyển giá gốc

7) Performance & Scalability

  • Dùng cache (Redis) để lưu promotion active
  • Tránh query DB mỗi lần tính toán
  • Dùng rule engine (Drools / custom DSL) để marketing tự định nghĩa điều kiện
  • Dùng event-driven (Kafka) để đồng bộ cập nhật promotion

8) Tích hợp với hệ thống khác

  • Cart Service: gửi dữ liệu sản phẩm → nhận về tiền giảm
  • Order Service: xác nhận promotion đã dùng, đảm bảo tính nhất quán
  • Inventory Service: giảm kho với flash sale
  • Analytics: log promotion được áp dụng → tính ROI từng chiến dịch
  • CMS: hiển thị banner campaign liên kết với promotion_id
9) Bảo mật và hạn chế gian lận
  • Giới hạn max_uses_per_user, max_use_per_ip
  • Gắn voucher vào user_id để không chia sẻ được
  • Kiểm tra device_id, cookie_id tránh abuse tạo nhiều tài khoản
  • Chống sửa request bằng chữ ký HMAC giữa client và server

10) Kết luận

Promotion Engine là “cỗ máy tạo doanh thu” trong hệ thống thương mại điện tử:
  • Cho phép marketing tự tạo hàng trăm campaign phức tạp
  • Tách biệt khỏi logic đơn hàng → giảm rủi ro
  • Dễ mở rộng, scale cao trong mùa sale
  • Theo dõi hiệu quả để tối ưu chiến lược
Gợi ý: Khi mới bắt đầu, hãy hỗ trợ 3 loại cơ bản (percent, fixed, threshold), sau đó dần bổ sung flash sale, voucher, bundle.