1. 9

  2. 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.