Skip to content

PRD: Thiết lập & vòng đời khuyến mãi

ModuleCampaignPRD IDPRD-PRM-001
Trạng tháiSẵn sàng devFEATPRM
EpicPlaneBANA-1492
Ngày2026-03-23Phiên bảnv1.0
Gói@nx/pricingURDPRM
SurfaceClient · Chủ/QL
Phụ tráchPhát Nguyễn

TL;DR

Merchant tạo một khuyến mãi trong một thao tác - phương thức giảm giá (phần trăm hoặc cố định), điều kiện áp dụng/nguồn/mục tiêu, khung thời gian hiệu lực, giới hạn sử dụng - rồi cho nó chạy qua vòng đời rõ ràng DRAFT → ACTIVATED → DEACTIVATED/EXPIRED/ARCHIVED. Mỗi khuyến mãi nằm gọn trong merchant của chính nó, nên mỗi gian hàng tự sở hữu ưu đãi của mình từ đầu đến cuối.

1. Bối cảnh & Vấn đề

Merchant muốn dùng giảm giá có mục tiêu để thúc đẩy doanh số, nhưng pricing mới chỉ biết fare và điều kiện của fare - chưa có khái niệm khuyến mãi, chưa có phương thức giảm giá, chưa có vòng đời. Merchant không có cách nào tạo một giảm giá có cấu trúc, nói rõ nó áp cho ai và cái gì, giới hạn số lần dùng, hay lên lịch khi nào nó chạy.

Increment này biến khuyến mãi thành một khái niệm pricing hạng nhất. Điều kiện được tổng quát hóa để fare và khuyến mãi dùng chung một model điều kiện áp dụng/nguồn/mục tiêu; ghép một khuyến mãi với phương thức giảm giá cho merchant đầy đủ quyền tạo/sửa/xóa, một khung thời gian hiệu lực, một giới hạn sử dụng, và một vòng đời theo trạng thái. Mỗi khuyến mãi nằm gọn trong phạm vi của chính merchant sở hữu nó, nên mỗi gian hàng sở hữu danh mục ưu đãi của riêng mình.

2. Mục tiêu & Ngoài phạm vi

Mục tiêu

  • Một khuyến mãi đi cùng phương thức giảm giá là khái niệm pricing hạng nhất, được tạo cùng phương thức và điều kiện trong một thao tác nguyên tử duy nhất.
  • Một phương thức giảm giá trên khuyến mãi: FIXED / PERCENTAGE, với một loại mục tiêu và một chiến lược phân bổ.
  • Một điều kiện tái sử dụng cho quy tắc áp dụng, nguồn và mục tiêu - chia sẻ với fare.
  • Một vòng đời theo trạng thái mặc định DRAFT, bao gồm DRAFT → ACTIVATED → DEACTIVATED / EXPIRED / ARCHIVED.
  • Một khung thời gian hiệu lực và một trường giới hạn sử dụng cho mỗi khuyến mãi (giới hạn được kiểm tra/tăng đếm ở thời điểm áp, sẽ đi cùng APP).
  • Loại khuyến mãi STANDARDBUY_GET.
  • Phạm vi theo từng merchant - mỗi khuyến mãi thuộc về đúng một merchant.

Ngoài phạm vi

3. Success Metrics

Chỉ sốMục tiêu / tín hiệu
Tính nguyên tử100% lần tạo khuyến mãi lưu khuyến mãi + phương thức + điều kiện cùng nhau, hoặc không lưu gì khi lỗi
Toàn vẹn vòng đờiMỗi khuyến mãi nằm ở đúng một trạng thái trong tập vòng đời chuẩn, mặc định DRAFT (chưa thực thi kiểm tra thứ tự chuyển trạng thái - trạng thái đổi qua thao tác update chung)
Cô lập tenancyMột merchant chỉ thấy và thay đổi khuyến mãi thuộc phạm vi của chính mình
Độ phủ thiết lậpMerchant có thể cấu hình ưu đãi phần trăm và cố định cùng điều kiện áp dụng/mục tiêu mà không cần kỹ sư hỗ trợ

4. Personas & Use Cases

PersonaMục tiêu trong tính năng này
OwnerTạo, kích hoạt và lưu trữ bất kỳ khuyến mãi nào của merchant
ManagerSoạn và quản lý khuyến mãi - phương thức, điều kiện, hiệu lực, giới hạn sử dụng

Kịch bản cốt lõi: tạo một khuyến mãi cùng phương thức và điều kiện trong một bước → đặt khung thời gian hiệu lực và giới hạn sử dụng → kích hoạt → sau đó hủy kích hoạt, để hết hạn, hoặc lưu trữ.

5. User Stories

  • Là một manager, tôi muốn tạo một khuyến mãi cùng phương thức giảm giá và điều kiện trong một bước, để ưu đãi được định nghĩa đầy đủ trong một thao tác duy nhất.
  • Là một manager, tôi muốn chọn phương thức FIXED hoặc PERCENTAGE với một loại mục tiêu và phân bổ, để giảm giá hoạt động đúng như chiến dịch cần.
  • Là một manager, tôi muốn định nghĩa điều kiện áp dụng, nguồn và mục tiêu, để khuyến mãi chỉ áp cho đúng khách hàng và sản phẩm.
  • Là một manager, tôi muốn đặt một khung thời gian hiệu lực và một giới hạn sử dụng, để ưu đãi chạy trong một khoảng cố định và không bị dùng quá mức.
  • Là một owner, tôi muốn đưa một khuyến mãi qua vòng đời của nó (kích hoạt, hủy kích hoạt, hết hạn, lưu trữ), để tôi kiểm soát khi nào một ưu đãi đang chạy.
  • Là một owner, tôi muốn khuyến mãi chỉ gói gọn trong merchant của mình, để ưu đãi của tôi không bao giờ rò rỉ qua các gian hàng khác.

6. Functional Requirements

#Yêu cầuURD ref
FR-1Tạo một khuyến mãi cùng phương thức và điều kiện trong một thao tác nguyên tử (tất cả hoặc không gì khi lỗi)URD-PRM-001
FR-2Trạng thái vòng đời DRAFT → ACTIVATED / DEACTIVATED / EXPIRED / ARCHIVED, mặc định DRAFT (trường trạng thái đã có; chưa có guard kiểm tra thứ tự chuyển trạng thái cho khuyến mãi)URD-PRM-002
FR-3Phương thức giảm giá FIXED / PERCENTAGE, với loại mục tiêu và chiến lược phân bổURD-PRM-001
FR-4Định nghĩa điều kiện áp dụng, nguồn và mục tiêu qua điều kiện dùng chungURD-PRM-003
FR-5Loại khuyến mãi STANDARDBUY_GETURD-PRM-001
FR-6Các trường khung thời gian hiệu lực trên khuyến mãiURD-PRM-002
FR-7Trường giới hạn sử dụng cho mỗi khuyến mãi, kèm helper kiểm tra giới hạn và tăng đếm nguyên tử; thực thi ở runtime chạy tại thời điểm áp và chưa hoạt độngURD-PRM-004
FR-8Phạm vi theo từng merchant - mỗi khuyến mãi thuộc về một merchant, với tra cứu theo merchant và trạng tháiURD-PRM-001

Toàn văn yêu cầu và tiêu chí chấp nhận nằm trong Campaign URD. PRD này tham chiếu chúng thay vì lặp lại.

7. Non-Functional Requirements

Khía cạnhYêu cầu
Toàn vẹn dữ liệuKhuyến mãi, phương thức và điều kiện được tạo cùng nhau theo cách nguyên tử - lỗi một phần không để lại khuyến mãi ghi dở
Tính hợp lệ vòng đờiTrạng thái mặc định DRAFT và dùng các trạng thái vòng đời chuẩn (không trạng thái tự chế); chưa có state machine kiểm tra thứ tự chuyển trạng thái (khác với fare set vốn đã guard chuyển trạng thái)
Tenancy & authzMọi thao tác gói gọn trong merchant của chính người dùng; được kiểm soát bởi permission khuyến mãi
Tái sử dụngĐiều kiện được chia sẻ giữa fare và khuyến mãi - một model điều kiện, hai bên dùng
CascadeXóa một khuyến mãi sẽ cascade tới phương thức và điều kiện của nó
i18nNhãn/trạng thái hiển thị cho người dùng là song ngữ (tiếng Anh + tiếng Việt)

8. UX & Flows

Màn hình chính (trong app quản trị của merchant): màn hình danh sách khuyến mãi, cùng tạo/sửa khuyến mãi cho phương thức, điều kiện, khung thời gian hiệu lực và giới hạn sử dụng.

9. Data & Domain

Khái niệmVai trò
Khuyến mãiTài liệu khuyến mãi - loại, trạng thái, khung thời gian hiệu lực, giới hạn sử dụng, merchant sở hữu
Phương thức giảm giáPhương thức giảm giá - FIXED/PERCENTAGE, loại mục tiêu, chiến lược phân bổ
Điều kiệnĐiều kiện áp dụng/nguồn/mục tiêu dùng chung (tái sử dụng bởi fare và khuyến mãi)

Chỉ ở mức khái niệm - schema và bất biến đầy đủ nằm trong pricing domain modeltài liệu promotion.

10. Dependencies & Assumptions

Phụ thuộc vào

  • Điều kiện dùng chung - tổng quát hóa từ điều kiện fare để khuyến mãi và fare dùng chung một model điều kiện.
  • Sản phẩm (Sản phẩm) - điều kiện mục tiêu tham chiếu sản phẩm và danh mục.
  • Khách hàng (Khách hàng) - điều kiện áp dụng tham chiếu phân khúc khách hàng.

Giả định

  • Kỳ vọng một khuyến mãi có phương thức hợp lệ trước khi kích hoạt (ràng buộc C-01); điều này chưa được thực thi trong code - kích hoạt là một thao tác đổi trạng thái thông thường, không có guard phương thức.
  • Mỗi merchant sở hữu khuyến mãi của riêng mình; mọi khuyến mãi đều gắn với một merchant.

11. Risks & Open Questions

Rủi ro / câu hỏiGiảm thiểu / trạng thái
Ghi khuyến mãi/phương thức/điều kiện có thể lệch khi lỗi một phầnĐược tạo nguyên tử như một đơn vị - tất cả hoặc không gì
Tổng quát hóa điều kiện fare thành điều kiện dùng chung có thể phá vỡ các bên dùng fareĐiều kiện dùng chung đã được kiểm chứng trên cả fare và khuyến mãi
Khuyến mãi được cấu hình nhưng chưa áp khi thanh toánChấp nhận - áp giảm giá là tính năng APP riêng (P2); tính toán giảm giá ngoài phạm vi ở đây
Kích hoạt một khuyến mãi mà không có phương thứcRàng buộc C-01 (cần phương thức trước khi kích hoạt) đã được nêu nhưng chưa thực thi - hiện chưa có guard kích hoạt; sẽ bổ sung cùng đường áp giảm giá

12. Release Plan & Launch Criteria

Khía cạnhKế hoạch
PhaseP1 (nền tảng) - xem URD feature catalog
RolloutTất cả merchant; không feature flag
MigrationBản ghi khuyến mãi và phương thức giảm giá mới; điều kiện fare được tổng quát hóa thành điều kiện dùng chung; thêm quyền sở hữu theo merchant cho khuyến mãi
Tiêu chí ra mắtTạo nguyên tử lưu khuyến mãi + phương thức + điều kiện; trạng thái mặc định DRAFT và cập nhật trạng thái hoạt động được; cô lập theo từng merchant được kiểm chứng; danh sách phía client render được
Giám sátSố khuyến mãi mỗi merchant, tỷ lệ lỗi tạo, lỗi chuyển trạng thái vòng đời

13. FAQ

Phương thức và điều kiện của một khuyến mãi có được tạo riêng không? Không - khuyến mãi, phương thức và điều kiện được tạo cùng nhau trong một thao tác nguyên tử; khi lỗi không lưu gì.

Những phương thức giảm giá nào được hỗ trợ? FIXEDPERCENTAGE, mỗi loại có một loại mục tiêu và một chiến lược phân bổ.

Vòng đời là gì? Một khuyến mãi bắt đầu ở DRAFT và đi qua ACTIVATED → DEACTIVATED / EXPIRED / ARCHIVED.

Kích hoạt một khuyến mãi có áp giảm giá khi thanh toán không? Chưa - thiết lập và trường trạng thái vòng đời đã hoạt động, nhưng tự áp/coupon khi thanh toán là tính năng Áp giảm giá riêng (APP, P2). Tính toán giảm giá có trong codebase nhưng chưa được bật, nên việc tính giảm giá, thực thi giới hạn sử dụng và guard phương thức khi kích hoạt đều ngoài phạm vi ở đây.

Một khuyến mãi có thể chia sẻ qua nhiều merchant không? Không - mỗi khuyến mãi chỉ gói gọn trong phạm vi của đúng một merchant; một merchant chỉ thấy và thay đổi khuyến mãi của mình.

References

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.