取消一个(现金+满减+积分)订单,用PHP如何做优惠分摊 ?

341 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 19 天,点击查看活动详情

优惠分摊,算法很多,这里是从shopnc挖出来,适合优惠条件过滤的算法,实质很简单,但是理解难度还是有一点。
应用场景: 一个订单的商品,如果参与了某种活动的时候,那就需要分摊优惠,一般来说需要分摊的有购物金,积分,优惠券,满减等。而且是在整个订单上来使用优惠。

多件N折,限制抢购,团购等都是在商品单价上面体现的,所以难点就在于如何去分摊优惠,比如一个订单用购物金,积分下单了。订单取消后需要返还。这个时候需要退给用户的钱就是商品的价格-购物金-积分之后的钱了

首先,程序员可以使用百分比分摊算法来处理订单优惠分摊。这个算法按照以下步骤来执行:
1)计算每种优惠的总价值额度;
2)将这三种优惠中每种优惠按理财公司比例分配到订单中;
3)用百分比来计算每种优惠在订单中的价值支出,以及订单最终实付金额。

程序员还可以使用全值分摊算法来处理。这个算法的执行过程如下:
1)给每种优惠划出固定价值;
2)将每种优惠的固定价值划分到订单中;
3)计算订单最终实付金额。

分摊算法也可以被程序员用于处理订单优惠分摊。这个算法按照以下步骤执行:
1)将每种优惠的总价值按理财公司比例分配到订单中;
2)按照赠送的优惠价值比例,计算出每种优惠在订单中的价值支出;
3)计算订单最终实付金额。

通过以上的算法,PHP程序员可以帮助商家实现现金+满减+积分订单优惠分摊的功能,且有效地分配订单中每种优惠的支出量,实现每种优惠最大程度地受益。 简单代码示例:

// 订单支付总金额
$totalAmount = 500;
// 现金支付金额 
$cashFee = 400; 
// 满减支付金额 
$manjianFee = 40; 
// 积分支付金额 
$jifenFee = 60; 
// 退款金额 
$refundAmount = 100;

// 先计算比例
if($totalAmount > 0){
    // 现金支付比例
    $cashRatio = $cashFee/$totalAmount; 
    // 满减比例
    $manjianRatio = $manjianFee/$totalAmount; 
    // 积分比例
    $jifenRatio = $jifenFee/$totalAmount; 
}

// 计算退款比例
$refundCash = $cashRatio * $refundAmount;
$refundManjian = $manjianRatio * $refundAmount;
$refundJifen = $jifenRatio * $refundAmount;

// 输出最后结果
echo "现金支付退款金额:".$refundCash;
echo "满减支付退款金额:".$refundManjian;
echo "积分支付退款金额:".$refundJifen;

以下提供优惠分摊的方法,有需要的可以借鉴一下

<?php
/*
* useuserpoint 拆购物金分摊
* usediscount 拆代金卷分摊
* use_offer 除去购物金和折价券之外的优惠分摊,目前来说就是满减的分摊
* 
* 按照不同活动类型来计算此次参与活动商品总金额,再按参与商品金额goods_total的占比来分配分摊的优惠,
* $type就是来对应相关的优惠分摊类型
*/
function _splitPrice(&$goods_info$tmprice$type{

    $goods_num count($goods_info);
    $total 0;

    foreach($goods_info as $k => $v) {
        if($type=='use_offer'){
            if($v['is_own_shop'] == 1) {
                if($goods_num>1){
                    if(!$v['yihe_supplier_deliver']){   //第三方发货的不要摊到满减等优惠
                                 if(!$v['more_goods_discount_info']){  //多件N折商品跳过满减优惠分摊
                             $total += $v['goods_total'];
                                 }
                    }    
                }else{
                    $total += $v['goods_total'];
                }
            }   
        }else{
            if($v['is_own_shop'] == 1) {
                $total += $v['goods_total'];
            }
        }
    }
    $tmp $tmprice;

表面看很不理解,但是其他2个$type对应的值写出来就很明白就是一个根据不同优惠分摊类型经行计算总价格的。
下面的也是不过是计算分摊具体优惠转换成存打数据库的字段

//        foreach($goods_info as $k => $v) {
//            if($type=='use_offer'){
//                if($v['is_own_shop'] == 1) {
//                    if($goods_num>1){
//                        if(!$v['yihe_supplier_deliver']){   //第三方发货的不要摊到满减等优惠
//                                     if(!$v['more_goods_discount_info']){  //多件N折商品跳过满减优惠分摊
//                                 $total += $v['goods_total'];
//                                     }
//                        }    
//                    }else{
//                        $total += $v['goods_total'];
//                    }
//                }   
//            }elseif($type=='usediscount'){
//                if($v['is_own_shop'] == 1) {
//                    $total += $v['goods_total'];
//                }
//            }elseif($type=='useuserpoint'){
//                        if($v['is_own_shop'] == 1) {
//                    $total += $v['goods_total'];
//                }
//                        
//                    }
//        }


        foreach($goods_info as $k => $v) {
            //第三方发货的跳过
            //多件N折商品跳过满减优惠分摊

            if($type == 'use_offer'&&$goods_num>1&&$v['yihe_supplier_deliver']){
                continue;
            }

            if($type == 'use_offer'&&$goods_num>1&&$v['more_goods_discount_info']){
                continue;
            }

            if($v['is_own_shop'] == 1) {
                $splitVal = intval($v['goods_total']/$total*$tmprice) + 1;
                if($splitVal > $tmp) {
                    $splitVal = $tmp;
                }

                $tmp -= $splitVal;
                if($type == 'useuserpoint') {
                    $goods_info[$k]['goods_splituserpoint'] = $splitVal;
                } elseif($type == 'usediscount') {
                    $goods_info[$k]['goods_splitusediscount'] = $splitVal;
                }elseif($type=='use_offer'){
                    $goods_info[$k]['goods_split_use_offer'] = $splitVal;
                }

                if($tmp == 0) {
                    break;
                }
            }
        }
//                P($goods_info);
//                die;
    }