在某个项目中,业务需求是要在发放优惠券时,由算法决策出券的可用次数和面额,然后将相关信息通过RPC调用传给券平台。券的面额和次数是可以随机指定,但是在真正使用优惠时,需要计算出单次可使用的优惠金额,这里面就有很多有意思的点。

方案1

如果是10元/3次的优惠券,那么单次使用的优惠怎么分摊,这里主要是要解决尾差的问题,想到的一种办法是向下取整保留两位小数。假设一张券的总次数为N,前N-1次用总面额除以总次数,然后向下取整保留两位小数,最后一次优惠券使用时将所有的可用金额给到用户。

  • 优缺点

上面这个方案看似很好的解决了这个问题,而且由于最后一次使用时将所有剩余可用金额返回给用户,对用户其实是有一定的让利。
但是当涉及到退款场景时,这种玩法就不怎么灵了。仍然是10元/3次的优惠券,第1笔和第2笔交易分别使用3.33元优惠。此时第2笔交易发生部分退款,券退了3.32元,由于是部分退款,可用次数并没有回加,那么现在这张券的可用金额/次数为6.66元/1,这就意味着第3笔交易可以使用6.65元。在第3笔交易发生后,第2笔交易把剩余的优惠退了回来,此时券的可用金额/次数为0.01/1,那么再使用随机周期券时,只能享受到0.01元的优惠。
出现这个问题的原因是上一笔交易占用了第2次券使用的可用金额,由此想到了方案2。

方案2

假设一张券的总次数为N,前N-1次用总面额除以总次数,然后向下取整保留两位小数。最后一次用券总面额减去前N-1次应该使用的金额。
这样计算的好处在于每次可享受的优惠,在发券时就已经明确了。但是这样也会产生另外一个问题,用户把券的次数使用完了,但是仍然存在剩余金额。这个其实也不是问题,在发券时已经明确告知用户每次可用的金额。
还有一个尾差累计的问题,如果总面额1000元,使用333次,前332次每次优惠3元,最后一次优惠4元。

其它问题

  • 如果是1分钱/3次的优惠券,那么单次使用的金额又怎么算

1分钱分3次使用,这种其实就不符合业务预期的场景,在给用户发放优惠券,不允许出现这种case。