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.

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