CouponConfig = Struct.new(:conditions, :effects, keyword_init: true) do
CONDITION_OPERATIONS = {
:gte => ->(operand1, operand2) { operand1 >= operand2 },
:lte => ->(operand1, operand2) { operand1 <= operand2 },
}
def apply?(**context)
conditions.all? do |condition|
operator = condition.fetch(:operator)
operands = condition.fetch(:operands).map { |op| context.fetch(op, op) }
CONDITION_OPERATIONS.fetch(operator).call(*operands)
end
end
DISCOUNT_EFFECTS = {
percentage: ->(amount, value) { amount * (value / 100.0) }
}
def discount(order_amount:)
effects.sum(0) do |effect|
type, value = effect.fetch_values(:type, :value)
DISCOUNT_EFFECTS.fetch(type).call(order_amount, value)
end
end
end
coupon_config = CouponConfig.new(**coupon_config_hash)