From 0d2932ea4aa93593be38f0598adc92172b5649a5 Mon Sep 17 00:00:00 2001 From: ctexthuang Date: Tue, 4 Mar 2025 17:42:49 +0800 Subject: [PATCH] feat : coupon --- app/Model/CouponTemplate.php | 30 ++++++++++++ app/Model/UserCoupon.php | 15 ++++++ app/Service/Api/Order/BaseOrderService.php | 14 ++++++ .../Api/Order/ConfirmationOrderService.php | 47 +++++++++++++++++++ 4 files changed, 106 insertions(+) diff --git a/app/Model/CouponTemplate.php b/app/Model/CouponTemplate.php index a0c1b4a..d95d05f 100644 --- a/app/Model/CouponTemplate.php +++ b/app/Model/CouponTemplate.php @@ -4,6 +4,8 @@ declare(strict_types=1); namespace App\Model; +use App\Constants\Common\CouponCode; +use Hyperf\Collection\Collection; use Hyperf\DbConnection\Model\Model; /** @@ -68,4 +70,32 @@ class CouponTemplate extends Model return $res; } + + /** + * @param int $userId + * @return Collection + */ + public function getNoUseCouponByUserId(int $userId): Collection + { + return $this + ->join('user_coupon', function ($join) use ($userId) { + $join->on('user_coupon.coupon_template_id', '=', 'coupon_template.id') + ->where('user_coupon.user_id', '=', $userId) + ->where('user_coupon.status', '=', CouponCode::COUPON_STATUS_UNUSED) + ->where('validity_start_time', '<=', date('Y-m-d H:i:s')) + ->where('validity_end_time', '>=', date('Y-m-d H:i:s')) + ->select([ + 'coupon_template.coupon_type', + 'coupon_template.amount', + 'coupon_template.ratio', + 'user_coupon.id', + 'user_coupon.coupon_template_id', + 'user_coupon.coupon_name', + 'user_coupon.status', + 'user_coupon.validity_start_time', + 'user_coupon.validity_end_time', + ]); + }) + ->get(); + } } diff --git a/app/Model/UserCoupon.php b/app/Model/UserCoupon.php index 9e9756b..f728bda 100644 --- a/app/Model/UserCoupon.php +++ b/app/Model/UserCoupon.php @@ -4,6 +4,9 @@ declare(strict_types=1); namespace App\Model; +use App\Constants\Common\CouponCode; +use Hyperf\Database\Model\Builder; +use Hyperf\Database\Model\Collection; use Hyperf\DbConnection\Model\Model; /** @@ -48,4 +51,16 @@ class UserCoupon extends Model ->pluck('coupon_id') ->toArray(); } + + /** + * @param int $userId + * @return Builder[]|Collection + */ + public function getNoUseCouponByUserId(int $userId): Collection|array + { + return $this + ->where('user_id', $userId) + ->where('status', CouponCode::COUPON_STATUS_UNUSED) + ->get(); + } } diff --git a/app/Service/Api/Order/BaseOrderService.php b/app/Service/Api/Order/BaseOrderService.php index 838d4bb..873e025 100644 --- a/app/Service/Api/Order/BaseOrderService.php +++ b/app/Service/Api/Order/BaseOrderService.php @@ -12,6 +12,8 @@ namespace App\Service\Api\Order; use App\Cache\Redis\Common\ConfigCache; use App\Cache\Redis\RedisCache; +use App\Model\CouponTemplate; +use App\Model\UserCoupon; use App\Service\Api\BaseService; use App\Service\ServiceTrait\Api\OrderTrait; use App\Service\ServiceTrait\Common\CycleTrait; @@ -50,6 +52,18 @@ abstract class BaseOrderService extends BaseService #[Inject] protected ConfigCache $configCache; + /** + * @var UserCoupon + */ + #[Inject] + protected UserCoupon $userCouponModel; + + /** + * @var CouponTemplate + */ + #[Inject] + protected CouponTemplate $couponTemplateModel; + /** * @var array */ diff --git a/app/Service/Api/Order/ConfirmationOrderService.php b/app/Service/Api/Order/ConfirmationOrderService.php index 66a4510..3046102 100644 --- a/app/Service/Api/Order/ConfirmationOrderService.php +++ b/app/Service/Api/Order/ConfirmationOrderService.php @@ -10,6 +10,7 @@ declare(strict_types=1); namespace App\Service\Api\Order; +use App\Constants\Common\CouponCode; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; @@ -36,6 +37,52 @@ class ConfirmationOrderService extends BaseOrderService $this->compute(); + $this->autoSelectCoupon(); + return $this->return->success('success',$this->orderRes); } + + private function autoSelectCoupon(): void + { + if ($this->couponId != 0) return; + + $noUseCoupon = $this->couponTemplateModel->getNoUseCouponByUserId($this->userId); + + if ($noUseCoupon->isEmpty()) return; + + $noUseCoupon = $noUseCoupon->toArray(); + + $orderMaxPrice = max(array_column($this->orderRes['good'],'price')); + $maxValidityEndTimeDate = max(array_column($noUseCoupon,'validity_end_time')); + + $filtered = array_filter($noUseCoupon, function($item) use($maxValidityEndTimeDate) { + return $item['validity_end_time'] === $maxValidityEndTimeDate; + }); + + $selectMaxPrice = 0; + $selectCouponInfo = []; + foreach ($filtered as &$value) { + $value['amount'] = match ($value['coupon_type']) { + CouponCode::COUPON_TYPE_INSTANT_REDUCTION => $value['amount'], + CouponCode::COUPON_TYPE_DISCOUNT => $value['amount'] * $orderMaxPrice, + default => 0 + }; + + if ($value['amount'] < $selectMaxPrice) continue; + + $selectMaxPrice = $value['amount']; + $selectCouponInfo = $value; + } + + $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