3

Two recent failed projects in my career involved trying to implement a discount/promotional offer system for retail. For example, a retailer may want to offer discount codes in emails or newsletters, or offer special incentives to order on a holiday.

Each use-case seems simple enough to implement. For discount codes, for example, you can create a table with the promo-code, a start and end date, and the percentage discount. Implementing a holiday-discount system might be equally simple.

The problem I encountered was that these use cases can become arbitrary complex. Maybe marketing wants a discount code that works only on certain days for certain item types. Maybe they want certain discount codes to be available after a set of arbitrary criterion have been met by the customer. Maybe a customer should only be able to redeem one promotion in a particular set. Maybe certain promotion should only apply to a certain demographic/segmentation of customers, and only during Superbowl weekend.

The core problem is that it is easy for marketing to come up with an arbitrary use case, and the developer has to some how fit it in with all other existing use cases and make sure it doesn't break anything, and remain understandable.

How would you approach such a problem?

My basic approach was to start with the simplest case (say, discount code for percentage off), implement the tables (in postgresql) and supporting code. Then alter it slightly to match the next next thing the business folks come up with. Then again. This became untenable when there is a use case that is substantially different from the others and you have to expand the schema to accommodate it.

I wonder, in retrospect, whether it would've been better to try and enumerate all possible use cases from the start, and try to implement a generic system instead.

2
  • "The core problem is that it is easy for marketing to come up with an arbitrary use case, and the developer has to some how fit it in..." - I guess you could just let the projects keep failing, until the marketing department agree to work in consultation with you about what can be successfully achieved?
    – Steve
    Jun 14, 2023 at 9:31
  • If the requirements are as arbitrary as you suggest and you can't "tame" the marketing beast, you need to design a promotion component that captures the dynamic nature (volatility) of the problem and I don't think you should try to model the criteria and parameters into a static data model (in a database table). Some kind of custom rule-engine could solve (most of) the problem I think.
    – Sil
    Jun 14, 2023 at 12:18

1 Answer 1

5

It's never possible to enumerate all possible use cases upfront. But some systems are more expandable than others.

Having maintained one of these that worked well for a point-of-sale system, I think the key insight was that these things are line items in themselves. You ring them up on the till, and they go on the bill, and they affect the overall price and tax. So in the same table as the rest of the line items, you have lines for "Promotion type X: -$3" and so on.

We also had distinct types for "promotion" (involving multiple items) and "discount" (one item). Discounts applied independently; promotions had a flag for "can be used in conjunction with other promotions". "Apply promo code" also counted as a line item. There were types for "fixed value discount", "fixed percentage discount", and "write-in (manager special) value/percentage".

The logic was then fairly straightforward: on any change to the contents of the basket, run through the promotions in priority order and ask "can this promotion be applied to the basket?" This sounds like it might have bad computational complexity, and it does, but the number of applicable items is usually small (people don't have thousand item baskets!) so it ran in the blink of an eye on a 400MHz till.

There was also an escape hatch button which sent the contents of the basket and customer ID to an external web service which could choose whether or not you were eligible for a promotion (returned as a promo code with $ value). That was a good way to make it "not our problem" and let the marketing people do collaborations or whatever.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.