You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

169 lines
5.7 KiB

  1. <?php
  2. namespace App\Service\v3\Implementations;
  3. use App\Constants\v3\ErrorCode;
  4. use App\Constants\v3\LogLabel;
  5. use App\Exception\ErrorCodeException;
  6. use App\Model\v3\CouponRec;
  7. use App\Model\v3\CouponUse;
  8. use App\Model\v3\OrderMain;
  9. use App\Service\v3\Interfaces\CouponServiceInterface;
  10. use Hyperf\DbConnection\Db;
  11. use Hyperf\Redis\Redis;
  12. use Hyperf\Utils\ApplicationContext;
  13. class CouponService implements CouponServiceInterface
  14. {
  15. /**
  16. * @inheritDoc
  17. */
  18. public function do()
  19. {
  20. // TODO: Implement do() method.
  21. }
  22. /**
  23. * @inheritDoc
  24. */
  25. public function check()
  26. {
  27. // TODO: Implement check() method.
  28. }
  29. /**
  30. * @inheritDoc
  31. */
  32. public function undo()
  33. {
  34. // TODO: Implement undo() method.
  35. }
  36. /**
  37. * @inheritDoc
  38. */
  39. public function countAvailableByUser($userId)
  40. {
  41. return mt_rand(0,10);
  42. }
  43. /**
  44. * 缓存优惠券今日使用情况
  45. * @param $userId
  46. * @param $couponId
  47. * @param $couponRecId
  48. * @return bool
  49. */
  50. function cacheTodayCouponUsed($userId, $couponId, $couponRecId)
  51. {
  52. $redis = ApplicationContext::getContainer()->get(Redis::class);
  53. $setRes = $redis->sAdd('coupon_' . date('Ymd') . '_used_' . $userId, $couponId);
  54. $expireRes = $redis->expire('coupon_' . date('Ymd') . '_used_' . $userId, strtotime(date('Y-m-d') . ' 23:59:59') - time());
  55. return $setRes && $expireRes;
  56. }
  57. public function orderUseCoupons($orderMainId, $couponRecs)
  58. {
  59. Db::beginTransaction();
  60. try {
  61. if (is_array($couponRecs)&&!empty($couponRecs)) {
  62. # 使用记录、更新当前优惠券
  63. foreach ($couponRecs as $key => &$coupon) {
  64. $couponUse = [
  65. 'user_id' => $coupon['user_id'],
  66. 'user_receive_id' => $coupon['id'],
  67. 'coupon_id' => $coupon['coupon_id'],
  68. 'order_main_id' => $orderMainId,
  69. 'use_time' => time(),
  70. 'return_time' => 0,
  71. 'number' => 1,
  72. 'status' => 1,
  73. 'update_time' => 0,
  74. ];
  75. $insertRes = CouponUse::query()->insert($couponUse);
  76. if ($insertRes) {
  77. $status = 0;
  78. $numberRemain = $coupon['number_remain'] - 1;
  79. if ($numberRemain == 0) {
  80. $status = 2;
  81. } elseif ($numberRemain > 0 && $numberRemain < $coupon['number']) {
  82. $status = 1;
  83. } elseif ($numberRemain == $coupon['number']) {
  84. $status = 0;
  85. }
  86. $upRes = CouponRec::query()->where(['id' => $coupon['id']])
  87. ->update(['number_remain' => $numberRemain, 'status' => $status]);
  88. if (!$upRes) {
  89. Db::rollBack();
  90. throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE);
  91. }
  92. // 缓存使用记录
  93. $usedRes = $this->cacheTodayCouponUsed($coupon['user_id'], $coupon['coupon_id'], $coupon['id']);
  94. if (!$usedRes) {
  95. Db::rollBack();
  96. throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE);
  97. }
  98. } else {
  99. Db::rollBack();
  100. throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE);
  101. }
  102. }
  103. }
  104. Db::commit();
  105. } catch (\Exception $e) {
  106. Db::rollBack();
  107. throw new ErrorCodeException(ErrorCode::COUPON_USE_FAILURE, $e->getMessage());
  108. }
  109. }
  110. /**
  111. * 退还优惠券,订单取消,申请退款成功时
  112. * 先查询是否正常使用优惠券
  113. * 修改状态,退还领取记录库存,删除ssdb缓存
  114. * @param $orderMainId
  115. * @return bool
  116. */
  117. public function orderRefundCoupons($orderMainId)
  118. {
  119. $currentTime = time();
  120. Db::beginTransaction();
  121. try {
  122. $couponUses = CouponUse::query()
  123. ->where('order_main_id', $orderMainId)
  124. ->where('status', 1)
  125. ->get();
  126. if (!empty($couponUses)) {
  127. foreach ($couponUses as $use) {
  128. $use->status = 1;
  129. $use->return_time = $currentTime;
  130. $use->update_time = $currentTime;
  131. $res = $use->save();
  132. $couponReceive = CouponRec::query()
  133. ->where('id', $use->user_receive_id)
  134. ->whereRaw('number >= number_remain+' . $use->number)
  135. ->update([
  136. 'number_remain' => Db::raw('number_remain+' . $use->number),
  137. 'status' => Db::raw('IF(number=number_remain, 0,1)'), 'update_time' => $currentTime
  138. ]);
  139. if ($res && $couponReceive) {
  140. $redis = ApplicationContext::getContainer()->get(Redis::class);
  141. $clearUseRedis = $redis->sRem('coupon_' . date('Ymd') . '_used_' . $use->user_id, $use->coupon_id);
  142. }
  143. }
  144. }
  145. Db::commit();
  146. return true;
  147. } catch (\Exception $e) {
  148. $this->log->event(LogLabel::COUPON_REFUND_LOG, ['msg' => '订单取消/退款退还优惠券', 'exception' => $e->getMessage()]);
  149. Db::rollBack();
  150. return false;
  151. }
  152. }
  153. }