| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- <?php
- namespace common\logic\order\marketing;
- use addons\Coupon\AddonConfig;
- use addons\Coupon\common\enums\AddonsCouponEnum;
- use addons\Coupon\common\models\AddonsCoupon;
- use addons\Coupon\common\models\AddonsCouponUserRelate;
- use common\enums\AddonsEnum;
- use common\enums\StatusEnum;
- use common\models\goods\GoodsCateRelate;
- use common\models\mall\MallAddons;
- use Exception;
- use yii\helpers\Json;
- /**
- * 优惠券
- * @Author bing
- * @DateTime 2021-09-27 19:07:32
- * @copyright: Copyright (c) 2020 广东七件事集团
- */
- class CouponMarketing extends BaseMarketing
- {
- public function execute($form)
- {
- }
- public static function compute($item, &$form, &$extra = [])
- {
- try {
- $group_order_goods = $form['group_order_goods'];
- $mall_id = $form['mall_id'];
- $data = is_array($form->data) ? $form->data : Json::decode($form->data, true);
- if (empty($data['user_coupon_ids'])) return $item;
- $time = $_SERVER['REQUEST_TIME'];
- if (empty($extra['coupon'])) {
- $user_coupon_id = $data['user_coupon_ids'];
- $params = ['where' => [['id' => $user_coupon_id]], 'with' => ['coupon' => function ($query) {
- $query->where(['status' => [StatusEnum::ENABLED,StatusEnum::DISABLED]])->with(['goodsRelate', 'cateRelate', 'memberRelate']);
- }]];
- $user_relate_list = AddonsCouponUserRelate::lists($params, true);
- // 优惠券叠加使用
- self::superpositionUse($user_relate_list);
- // 验证优惠券是否能使用
- AddonsCoupon::checkIsAllowUse($user_relate_list, $form);
- $is_install = MallAddons::isInstall($mall_id, AddonsEnum::ADDONS_NAME_COUPON);
- $coupon_data['user_relate_list'] = $user_relate_list;
- $coupon_data['user_coupon_id'] = $user_coupon_id;
- $coupon_data['is_install'] = $is_install;
- $extra['coupon'] = $coupon_data;
- $goods_ids = $goods_arr = $cate_arr = [];
- foreach ($item['goods'] as $v) {
- $goods_ids[] = $v['goods_id'];
- $goods_arr[$v['goods_id']]['mch_id'] = $v['goods_details'][0]['mch_id'];
- }
- $gcrl = GoodsCateRelate::findAll(['goods_id' => $goods_ids]);
- $cate_id_arr = [];
- foreach ($gcrl as $v) {
- $goods_arr[$v['goods_id']]['cate_id'][]= $v['cate_id'];
- $cate_id_arr[] = $v['cate_id'];
- $cate_arr[$v['cate_id']]['mch_id'] = $goods_arr[$v['goods_id']]['mch_id'];
- }
- $extra['cate_arr'] = $cate_arr;
- $extra['goods_arr'] = $goods_arr;
- $extra['cate_id_arr'] = $cate_id_arr;
- foreach ($coupon_data['user_relate_list'] as &$info) {
- if (!empty($info['is_use'])) throw new Exception('优惠券【' . $info['coupon']['name'] . '】已被使用');
- if (empty($info['coupon'])) throw new Exception('优惠券id:【' . $info['coupon_id'] . '】不存在');
- $end_time = $info['end_time'];
- $start_time = $info['start_time'];
- if ($time < $start_time) throw new Exception('优惠券【' . $info['coupon']['name'] . '】还没生效');
- if ($time > $end_time) throw new Exception('优惠券【' . $info['coupon']['name'] . '】已过期');
- $coupon = $info['coupon'];
- if (!AddonsCoupon::checkCouponSourceIsFromSharing($info)) {
- throw new Exception('当前优惠券只能转赠之后才能使用');
- }
- $info['total_goods_price'] = 0;
- $info['have_sub_price'] = 0;
- $goods_id_arr = array_column($coupon['goodsRelate'], 'goods_id');//该优惠券关联的商品id
- $cate_id_arr = array_column($coupon['cateRelate'], 'cate_id');//该优惠券关联的商品分类id
- foreach ($item['goods'] as $row) {
- //指定分类
- if ($coupon['appoint_type'] == AddonsCouponEnum::APPOINT_TYPE1) {
- $cate_id = $goods_arr[$row['goods_id']]['cate_id'];
- if (!empty($info['mch_id'])) {
- $goods_arr = $extra['goods_arr'];
- if ($info['mch_id'] != $cate_arr[$cate_id]['mch_id']) continue;
- }
- if (!array_intersect($cate_id, $cate_id_arr)) continue;
- $info['total_goods_price'] = bcadd($info['total_goods_price'], $row['goods_price'], 2);
- }
- //指定商品
- if ($coupon['appoint_type'] == AddonsCouponEnum::APPOINT_TYPE2) {
- if (!empty($info['mch_id'])) {
- $goods_arr = $extra['goods_arr'];
- if ($info['mch_id'] != $goods_arr[$row['goods_id']]['mch_id']) continue;
- }
- if (!in_array($row['goods_id'], $goods_id_arr)) continue;
- $info['total_goods_price'] = bcadd($info['total_goods_price'], $row['goods_price'], 2);
- }
- //全场通用
- if ($coupon['appoint_type'] == AddonsCouponEnum::APPOINT_TYPE3) {
- $info['total_goods_price'] = bcadd($info['total_goods_price'], $row['goods_price'], 2);
- }
- if ($coupon['appoint_type'] == AddonsCouponEnum::APPOINT_TYPE5) {
- if (!empty($info['coupon']['mch_id'])) {
- $mch_ids = explode(',',$info['coupon']['mch_id']);
- $goods_arr = $extra['goods_arr'];
- if ( !in_array($goods_arr[$row['goods_id']]['mch_id'],$mch_ids)) continue;
- }
- $info['total_goods_price'] = bcadd($info['total_goods_price'], $row['goods_price'], 2);
- }
- }
- }
- } else {
- $coupon_data = $extra['coupon'];
- }
- if (empty($extra['total_deduct_money'])) {
- $total_deduct_money = 0;
- $extra['total_deduct_money'] = $total_deduct_money;
- } else {
- $total_deduct_money = $extra['total_deduct_money'];
- }
- $coupon_arr = [];
- $originalGoodsPriceArr = [];
- $useCouponNum = count($coupon_data['user_relate_list']);
- foreach ($coupon_data['user_relate_list'] as $k => &$v) {
- if (!empty($v['is_use'])) throw new Exception('优惠券【' . $v['coupon']['name'] . '】已被使用');
- if (empty($v['coupon'])) throw new Exception('优惠券id:【' . $v['coupon_id'] . '】不存在');
- $begin_at = $v['coupon']['begin_at'];
- if($v['coupon']['expire_type']==AddonsCouponEnum::EXPIRE_TYPE1){
- $begin_at = $v['created_at'];
- }
- $end_at = $v['end_time'];
- if ($time < $begin_at) throw new Exception('优惠券【' . $v['coupon']['name'] . '】还没生效');
- if ($time > $end_at) throw new Exception('优惠券【' . $v['coupon']['name'] . '】已过期');
- $coupon_arr[$v['coupon_id']] = $v['coupon'];
- $coupon = $v['coupon'];
- $cate_id_arr = array_column($coupon['cateRelate'], 'cate_id');
- $goods_id_arr = array_column($coupon['goodsRelate'], 'goods_id');
- $cate_arr = $extra['cate_arr'];
- $goods_arr = $extra['goods_arr'];
- $total_coupon_money = bcadd($total_coupon_money ?? 0, $v['coupon']['sub_price'], 2);
- $goodsKey = 0;
- foreach ($item['goods'] as &$row) {
- if (!isset($originalGoodsPriceArr[$row['goods_id']])) {
- $originalGoodsPriceArr[$row['goods_id']] = $row['goods_price'];
- }
- if ($coupon['appoint_type'] == AddonsCouponEnum::APPOINT_TYPE1) {
- $cate_id = $goods_arr[$row['goods_id']]['cate_id'];
- if (!empty($v['mch_id']) && $v['mch_id'] != $cate_arr[$cate_id]['mch_id']) continue;
- if (!($cate_id && $cate_id_arr)) continue;
- if (!array_intersect($cate_id, $cate_id_arr)) continue;
- }
- if ($coupon['appoint_type'] == AddonsCouponEnum::APPOINT_TYPE2) {
- if (!empty($v['mch_id']) && $v['mch_id'] != $goods_arr[$row['goods_id']]['mch_id']) continue;
- if (!in_array($row['goods_id'], $goods_id_arr)) continue;
- }
- if ($coupon['appoint_type'] == AddonsCouponEnum::APPOINT_TYPE3) {
- if (!empty($v['mch_id']) && $v['mch_id'] != $goods_arr[$row['goods_id']]['mch_id']) continue;
- }
- if ($coupon['appoint_type'] == AddonsCouponEnum::APPOINT_TYPE6) {
- continue;
- }
- $old_goods_price = $row['goods_price'];
- $goods_price = self::deduct(array_merge($row, ['original_goods_price_arr' => $originalGoodsPriceArr, 'goods_key' => $goodsKey, 'use_coupon_num' => $useCouponNum, 'use_coupon_index' => $k]), $v);
- $deduct_money = static::_floorNum($row['goods_price'] - $goods_price, 2);
- $total_deduct_money = bcadd($total_deduct_money, $deduct_money, 2);
- $row['goods_price'] = $goods_price;
- $sum = $temp_sum = 0;
- foreach ($row['goods_details'] as &$goods_detail) {
- if($row['goods_price']>0){
- $deduct_money_single = bcdiv(bcmul($goods_detail['goods_price'], $deduct_money, 2), $old_goods_price, 2); // 优惠按售价占比
- }else{
- $deduct_money_single = $goods_detail['goods_price'];
- }
- $temp_sum = bcadd($temp_sum, $deduct_money_single, 2);
- if ($temp_sum > $deduct_money) {
- $deduct_money_single = bcsub($deduct_money, $sum, 2);
- } else {
- $sum = bcadd($sum, $deduct_money_single, 2);
- }
- if (isset($goods_detail['marketing']['pay_money'])) {
- $pay_money = bcsub(($goods_detail['marketing']['pay_money'] ?? 0), $deduct_money_single, 2);
- } else {
- $pay_money = bcsub(($goods_detail['goods_price'] ?? 0), $deduct_money_single, 2);
- }
- $goods_detail['goods_price'] = bcsub(($goods_detail['goods_price'] ?? 0), $deduct_money_single, 2);
- $goods_detail['coupon'][] = ['user_coupon_id' => $v['id'], 'pay_money' => $pay_money, 'coupon_discount_money' => static::_floorNum($deduct_money_single, 2)];
- }
- $goodsKey++;
- }
- }
- foreach ($item['goods'] as &$row) {
- $coupons = [];
- $coupon_discount_money = 0;
- $pay_money = 0;
- foreach ($row['goods_details'] as &$goods_detail) {
- if (!empty($goods_detail['coupon'])) {
- array_map(function ($item) use (&$coupons, &$pay_money, &$coupon_discount_money) {
- $coupons[$item['user_coupon_id']] = $item['coupon_discount_money'];
- $pay_money = $item['pay_money'];
- $coupon_discount_money += $item['coupon_discount_money'];
- }, $goods_detail['coupon']);
- unset($goods_detail['coupon']);
- $goods_detail['marketing']['user_coupon_id'] = json_encode($coupons);
- $goods_detail['marketing']['pay_money'] = $pay_money;
- $goods_detail['marketing']['coupon_discount_money'] = $coupon_discount_money;
- }
- }
- }
- // 适应满减券
- if (self::_isFullMinus($user_relate_list ?? [])) {
- $total_deduct_money = ($total_coupon_money == $total_deduct_money) ? $total_deduct_money : $total_coupon_money;
- }
- $item['mch_order_info']['goods_price'] = bcsub(($item['mch_order_info']['goods_price'] ?? 0), $total_deduct_money, 2) ;
- $item['mch_order_info']['coupon_money'] = $total_deduct_money;
- $form['group_order_goods'] = $group_order_goods;
- $form['total_pay_money'] = bcsub(($form['total_pay_money'] ?? 0), $total_deduct_money, 2);
- if (!empty($total_deduct_money)) $form->marketing['deduct']['coupon'] = ['name' => '优惠券', 'money' => -static::_floorNum($total_deduct_money, 2)];
- return $item;
- } catch (Exception $e) {
- CouponMarketing::setStaticError($e->getMessage());
- return false;
- }
- }
- /**
- * 优惠后的金额
- * @Author: hua
- * @DateTime: 2021/10/15 16:46
- * @Copyright: copyright (c) 2021 广东七件事集团
- * @param $row
- * @param $v
- * @return float|int|string
- * @throws Exception
- */
- public static function deduct($row, &$v)
- {
- $goods_price = $row['goods_price'];
- $coupon = $v['coupon'];
- if(!empty($coupon['is_original_use'])){
- $price=0;
- foreach ($row['goods_details'] as $goods_detail) {
- $price+=$goods_detail['price']*$goods_detail['num'];
- }
- if($row['goods_price']!=$price) throw new Exception('原价购买['.$row['goods_name'].']才能使用优惠券:'.$coupon['name']);
- }
- //最低消费
- if (!empty($coupon['min_price']) && $v['total_goods_price'] < $coupon['min_price']) throw new Exception('没有达到最低消费');
- //折扣
- if ($coupon['type'] == AddonsCouponEnum::DISCOUNT) {
- $goods_price = sprintf('%.2f', $row['goods_price'] * $coupon['discount'] / 10); //折扣
- $deduct_money = $row['goods_price'] - $goods_price;
- if ($coupon['discount_limit'] != '0.00' && $deduct_money > $coupon['discount_limit']) {
- $goods_price = bcsub($row['goods_price'], $coupon['discount_limit'], 2);
- }
- }
- //满减
- if ($coupon['type'] == AddonsCouponEnum::FULL_MINUS) {
- $sub_price = $row['original_goods_price'] / $v['total_goods_price'] * $coupon['sub_price'];
- $v['coupon']['have_sub_price'] = isset($v['coupon']['have_sub_price']) ? $v['coupon']['have_sub_price'] : 0;
- if ($v['coupon']['have_sub_price'] + $sub_price > $coupon['sub_price']) {
- $sub_price = $coupon['sub_price'] - $v['coupon']['have_sub_price'];
- $v['coupon']['have_sub_price'] += $sub_price;
- } else {
- $v['coupon']['have_sub_price'] += $sub_price;
- }
- if (($row['goods_price'] - $sub_price) < 0) {
- $goods_price = 0;
- } else {
- $goods_price = bcsub($row['goods_price'], $sub_price, 2);
- }
- }
- // 兑换券
- if ($coupon['type'] == AddonsCouponEnum::EXCHANGE && isset($row['goods_key']) && $row['goods_key'] == 0) {
- $goods_price = bcsub($row['goods_price'], bcdiv($row['original_goods_price_arr'][$row['goods_id']], $row['num'], 2), 2);
- $goods_price = max($goods_price, 0);
- // 如果使用兑换券和下单的数量相等,则最终的优惠结果就应该是0,所以如果循环到最后一次优惠券计算但是金额仍不等于0,则直接等于0
- if ($row['num'] == $row['use_coupon_num'] && ($row['use_coupon_index'] + 1) == $row['use_coupon_num'] && $goods_price != 0) {
- $goods_price = 0;
- }
- }
- return static::_floorNum($goods_price, 2);
- }
- /**
- * 优惠券叠加使用
- *
- * @param array $user_coupon_list
- * @return void
- */
- public static function superpositionUse(array $user_coupon_list)
- {
- if (count($user_coupon_list) >= 2) {
- foreach ($user_coupon_list as $user_coupon) {
- // 优惠券属性
- $coupon = $user_coupon['coupon'];
- // 兑换券类型不需要检查
- if ($coupon['type'] == AddonsCouponEnum::EXCHANGE) {
- continue;
- }
- if ($coupon['is_superposition_use'] == 0) throw new Exception('选择优惠券中存在不支持叠加使用的优惠券');
- }
- }
- }
- /**
- * 获取
- *
- * @param string $number
- * @param integer $precision
- * @return string
- */
- private static function _floorNum(string $number, $precision = 2)
- {
- $pow = pow(10, 2);
- return bcdiv(bcmul($number, $pow), $pow, 2);
- }
- /**
- * 判断当前使用优惠券是否是满减券
- *
- * @param array $coupon_ids
- * @return boolean
- */
- private static function _isFullMinus(array $user_coupon_list)
- {
- $type = reset(array_column(array_column($user_coupon_list, 'coupon'), 'type'));
- return $type == AddonsCouponEnum::FULL_MINUS;
- }
- }
|