Redeem Codes and Coupons: A Tale of Vouchers and Offers

We've been asked to support "100% redeem codes" by the end of Q3; "coupons" ("redeem codes" tied to discounts less than 100%) will likely need to be supported in the future. In light of this, we want to get an idea of how we'll support different types of discounting. Oscar ships with support for what it calls "vouchers," which are handled by the Voucher app. It's most likely the application we'll want to extend to model what we currently refer to as "redeem codes" and "coupons."

Voucher

A voucher in vanilla Oscar is a case-insensitive code containing no spaces which is entered at checkout. Vouchers associate a basket's contents (the order) with a collection of "offers," each of which is defined by availability, a benefit, and conditions for applying the benefit; offers are explored in more detail below.

By default, Oscar provides three usage models for its vouchers: "single use," "multi-use," and "once-per-customer." The first, "single use," corresponds closely to our idea of a "redeem code": a code which can be exchanged once for an enrollment. The discount "applied" by the code is a property of the offer underlying the voucher. Multi-use vouchers can help us offer "coupons" like site-wide promotional discounts (e.g., "enter LEARNCS at checkout for 20% off enrollments in computer science courses").

Vouchers are intended to be entered during checkout and aren't associated with any views of their own. Major e-commerce services like Steam operate in a manner consistent with this implementation: a valid "activation code" can be redeemed on one's dashboard by "Activating a Product on Steam." Similarly, we may want to provide an interface which can be used to "activate a product on edX." If we need to continue providing links which can be visited to redeem vouchers (instead of just codes that can be entered manually), we'll likely want to extend Oscar's implementation of Voucher to include a view which exposes checkout, pre-filling the voucher code for a basket populated by a set of products matching the offer which backs the code being used. This approach doesn't make the assumption that the discount associated with a voucher is 100%, making it more robust than the code activation mechanism which currently exists in edx-platform.

Offers

Offers in Oscar are the foundation of vouchers. Oscar's offers are "conditional," meaning that a customer's basket must satisfy some pre-determined condition within some fixed availability period in order to qualify for a specified benefit.

Oscar uses conditions to determine if a basket is eligible for a benefit. Oscar comes with three pre-defined conditions, but also includes a base Condition class which we can extend in order to create and register custom conditions. Conditions show up in the Oscar dashboard where they are linked to a range object, a subset of the product catalog to which the condition applies. The first of Oscar's built-in conditions is count-based, requiring the customer to purchase `count` products in order to qualify. The second is coverage-based, requiring the customer to purchase `count` distinct products in order to qualify. The third is value-based, requiring the customer to spend `value` on products in order to qualify.

An offer’s availability can be controlled by several settings which can be used in combination. These include date ranges, a maximum number of global, user, and basket-based "applications" (i.e., uses of the offer), and a maximum global discount (i.e., total amount of benefit given; for example, $10,000).

Oscar divides the benefits tied to offers into two categories: those benefits which apply to baskets, and those benefits which apply to shipping. Since we sell digital products, we most likely won't need to concern ourselves with shipping benefits (unless we start selling swag, like t-shirts). Basket benefits include fixed discounts (e.g., $5 off), percentage discounts (e.g., 5% off), fixed prices (e.g., $5 flat), and "multibuys" (i.e., get the cheapest product which meets the specified condition for free).

Data Model

Assuming we've defined a product catalog, it looks like we should be able to model "redeem codes" and "coupons" using Oscar's Voucher and Offers apps. The offer backing a "100% redeem code" for single enrollment products could be constructed using 1) a count-based condition with a value of 1, bound to a range of eligible enrollment products, and 2) a percentage discount benefit with a value of 100. Likewise for single enrollment "coupons"; the offer backing one could be constructed using 1) a count-based condition with a value of 1, bound to a range of eligible enrollment products, and 2) a percentage discount benefit with a value between 0 and 100. Vouchers would then be used to link baskets to these offers.

For Further Consideration

This discovery has produced a few points requiring further consideration as we develop our new e-commerce infrastructure.

First, we need to agree on accurate and precise terms which can be used when discussing this component of our e-commerce infrastructure amongst ourselves, with Product, and with Marketing. I want us to avoid the "register" vs. "enroll" confusion which plagued us for so long in edx-platform. I propose using the term "code" as a base. A code can be further qualified as either a "fixed discount" (e.g., $5 off), "percentage discount" (e.g., 5% off), or "fixed price" (e.g., $5 flat) code. Percentage discount codes which are tied to an offer with a 100% off benefit may be referred to as "activation codes."

Second, should vouchers be considered products in their own right? For example, I may want to purchase an activation code for a friend which she can use to take a paid course for free.