1. 9
    1. 2

      I wonder how they would handle a cart-level coupon rule in code like this - like a general 10% off coupon. I think the cart should be responsible for applying the coupon to discount the total of the order - even if the discounting rules apply at the item level.

      That being said, I guess the goal of this blog post is to keep map methods clean and simple?

      1. 1

        Even more tricky would be “2 for 1” / multibuy / combo offers since an Item won’t know what else is in a Cart.

        1. 3

          The eligibility logic of a coupon should be written inside the coupon itself.

          Example in pseudocode.

          // returns an AppliableCoupon, which knows what are the eligible items.
          appliable_coupon = coupon.for_eligible(items) 
          
          // item.total_cost will call appliable_coupon.check(item) to see if the coupon is valid for that specific item.
          items.map(|item| item.total_cost(appliable_coupon)) 
          

          This has the following benefits:

          • if you introduce a new coupon type, neither the Cart nor the Item need to be changed.
          • it’s hard to misuse. You can’t apply a coupon directly. You need to get an AppliableCoupon, which you can only get through coupon.for_eligible(items).
          • It’s all functional and immutable, if you like that kind of things.