diff --git a/app/Amqp/Consumer/CancelOrderConsumer.php b/app/Amqp/Consumer/CancelOrderConsumer.php index ba0d7a9..405ea15 100644 --- a/app/Amqp/Consumer/CancelOrderConsumer.php +++ b/app/Amqp/Consumer/CancelOrderConsumer.php @@ -4,16 +4,20 @@ declare(strict_types=1); namespace App\Amqp\Consumer; +use App\Constants\Common\CouponCode; use App\Constants\Common\OrderCode; use App\Lib\Log; use App\Model\Order; +use App\Model\UserCoupon; use App\Service\ServiceTrait\Api\OrderTrait; +use Exception; use Hyperf\Amqp\Message\ConsumerDelayedMessageTrait; use Hyperf\Amqp\Message\ProducerDelayedMessageTrait; use Hyperf\Amqp\Message\Type; use Hyperf\Amqp\Result; use Hyperf\Amqp\Annotation\Consumer; use Hyperf\Amqp\Message\ConsumerMessage; +use Hyperf\DbConnection\Db; use Hyperf\Di\Annotation\Inject; use PhpAmqpLib\Message\AMQPMessage; @@ -40,6 +44,12 @@ class CancelOrderConsumer extends ConsumerMessage #[Inject] protected Order $orderModel; + /** + * @var UserCoupon + */ + #[Inject] + protected UserCoupon $userCouponModel; + public function consumeMessage($data, AMQPMessage $message): Result { @@ -66,9 +76,18 @@ class CancelOrderConsumer extends ConsumerMessage return Result::ACK; } - $orderInfo->status = OrderCode::CANCEL; - if (!$orderInfo->save()) { - $this->log->debug('CancelOrderConsumer:error:orderStatusSaveError:'.json_encode($orderInfo->toArray())); + try { + Db::beginTransaction(); + + $this->rollbackCoupon($orderType, $orderInfo); + + $orderInfo->status = OrderCode::CANCEL; + if (!$orderInfo->save()) throw new Exception('CancelOrderConsumer:error:orderStatusSaveError:'.json_encode($orderInfo->toArray())); + + Db::commit(); + }catch (Exception $e){ + Db::rollback(); + $this->log->debug($e->getMessage()); return Result::ACK; } @@ -76,4 +95,27 @@ class CancelOrderConsumer extends ConsumerMessage return Result::ACK; } + + /** + * @param $orderType + * @param $orderInfo + * @return void + * @throws Exception + */ + private function rollbackCoupon($orderType,$orderInfo): void + { + if ($orderType != OrderCode::ORDER_TYPE_GOOD) return; + + if ($orderInfo->coupon_id <= 0) return; + + $couponInfo = $this->userCouponModel->where('coupon_id', $orderInfo->coupon_id)->where('user_id',$orderInfo->user_id)->first(); + + if (empty($couponInfo)) return; + + $couponInfo->status = CouponCode::COUPON_STATUS_UNUSED; + + if (date('Y-m-d H:i:s') > $couponInfo->validity_end_time) $couponInfo->status = CouponCode::COUPON_STATUS_EXPIRE; + + if (!$couponInfo->save()) throw new Exception('CancelOrderConsumer:error:couponStatusUpdateError:'.json_encode($orderInfo->toArray())); + } } diff --git a/app/Constants/Common/CouponCode.php b/app/Constants/Common/CouponCode.php index 2a5828e..12773a0 100644 --- a/app/Constants/Common/CouponCode.php +++ b/app/Constants/Common/CouponCode.php @@ -39,11 +39,11 @@ class CouponCode CONST INT DISPENSE_CLAIM_RULE_SINGLE_PAGE = 3; /** - * @var int 优惠券状态 1 未使用 2 已使用 3 未过期 + * @var int 优惠券状态 1 未使用 2 已使用 3 过期 */ CONST INT COUPON_STATUS_UNUSED = 1; CONST INT COUPON_STATUS_USED = 2; - CONST INT COUPON_STATUS_NOT_EXPIRE = 3; + CONST INT COUPON_STATUS_EXPIRE = 3; /** * @var int 优惠券发放状态 1 未领取 2 已领取 diff --git a/app/Service/Api/Order/ConfirmationOrderService.php b/app/Service/Api/Order/ConfirmationOrderService.php index 366b1fc..56d42a4 100644 --- a/app/Service/Api/Order/ConfirmationOrderService.php +++ b/app/Service/Api/Order/ConfirmationOrderService.php @@ -35,10 +35,14 @@ class ConfirmationOrderService extends BaseOrderService $this->check(); + $this->getCouponInfo(); + $this->compute(); $this->autoSelectCoupon(); + $this->reloadCompute(); + return $this->return->success('success',$this->orderRes); } @@ -67,7 +71,7 @@ class ConfirmationOrderService extends BaseOrderService foreach ($filtered as &$value) { $value['amount'] = match ($value['coupon_type']) { CouponCode::COUPON_TYPE_INSTANT_REDUCTION => $value['amount'], - CouponCode::COUPON_TYPE_DISCOUNT => $value['ratio'] * $orderMaxPrice, + CouponCode::COUPON_TYPE_DISCOUNT => bcmul(bcsub("1", $value['ratio'],2),$orderMaxPrice,2), default => 0 }; @@ -80,12 +84,7 @@ class ConfirmationOrderService extends BaseOrderService $this->couponId = $selectCouponInfo['id']; $this->orderRes['coupon'] = $selectCouponInfo; $this->orderRes['coupon_id'] = $selectCouponInfo['id']; - - $this->reloadCompute(); } - private function reloadCompute(): void - { - } } \ No newline at end of file diff --git a/app/Service/Api/Order/PlaceOrderService.php b/app/Service/Api/Order/PlaceOrderService.php index 0824702..ff7f9e4 100644 --- a/app/Service/Api/Order/PlaceOrderService.php +++ b/app/Service/Api/Order/PlaceOrderService.php @@ -57,9 +57,15 @@ class PlaceOrderService extends BaseOrderService // 生成购物车信息 , 检测商品和库存等 $this->check(); + // 如果传递了优惠券的值 则进行检测 + $this->getCouponInfo(); + // 计算 $this->compute(); + // 如果有优惠券的情况下 重载计算 + $this->reloadCompute(); + // 下单 减少库存 写入数据库 $this->placeOrder(); diff --git a/app/Service/ServiceTrait/Api/OrderTrait.php b/app/Service/ServiceTrait/Api/OrderTrait.php index 89adebe..fc0d67b 100644 --- a/app/Service/ServiceTrait/Api/OrderTrait.php +++ b/app/Service/ServiceTrait/Api/OrderTrait.php @@ -15,6 +15,7 @@ use App\Cache\Redis\Api\ApiRedisKey; use App\Cache\Redis\Api\SiteCache; use App\Cache\Redis\RedisCache; use App\Constants\ApiCode; +use App\Constants\Common\CouponCode; use App\Constants\Common\GoodCode; use App\Constants\Common\OrderCode; use App\Constants\Common\PayCode; @@ -333,4 +334,55 @@ trait OrderTrait $producer->produce($message); } + /** + * 重载计算 + * @return void + */ + protected function reloadCompute(): void + { + if ($this->couponId <= 0 || empty($this->orderRes['coupon_info']) || $this->orderRes['coupon_id'] <= 0) return; + + if ($this->orderRes['coupon_info']['amount'] <= 0 && $this->orderRes['coupon_info']['coupon_type'] != CouponCode::COUPON_TYPE_INSTANT_REDUCTION) { + $orderMaxPrice = max(array_column($this->orderRes['good'],'price')); + $this->orderRes['coupon_info']['amount'] = match ($this->orderRes['coupon_info']['coupon_type']) { + CouponCode::COUPON_TYPE_INSTANT_REDUCTION => $this->orderRes['coupon_info']['amount'], + CouponCode::COUPON_TYPE_DISCOUNT => bcmul(bcsub("1", $this->orderRes['coupon_info']['ratio'],2),$orderMaxPrice,2), + default => 0 + }; + } + + $this->orderRes['favorable_good_price'] = $this->orderRes['coupon_info']['amount']; + $this->orderRes['good_after_discount_price'] = bcsub($this->orderRes['good_after_discount_price'],$this->orderRes['favorable_good_price'],2); + $this->orderRes['actual_price'] = bcsub($this->orderRes['actual_price'],$this->orderRes['favorable_good_price'],2); + } + + + /** + * @return void + */ + protected function getCouponInfo(): void + { + if ($this->couponId <= 0) return; + + $couponInfo = $this->userCouponModel->where('coupon_id', $this->couponId)->where('user_id',$this->userId)->first(); + if (empty($couponInfo)) throw new ErrException('优惠券信息错误'); + if (in_array($couponInfo->status,[CouponCode::COUPON_STATUS_USED,CouponCode::COUPON_STATUS_EXPIRE])) throw new ErrException('优惠券已经被使用'); + + $couponTemplateInfo = $this->couponTemplateModel->getInfoById($couponInfo->coupon_template_id); + if (empty($couponTempleteInfo)) throw new ErrException('优惠券信息错误'); + + $this->couponId = $couponInfo->id; + $this->orderRes['coupon_info'] = [ + 'id' => $couponInfo->id, + 'coupon_type' => $couponTemplateInfo->coupon_type, + 'amount' => $couponTemplateInfo->amount, + 'ratio' => $couponTemplateInfo->ratio, + 'coupon_template_id' => $couponTemplateInfo->id, + 'coupon_name' => $couponInfo->coupon_name, + 'status' => $couponInfo->status, + 'validity_start_time' => $couponInfo->validity_start_time, + 'validity_end_time' => $couponInfo->validity_end_time, + ]; + $this->orderRes['coupon_id'] = $couponInfo->id; + } } \ No newline at end of file