Coupons (Discount Codes)

The edX Marketing Team would like to offer discounts to students in an effort to entice users to upgrade to verified seats. Specifically, the team wishes to offer discounts in percentage form (e.g. 10% off) or fixed amount form (e.g. $10 off). Otto has support for both types of discounts, applied to single items or entire baskets of items, as well as practically any combination of conditional discounts we can imagine.

Definitions

Otto is built atop django-oscar which has an existing concept of coupons. Below are definitions of those concepts as well as others that will be used throughout this document.

  • Benefit: The discount a shopper receives when an offer is applied to a basket. Examples include a percentage or fixed amount off the price of an item.

  • Catalog: Specific to edX multi-tenancy extension. A collection of one, or more, products sold by a single Partner.

  • Condition: Criteria for an offer to be applied to a basket. Examples include requiring a minimum number of items in the basket, or minimum basket price.

  • Conditional Offer: A discount applied if a basket meets specific criteria. Such discounts can be made available to all users, a subset of users (specified in code), users with a voucher, or for a single user session.

  • Discount Code: Synonym for coupon code or voucher.

  • Partner: Specific to edX multi-tenancy extension. A tenant of the Otto service (e.g. edX, MIT Professional Education).

  • Range: A collection of products to which an offer can be applied. This is a django-oscar concept that we propose extending to include the edX concept of catalogs.

  • Voucher: A code, normally entered by the user during the checkout flow, that links to a conditional offer. Can be single-use (usable once by one customer), multi-use (usable many times by many customers, or once-per-customer.

Data Model

The underlying data models exist already; however, we will need to update it to add support for multi-tenancy.


Specific changes include:

  1. adding a foreign key to Catalogs on the Range model,

  2. adding a foreign key to the Partners on the Conditional Offer model.

The Range model is django-oscar's method of grouping products to which an offer can be applied; however, given our need for multi-tenancy, edX uses the Catalog model to group products. The foreign key, and the addition of a few methods, helps us achieve the linking without drastically overhauling the existing models.

Similarly, the foreign key to Partners on the Conditional Offer model aids in making offers multi-tenant-friendly.

These changes, coupled with validation when applying offers to baskets will ensure that offers and vouchers for one partner cannot be mistakenly applied to baskets containing products from another partner.

Code Changes

As previously mentioned, much of the code for the coupons functionality already exist. Nevertheless, a few changes will be needed to add support for multi-tenancy:

  • Add products() and has_products() methods to Catalog model to aid in determining if an offer should be applied to a basket.

  • Update offer application code to only apply offers if the Partner for the offer matches the Partner of the items in the basket.

Additionally, existing checkout code will need to be updated to apply site-wide offers (e.g. 10% off all products) to baskets.

API

API endpoints will be needed to expose models for creation, reading, and updating. The API will primarily be consumed by tools used to manage discounts, and the checkout page (to apply a voucher to an order).

Additional Information