diff --git a/app/common.php b/app/common.php index 27f14a63..ba98d7f0 100644 --- a/app/common.php +++ b/app/common.php @@ -1190,5 +1190,20 @@ if (!function_exists('strUcwords')) { } } - +if (!function_exists('reset_index')) { + /** + * 重置数组索引 + * @param array $data + * @param string $index + * @return array + */ + function reset_index(array $data, string $index) + { + $return = []; + foreach ($data as $item) { + $return[$item[$index]] = $item; + } + return $return; + } +} diff --git a/app/common/dao/store/coupon/StoreCouponUserDao.php b/app/common/dao/store/coupon/StoreCouponUserDao.php index 5ba52997..deaa0ea2 100644 --- a/app/common/dao/store/coupon/StoreCouponUserDao.php +++ b/app/common/dao/store/coupon/StoreCouponUserDao.php @@ -17,6 +17,8 @@ namespace app\common\dao\store\coupon; use app\common\dao\BaseDao; use app\common\model\BaseModel; use app\common\model\store\coupon\StoreCouponUser; +use app\common\repositories\store\coupon\StoreCouponRepository; +use think\exception\ValidateException; /** * Class StoreCouponUserDao @@ -27,6 +29,30 @@ use app\common\model\store\coupon\StoreCouponUser; class StoreCouponUserDao extends BaseDao { + /** @var float $maxAmount 单笔订单计算红包的最大有效金额 */ + public $maxAmount = 20000; + + /** @var float $orderTotalPrice 订单总金额 */ + public $orderTotalPrice; + + /** @var float $orderProductPrice 当前商品金额 */ + public $orderProductPrice; + + /** @var float $isLast 是否最后一条数据 */ + public $isLast = false; + + /** @var float $groupOrderTotalPrice 订单组总金额 */ + public $groupOrderTotalPrice; + + /** @var float $couponTotalAmount 红包总金额 */ + public $couponTotalAmount; + /** @var int $orderType 订单类型:1 groupOrder,2 order */ + public $orderType = 2; + /** @var float $couponUsed 已使用的红包金额 */ + public $couponUsed; + /** @var float $profitRate 商品毛利率 */ + public $profitRate; + /** * @return BaseModel * @author xaboy @@ -129,4 +155,115 @@ class StoreCouponUserDao extends BaseDao $this->getModel()::getDB()->where($field, $id)->delete(); } + /** + * 增加优惠券余额 + * @param $id + * @param $amount + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function increase($id, $amount) + { + $storeCouponUser = StoreCouponUser::where('coupon_user_id', $id)->find(); + if (empty($storeCouponUser)) { + throw new ValidateException('优惠券不存在'); + } + $storeCouponUser->coupon_price = bcadd($storeCouponUser->coupon_price, $amount, 2); + if (!$storeCouponUser->save()) { + throw new ValidateException('优惠券余额更新出错'); + } + } + + /** + * 扣减优惠券余额 + * @param $id + * @param $amount + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function reduce($id, $amount) + { + $storeCouponUser = StoreCouponUser::where('coupon_user_id', $id)->find(); + if (empty($storeCouponUser)) { + throw new ValidateException('优惠券不存在'); + } + $isBalance = $storeCouponUser->isbalance(); + $couponPrice = bcsub($storeCouponUser->coupon_price, $amount, 2); + if ($isBalance && $couponPrice > 0) { + $storeCouponUser->coupon_price = $couponPrice; + } + if ($couponPrice <= 0 || !$isBalance) { + $storeCouponUser->status = 1; + } + if (!$storeCouponUser->save()) { + throw new ValidateException('优惠券余额更新出错'); + } + } + + /** + * 按商品使用优惠券 + * @param $type + * @return array + */ + public function couponByProduct($type = StoreCouponRepository::TYPE_STORE_COUPON) + { + // 把所有金额转换成分,避免红包金额产生误差 + $totalPrice = $this->orderProductPrice * 100; + $couponUsed = $this->couponUsed * 100; + $couponTotal = $this->couponTotalAmount * 100; + if ($type == StoreCouponRepository::TYPE_STORE_COUPON) { + //店铺现金抵扣券,根据商品毛利率计算优惠金额 + $couponBalance = $couponTotal - $couponUsed; + if ($couponBalance <= 0) { + return [$this->orderProductPrice, '0.00', $this->couponUsed]; + } + $rate = $this->getRate($this->profitRate); + $useAmount = bcmul($totalPrice, $rate, 2); + if ($useAmount >= $couponBalance) { + $useAmount = $couponBalance; + } + } else { + //平台购物卡 + $groupOrderTotalPrice = $this->groupOrderTotalPrice * 100; + $rate = bcdiv($totalPrice, $groupOrderTotalPrice, 5); + if ($couponTotal >= $groupOrderTotalPrice) { + $useAmount = $totalPrice; + } else { + $useAmount = $this->isLast ? $couponTotal - $couponUsed : round(bcmul($couponTotal, $rate, 1)); + } + } + $payPrice = $totalPrice - $useAmount; + $couponUsed += $useAmount; + $payPrice = bcdiv($payPrice, 100, 2); + $useAmount = bcdiv($useAmount, 100, 2); + $couponUsed = bcdiv($couponUsed, 100, 2); + /** $payPrice:实际支付的金额,$useAmount:当前商品使用的优惠券金额,$couponUsed:使用的优惠券金额总计 */ + return [$payPrice, $useAmount, $couponUsed]; + } + + /** + * 根据商品毛利率计算红包抵扣比例 + * @param float $profitRate 毛利率 + * @return float|int + */ + public function getRate($profitRate) + { + $rateArray = [ + '0.25' => 0.4, + '0.2' => 0.3, + '0.15' => 0.2, + '0.1' => 0.1, + ]; + $rate = 0; + foreach ($rateArray as $k => $item) { + if ($profitRate >= $k) { + $rate = $item; + break; + } + } + return $rate; + } + } diff --git a/app/common/model/store/coupon/StoreCouponUser.php b/app/common/model/store/coupon/StoreCouponUser.php index 7ffdae1d..4d2b6ebe 100644 --- a/app/common/model/store/coupon/StoreCouponUser.php +++ b/app/common/model/store/coupon/StoreCouponUser.php @@ -17,6 +17,7 @@ namespace app\common\model\store\coupon; use app\common\model\BaseModel; use app\common\model\system\merchant\Merchant; use app\common\model\user\User; +use app\common\repositories\store\coupon\StoreCouponRepository; /** * Class StoreCouponUser @@ -66,4 +67,14 @@ class StoreCouponUser extends BaseModel { return $this->hasOne(Merchant::class, 'mer_id', 'mer_id'); } + + /** + * 当前优惠券是否有余额 + * @return bool + */ + public function isBalance() + { + return in_array($this->coupon_type, [StoreCouponRepository::TYPE_STORE_COUPON, StoreCouponRepository::TYPE_PLATFORM_CARD]); + } + } diff --git a/app/common/repositories/store/coupon/StoreCouponRepository.php b/app/common/repositories/store/coupon/StoreCouponRepository.php index a4e7d6ce..a08532c3 100644 --- a/app/common/repositories/store/coupon/StoreCouponRepository.php +++ b/app/common/repositories/store/coupon/StoreCouponRepository.php @@ -48,7 +48,7 @@ class StoreCouponRepository extends BaseRepository const TYPE_STORE_ALL = 0; //店铺商品券 const TYPE_STORE_PRODUCT = 1; - //店铺现金抵扣券 + //店铺现金抵扣券,可结余 const TYPE_STORE_COUPON = 2; //平台券 const TYPE_PLATFORM_ALL = 10; @@ -334,8 +334,9 @@ class StoreCouponRepository extends BaseRepository $data = [ 'uid' => $uid, 'coupon_title' => $coupon['title'], + 'coupon_type' => $coupon['type'], 'coupon_price' => $coupon['coupon_price'], - 'balance' => $coupon['coupon_price'], + 'origin_price' => $coupon['coupon_price'], 'use_min_price' => $coupon['use_min_price'], 'type' => $type, 'coupon_id' => $coupon['coupon_id'], diff --git a/app/common/repositories/store/order/StoreOrderCreateRepository.php b/app/common/repositories/store/order/StoreOrderCreateRepository.php index 460bfdf3..c1633129 100644 --- a/app/common/repositories/store/order/StoreOrderCreateRepository.php +++ b/app/common/repositories/store/order/StoreOrderCreateRepository.php @@ -2,6 +2,7 @@ namespace app\common\repositories\store\order; +use app\common\dao\store\coupon\StoreCouponUserDao; use app\common\repositories\system\form\FormRepository; use app\common\repositories\system\RecordRepository; use crmeb\jobs\SendSmsJob; @@ -1107,7 +1108,7 @@ class StoreOrderCreateRepository extends StoreOrderRepository 'activity_type' => $orderInfo['order_type'], ]; event('order.create.before', compact('groupOrder', 'orderList')); - $group = Db::transaction(function () use ($ex, $user, $topUid, $spreadUid, $uid, $receipt_data, $cartIds, $allUseCoupon, $groupOrder, $orderList, $orderInfo) { + $group = Db::transaction(function () use ($ex, $user, $topUid, $spreadUid, $uid, $receipt_data, $cartIds, $allUseCoupon, $groupOrder, $orderList, $orderInfo, $useCoupon) { $storeGroupOrderRepository = app()->make(StoreGroupOrderRepository::class); $storeCartRepository = app()->make(StoreCartRepository::class); $attrValueRepository = app()->make(ProductAttrValueRepository::class); @@ -1117,6 +1118,7 @@ class StoreOrderCreateRepository extends StoreOrderRepository //订单记录 $storeOrderStatusRepository = app()->make(StoreOrderStatusRepository::class); $userMerchantRepository = app()->make(UserMerchantRepository::class); + $storeCouponUserDao = new StoreCouponUserDao(); //减库存 foreach ($orderList as $order) { @@ -1156,6 +1158,9 @@ class StoreOrderCreateRepository extends StoreOrderRepository throw new ValidateException('库存不足'); } } + if (!empty($useCoupon[$order['mer_id']])) { + $storeCouponUserDao->reduce($useCoupon[$order['mer_id']][0], $order['total_price']); + } } if ($orderInfo['order_type'] == 10 && !app()->make(StoreDiscountRepository::class)->decStock($orderList[0]['cartInfo']['list'][0]['source_id'])) { @@ -1167,12 +1172,9 @@ class StoreOrderCreateRepository extends StoreOrderRepository 'is_pay' => 1 ]); - //使用优惠券 - if (count($allUseCoupon)) { - $couponUserRepository->updates($allUseCoupon, [ - 'use_time' => date('Y-m-d H:i:s'), - 'status' => 1 - ]); + //使用了平台优惠券 + if (!empty($useCoupon[0])) { + $storeCouponUserDao->reduce($useCoupon[0][0], $groupOrder['total_price']); } //创建订单