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.

193 lines
5.6 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. <?php
  2. namespace App\Service\v3\Implementations;
  3. use App\Commons\Log;
  4. use App\Constants\v3\ActivityType;
  5. use App\Constants\v3\ErrorCode;
  6. use App\Constants\v3\LogLabel;
  7. use App\Constants\v3\SsdbKeys;
  8. use App\Service\v3\Interfaces\GoodsActivityServiceInterface;
  9. use App\Service\v3\Interfaces\GoodsInventoryServiceInterface;
  10. use App\TaskWorker\SSDBTask;
  11. use App\Model\v3\GoodsActivity;
  12. use App\Model\v3\GoodsActivityBanner;
  13. use Hyperf\Redis\Redis;
  14. use Hyperf\Utils\ApplicationContext;
  15. use Hyperf\Di\Annotation\Inject;
  16. class GoodsActivityService implements GoodsActivityServiceInterface
  17. {
  18. /**
  19. * @Inject
  20. * @var Log
  21. */
  22. protected $log;
  23. /**
  24. * @Inject
  25. * @var GoodsInventoryServiceInterface
  26. */
  27. protected $goodsInventoryService;
  28. public function do($goodsId)
  29. {
  30. }
  31. public function check(GoodsActivity $goods, $num, $userId)
  32. {
  33. if (empty($goods)) {
  34. return ErrorCode::GOODS_ACTIVITY_NOT_EXISTS;
  35. }
  36. // 活动是否已经结束
  37. if ($goods->expire_time < time()) {
  38. return ErrorCode::GOODS_ACTIVITY_EXPIRED;
  39. }
  40. // 商户歇业
  41. if(is_null($goods->store) || $goods->store->is_open == 0 || $goods->store->is_rest == 1){
  42. return ErrorCode::STORE_REST;
  43. }
  44. // 商品下架或已删除
  45. if($goods->on_sale == 0 || !is_null($goods->deleted_at)){
  46. return ErrorCode::GOODS_ACTIVITY_ON_SALE_NO;
  47. }
  48. // 商品库存不足
  49. // 获取冻结的库存
  50. $inventoryFrozen = $this->goodsInventoryService->getSold(2, $goods->id);
  51. // $inventoryFrozen = 0;
  52. if($goods->is_infinite != 1 && $goods->inventory < ($num+$inventoryFrozen)){
  53. return ErrorCode::GOODS_ACTIVITY_INVENTORY_ERROR;
  54. }
  55. // 是否超过限购数量
  56. if (($goods->restrict_num <= $inventoryFrozen || $goods->restrict_num <= 0) && $goods->restrict_num < $num) {
  57. return ErrorCode::GOODS_ACTIVITY_RESTRICT_LIMIT;
  58. }
  59. // 是否已经购买过(某个时间段内,时间段有商品的限制)
  60. $ssdb = ApplicationContext::getContainer()->get(SSDBTask::class);
  61. $hasBuy = $ssdb->exec('get', SsdbKeys::ACTIVITY_GOODS_BUY_RECORD.$userId.'_'.$goods->type.'_'.$goods->id);
  62. if ($hasBuy && $hasBuy >= $goods->time_limit_num) {
  63. return ErrorCode::GOODS_ACTIVITY_BUY;
  64. }
  65. return true;
  66. }
  67. public function undo()
  68. {
  69. // TODO: Implement undo() method.
  70. }
  71. public function getBanner($goodsId)
  72. {
  73. $banner = GoodsActivityBanner::query()->where('goods_id',$goodsId)->orderByDesc('type')->get();
  74. return $banner;
  75. }
  76. public function detail($goodsId)
  77. {
  78. $res = GoodsActivity::query()->with('store')->where('id',$goodsId)->first();
  79. return $res;
  80. }
  81. public function cacheRecord($goodsId, $num, $userId)
  82. {
  83. $goods = GoodsActivity::query()
  84. ->where('id', $goodsId)
  85. ->first();
  86. $ssdbKey = SsdbKeys::ACTIVITY_GOODS_BUY_RECORD.$userId.'_'.$goods->type.'_'.$goodsId;
  87. $expireTime = 0;
  88. if ($goods->time_limit_days >= 1) {
  89. $expireTime += strtotime(date('Y-m-d 23:59:59')) - time();
  90. $expireTime += ($goods->time_limit_days-1) * 86400;
  91. } elseif ($goods->time_limit_days > 0 && $goods->time_limit_days < 1) {
  92. $expireTime += bcmul($goods->time_limit_days,86400,0);
  93. } else {
  94. return;
  95. }
  96. $ssdb = ApplicationContext::getContainer()->get(SSDBTask::class);
  97. if (!$ssdb->exec('exists', $ssdbKey)) {
  98. $ssdb->exec('set', $ssdbKey, $num);
  99. $ssdb->exec('expire', $ssdbKey, $expireTime);
  100. } else {
  101. $ssdb->exec('incr', $ssdbKey, $num);
  102. }
  103. }
  104. public function clearCacheRecord($goodsId, $num, $userId)
  105. {
  106. $goods = GoodsActivity::query()
  107. ->where('id', $goodsId)
  108. ->first();
  109. if (empty($goods)) {
  110. return true;
  111. }
  112. $ssdbKey = SsdbKeys::ACTIVITY_GOODS_BUY_RECORD.$userId.'_'.$goods->type.'_'.$goodsId;
  113. $ssdb = ApplicationContext::getContainer()->get(SSDBTask::class);
  114. if ($ssdb->exec('exists', $ssdbKey)) {
  115. $res = $ssdb->exec('incr', $ssdbKey, -1*$num);
  116. }
  117. }
  118. /**
  119. * 统计订单中活动商品的数量,并校验
  120. * @param $goodsIds
  121. * @param int $limitNum
  122. * @return bool
  123. */
  124. public function checkOrderActivityCount($goodsIds, $limitNum=1)
  125. {
  126. $sourceGoods = GoodsActivity::query()
  127. ->whereIn('id', $goodsIds)
  128. ->get()->toArray();
  129. $redis = ApplicationContext::getContainer()->get(Redis::class);
  130. $activityTypeLimitNumsKey = 'activity_type_limit_nums';
  131. $limitNums = $redis->hGetAll($activityTypeLimitNumsKey);
  132. if (empty($limitNums)) {
  133. $limitNums = [
  134. ActivityType::FLASH_SALE => 0,
  135. ActivityType::GROUP_BUY => 0,
  136. ActivityType::NEW_PRODUCT => 0,
  137. ];
  138. }
  139. $buyNum = [
  140. ActivityType::FLASH_SALE => 0,
  141. ActivityType::GROUP_BUY => 0,
  142. ActivityType::NEW_PRODUCT => 0,
  143. ];
  144. foreach ($sourceGoods as $key => &$goods) {
  145. if ($limitNums[$goods['type']] == 0) { // 不限制同类购买商品种数,也就是可以同时购买多款不同商品
  146. continue;
  147. }
  148. $buyNum[$goods['type']] += 1;
  149. if ($buyNum[$goods['type']] > $limitNums[$goods['type']]) {
  150. return false;
  151. }
  152. }
  153. return true;
  154. }
  155. }