Copyright notice: This article is the blogger’s original article, shall not be reproduced without the permission of the blogger. The author can be reached at jishuhui_2015.

The core of the coupon system lies in the management, distribution and use of coupons.

The usual design perspective is from the end user, the so-called “what you see is what you get”, the end user sees a variety of coupons, is the challenge of developing the whole system.

It can be imagined that in order to coordinate with different forms of online and offline activities, the coupon system is bound to be greatly modified. How to minimize the cost of modification has become the most core challenge.

In this case, the solution is to separate rules from execution.

The rule layer is the use limit of all kinds of coupons, and the effect that can be achieved.

The executive layer can be understood as calculating the final transaction price according to the rules.

For the rules layer, I don’t want to elevate it to the level of a rules engine, just do a proper abstraction. Moreover, the existing rules engine development framework may not be able to meet the complex application scenario of coupons.

It is important to note that coupons are not equivalent to any kind of discount promotion, but are part of the overall marketing system. Compared to coupons, promotion systems are even more difficult to implement. The purpose of this article is to explain how to develop a coupon system, the design and implementation of promotional activities is not the scope of this article.

First, how to generate coupons

Before generating a coupon, let’s take a look at the concept of a coupon template.

As the name suggests, follow the template to generate coupons.

Just like the mold on the industrial production line, only need to inject raw materials for processing, can be made into finished products.

Therefore, the template carries a lot of information about coupons, including but not limited to name, timeliness, various discount rules, and coupon denomination. The template itself also has the title, status, creator and other basic information.

When you need to generate coupons, specify which template and fill in the total number of coupons to be generated. You can also specify the recipient during the process of generating coupons to complete the distribution of coupons.

Maybe readers can’t help asking: this design seems to be a little redundant, the coupon template and the coupon entity overlap a lot of attributes, why not directly skip the link of the coupon template, directly generate coupons?

There are two reasons for this:

First, do not want to repeatedly input the same coupon information, as long as the input of template information, can realize the batch generation of coupons, can improve the efficiency of operation personnel;

Second, creating the coupon template and sending the coupon entities are done by people with two different permissions. Perhaps the operators with higher authority can control the permission to create templates, while the ordinary operators only need to send coupons according to the templates.

The following figure can reflect the relationship between the bond template and the bond entity:

Second, the design of preferential rules

The above is pretty straightforward, but let’s focus on the design of the preferential rule.

The preferential rule is undoubtedly the core part of the coupon system, and whether it can adapt to the market operation needs to the maximum extent depends on how the preferential rule is implemented.

Obviously, it is unwise to use the exhaustive method to implement preferential rules in the market.

As the saying goes, “the only constant in the world is change”, we must extract the essence of preferential rules, in order to “respond to all changes with the same”.

According to the author’s research on the common preferential rules in the market, and combined with their own business needs, the preferential rules can be roughly divided into two categories:

1. Computational rules. Such as “no threshold straight down 20 yuan”, “full xx minus XX” and so on, these rules are exposed to the end user, is obvious, let the user know how the coupon is involved in the calculation.

2. Limiting rules. In contrast to computational rules, restrictive rules are mostly implicit. For example: limit some users to receive, limit the maximum amount of coupons issued by a set of coupons template, limit the channels of coupons and so on. These kinds of rules can support day-to-day operations well.

“All things complement each other”, and not all preferential rules can coexist, so the concept of “mutual exclusion” of rules is introduced here. When a preference rule and another preference rule cannot exist in the same set of templates, the two rules are considered mutually exclusive, which needs to be considered in the design of the rules.

Secondly, preference rules also pay attention to the order of precedence, so it inevitably brings the “priority” attribute of preference rules. We agree that the smaller the number is, the higher the priority is, that is, the order from the smallest to the largest.

The following is a complete list of rules, informative, the author will do the necessary explanation.

In the rule list, channel restriction, object restriction, amount restriction and quantity restriction are all restricted rules, and they rank higher in priority. Parameter descriptions, rule descriptions, relationships to templates, and mutual exclusion rules are also given at a glance.

The next deduction rules and capping rules belong to the same type of calculation rules, is also the most important coupon.

The author focuses on explaining the “ladder full reduction” in the full reduction rule. We usually see this kind of saying: every 100 yuan minus 10 yuan, meaning: 100 yuan minus 10 yuan, 200 minus 20, and so on, I call this the “ladder full minus” rule.

Iii. Design of preferential rule number

There are many numbers involved in the rule table, so the author designs a set of generating rules.

The rule number is int. In Java programming language, int is 32 bits long, as shown in the following figure:

1. The first bit is a sign bit, which is fixed as 0 and cannot contain all 32 bits of 0, that is, a positive integer.

2. The higher 8 bits are the rule group numbers. Theoretically, the allowed value range is 0~255, but in practice, it is assumed that there are at most 15 groups of preferential rules.

3. The 10th and 11th bits are used as backup, no practical use at the moment, fixed as 00;

The middle 15 bits are used to store rules in the rule group. The value ranges from 0 to 32767. Actual service rules are mutually exclusive, and the values are as follows (take four-bit binary as an example) :

0001

0010

0100

1000

Conclusion: If all zeros are excluded, then N pairs are mutually exclusive if there are N bits. If both groups are mutually exclusive, then there are fewer values available;

The last six bits store the priority of the rule group. The allowed value ranges from 0 to 63. The actual value starts from 1. ;

6. In accordance with the above rules, by-law numbers in the above table can be generated according to the established groups and priorities.

Channel limit 83888577

0 00001010 00 000000000100111 000001

User type limit 167775300

0 00010100 00 000000000110001 000100

Specify user limit 167776900

0 00010100 00 000000001001010 000100

Total amount limit 251660487

0 00011110 00 000000000100011 000111

Unit amount limit 251662535

0 00011110 00 000000001000011 000111

Total limit 335545290

0 00101000 00 000000000001111 001010

Individuals are limited to 33,554,778

0 00101000 00 000000000000111 001010

Minus 419430989 without threshold

0 00110010 00 000000000001001 001101

With 419431565

0 00110010 00 000000000010010 001101

419436813 discount

000110010 00 000000001100100 001101

Top capping Rule 503323024

0 00111100 00 000000001100110 010000

4. Program design of coupon system

Before we start programming, there are three main actions we must take with regard to coupons:

1. Management. This refers to the creation, rule setting, and closing of ticket templates. Of course, when setting rule parameters for a template, you need to verify that the rule parameters are valid.

2. Distribute/pick up. The author combined these two operations. The difference between the two operations is that they can be combined at the interface level without binding end users. Typically, restrictive rules come into play here, and when either operation is triggered, the restrictive rules are validated before the coupon is generated.

3. Use. Is to spend the coupon, calculation rules will play a role in this, mainly to determine whether the full use of the coupon conditions, calculate the amount of exemption, etc.

In summary, the program design is extended by these three actions.

Let’s design the rules layer first.

Depending on the set of rules defined in the rule table, reflection in the program can take two forms:

One is to use a configuration file (usually XML) that the program parses.

The other is to use enumerated classes (or some other form of class) directly.

The first kind of development is slightly more difficult, want to do more powerful words, is to spend a lot of effort.

The definition and implementation of the preferential rules are built into the program beforehand, not just by non-professionals changing the configuration file.

So with this in mind, a second implementation is used. Rule definitions are as follows:

Rulers have five important attributes: rule number (ruleNo), ruleName (ruleName), sort (sort), corresponding Model Class object, and serviceName that implements a specific interface.

The following three methods are also important: directly find the corresponding enumeration by rule number to determine whether it is a computational rule and whether the rule has multiple parameters. The relationship between the rule and the coupon template is 1~* indicates that the rule has multiple parameters.

Of course, there are also Beans that are persisted to the database. Each Bean inherits an abstract class called SuperRule, whose properties are mentioned in the rule table. That’s where the Model Class in Rulers comes from. Since there are many rules, only superrules are shown below:

Because rules are divided into two categories, it is natural to derive two services, one for computational rules and the other for constraint rules.

The last one is a validation of rule parameters, using the generic R, inherited from SuperRule.

At this point, the interface design includes all three of the above coupon-related operations, which means that if a new rule comes along, it will implement at most three of the above services (since there may be both restrictive and computational rules), but most of the time it will implement only two services, Then configure this new rule on Rulers. As for the rules of basic CRUD operations, as long as inherit AbstractCouponRuleService, do not need to spend extra effort to achieve it.

With so many rules, it is natural to need a “factory class” for scheduling, such as generating a rule Bean instance, generating a Service instance.

Five, the summary

From business design to program design, this article has made a comprehensive and clear exposition of the coupon system. If readers just need to develop a coupon system, this article will be a good reference.