当我们要做开立发票、发票折让的时候,或者对第三方如 POS
整合系统要同步资料时,可能会遇到需要使用『摊提』的情境。在开始介绍摊提以前,我们先介绍基本情境,以及各个资料表之间的关系
#======= 订单 Order
columns:
used_rebate: 纪录使用的回馈点
used_birth: 纪录使用的生日点
target_price: 满额赠实际扣点
#======= 卖出商品 OrderItem
columns:
quantity: 卖出数量
price: 折价後价钱
#======= 退货商品 ReturnOrderItem
columns:
quantity: 退货数量
#======= 订单与卖出商品之间的关系
order has_many order_items
order_item belongs_to order
#======= 卖出商品、退货商品之间的关系
order_item has_one return_order_item
return_order_item belongs_to order_item
decorator pattern 的精神是,在不动用该实体的行为的同时,对该实体新增一些显示方法。以该情境来说,我们不动订单、退货单的金额,用现有的方法算摊提後的价格。
下列为将计算退款的Decorator
写在module,并透过 module#included
在被include
之後对Order
, OrderItem
加入实体方法
module OrderSyncDecorator
def self.included(base)
Order.class_eval do
# 减项: 使用点数、满额赠
define_method :minus, -> { used_rebate.to_i + target_price.to_i }
end
OrderItem.class_eval do
# 退货完後的数量
define_method :qty_after_return, -> { quantity.to_i - return_order_item&.quantity.to_i }
# 比率分子
define_method :item_numerator, -> { qty_after_return * price }
end
Order.class_eval do
# 比率分母
define_method :item_denominator, -> { order_items.sum(&:item_numerator) }
end
OrderItem.class_eval do
# 比率
define_method :item_ratio, -> { item_numerator.to_f / order.item_denominator.to_f }
end
Order.class_eval do
# 摊平金额
define_method :flatten_minus, -> { order_items.map { |_| {id: _.id, price: (_.item_ratio * minus.to_f).to_i} } }
# 误差数
define_method :deviation_minus, -> { minus - flatten_minus.sum { |_| _[:price] } }
# 修正金额 (+在首位)
define_method :corr_flatten_minus, -> { e = flatten_minus; [e[0].merge(price: e[0][:price] + deviation_minus), *e[1..-1]] }
end
OrderItem.class_eval do
# 商品小计
define_method :subtotal, -> { quantity * price - minus }
# minus
define_method :minus, -> { order.corr_flatten_minus.find { |_| _[:id] == id }.try(:[], :price) }
end
# 单项折让
define_method :rebate, -> { variant.price - subtotal.to_f }
# 单项折扣
define_method :discount, -> { 100 * (subtotal.to_f / variant.price.to_f) }
end
end
end
以上例来说,摊提的算法为
订单Order
➡️ 先将订单的减项算出来
订单项OrderItem
➡️ 将退货後的数量算出来
订单项OrderItem
➡️ 将摊提比率的分子算出来
订单Order
➡️ 先将订单摊提比率的分母算出来
订单项OrderItem
➡️ 将摊提比率算出来
订单Order
➡️ 将摊提金额算出来flatten_minus
➡️ 将误差算出来deviation_minus
➡️ 修正误差corr_flatten_minus
:将误差修正的结果
订单项OrderItem
➡️ 算商品小计
➡️ 算用比率
/ 修正
後的减项 ? 从corr_flatten_minus
取得结果
➡️ 算单项折让
➡️ 算单项折扣
搭配之前介绍的继承,只要有分销相关的逻辑,包含後台画面、发票折让、同步订单等,只要继承了OrderSyncDecorator
,就可以共用包含在OrderSyncDecorator
里面所有的实体方法。
>>: [DAY 17]Discord server串接webhook
本来今天要介绍的是验证授权,但官方那一套我不是很喜欢,所以就从网路上找其他的解决办法,果不其然就找到...
在写这篇时发现,因为在上篇文章有提到模板讯息,里面有大量出现Action objects,Quick...
这是我个人的使用偏好,而且是以抽象资料型别的使用方式来理解 vuex 的使用方式。也许,我是说也许...
Immutable Immutable 中文意思为不可变的, 即重新赋值後, 新的值和原始的值并不互...
由於可能很多人会不习惯缩排的写法来写html,然後在Day17以後的章节,汉汉老师会大量的使用缩排式...