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; } }