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.