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.

236 lines
7.8 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
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\Goods as GoodsConstants;
  7. use App\Constants\v3\LogLabel;
  8. use App\Constants\v3\SsdbKeys;
  9. use App\Model\v3\Store;
  10. use App\Service\v3\Interfaces\GoodsActivityServiceInterface;
  11. use App\Service\v3\Interfaces\GoodsInventoryServiceInterface;
  12. use App\TaskWorker\SSDBTask;
  13. use App\Model\v3\GoodsActivity;
  14. use App\Model\v3\GoodsActivityBanner;
  15. use Hyperf\Redis\Redis;
  16. use Hyperf\Utils\ApplicationContext;
  17. use Hyperf\Di\Annotation\Inject;
  18. class GoodsActivityService implements GoodsActivityServiceInterface
  19. {
  20. /**
  21. * @Inject
  22. * @var Log
  23. */
  24. protected $log;
  25. /**
  26. * @Inject
  27. * @var GoodsInventoryServiceInterface
  28. */
  29. protected $goodsInventoryService;
  30. public function do($goodsId)
  31. {
  32. }
  33. public function check(GoodsActivity $goods, $num, $userId)
  34. {
  35. if (empty($goods)) {
  36. return ErrorCode::GOODS_ACTIVITY_NOT_EXISTS;
  37. }
  38. // 活动是否已经结束
  39. if ($goods->expire_time < time()) {
  40. return ErrorCode::GOODS_ACTIVITY_EXPIRED;
  41. }
  42. // 商户歇业
  43. if(is_null($goods->store) || $goods->store->is_open == 0 || $goods->store->is_rest == 1){
  44. return ErrorCode::STORE_REST;
  45. }
  46. // 商品下架或已删除
  47. if($goods->on_sale == 0 || !is_null($goods->deleted_at)){
  48. return ErrorCode::GOODS_ACTIVITY_ON_SALE_NO;
  49. }
  50. // 商品库存不足
  51. // 获取冻结的库存
  52. $inventoryFrozen = $this->goodsInventoryService->getSold(2, $goods->id);
  53. // $inventoryFrozen = 0;
  54. if($goods->is_infinite != 1 && $goods->inventory < ($num+$inventoryFrozen)){
  55. return ErrorCode::GOODS_ACTIVITY_INVENTORY_ERROR;
  56. }
  57. // 是否超过限购数量
  58. if ($goods->restrict_num > 0 && $goods->restrict_num < $num) {
  59. return ErrorCode::GOODS_ACTIVITY_RESTRICT_LIMIT;
  60. }
  61. // 是否已经购买过(某个时间段内,时间段有商品的限制)
  62. $ssdb = ApplicationContext::getContainer()->get(SSDBTask::class);
  63. $hasBuy = $ssdb->exec('get', SsdbKeys::ACTIVITY_GOODS_BUY_RECORD.$userId.'_'.$goods->type.'_'.$goods->id);
  64. if ($hasBuy && $hasBuy >= $goods->time_limit_num) {
  65. return ErrorCode::GOODS_ACTIVITY_BUY;
  66. }
  67. return true;
  68. }
  69. public function undo()
  70. {
  71. // TODO: Implement undo() method.
  72. }
  73. public function getBanner($goodsId)
  74. {
  75. $banner = GoodsActivityBanner::query()->where('goods_id',$goodsId)->orderByDesc('type')->get();
  76. return $banner;
  77. }
  78. public function detail($goodsId)
  79. {
  80. $res = GoodsActivity::query()->with('store')->where('id',$goodsId)->first();
  81. return $res;
  82. }
  83. public function cacheRecord($goodsId, $num, $userId)
  84. {
  85. $goods = GoodsActivity::query()
  86. ->where('id', $goodsId)
  87. ->first();
  88. $ssdbKey = SsdbKeys::ACTIVITY_GOODS_BUY_RECORD.$userId.'_'.$goods->type.'_'.$goodsId;
  89. $expireTime = 0;
  90. if ($goods->time_limit_days >= 1) {
  91. $expireTime += strtotime(date('Y-m-d 23:59:59')) - time();
  92. $expireTime += ($goods->time_limit_days-1) * 86400;
  93. } elseif ($goods->time_limit_days > 0 && $goods->time_limit_days < 1) {
  94. $expireTime += bcmul($goods->time_limit_days,86400,0);
  95. } else {
  96. return;
  97. }
  98. $ssdb = ApplicationContext::getContainer()->get(SSDBTask::class);
  99. if (!$ssdb->exec('exists', $ssdbKey)) {
  100. $ssdb->exec('set', $ssdbKey, $num);
  101. $ssdb->exec('expire', $ssdbKey, $expireTime);
  102. } else {
  103. $ssdb->exec('incr', $ssdbKey, $num);
  104. }
  105. }
  106. public function clearCacheRecord($goodsId, $num, $userId)
  107. {
  108. $goods = GoodsActivity::query()
  109. ->where('id', $goodsId)
  110. ->first();
  111. if (empty($goods)) {
  112. return true;
  113. }
  114. $ssdbKey = SsdbKeys::ACTIVITY_GOODS_BUY_RECORD.$userId.'_'.$goods->type.'_'.$goodsId;
  115. $ssdb = ApplicationContext::getContainer()->get(SSDBTask::class);
  116. if ($ssdb->exec('exists', $ssdbKey)) {
  117. $res = $ssdb->exec('incr', $ssdbKey, -1*$num);
  118. }
  119. }
  120. /**
  121. * 统计订单中活动商品的数量,并校验
  122. * @param $goodsIds
  123. * @param int $limitNum
  124. * @return bool
  125. */
  126. public function checkOrderActivityCount($goodsIds, $limitNum=1)
  127. {
  128. $sourceGoods = GoodsActivity::query()
  129. ->whereIn('id', $goodsIds)
  130. ->get()->toArray();
  131. $redis = ApplicationContext::getContainer()->get(Redis::class);
  132. $activityTypeLimitNumsKey = 'activity_type_limit_nums';
  133. $limitNums = $redis->hGetAll($activityTypeLimitNumsKey);
  134. if (empty($limitNums)) {
  135. $limitNums = [
  136. ActivityType::FLASH_SALE => 0,
  137. ActivityType::GROUP_BUY => 0,
  138. ActivityType::NEW_PRODUCT => 0,
  139. ];
  140. }
  141. $buyNum = [
  142. ActivityType::FLASH_SALE => 0,
  143. ActivityType::GROUP_BUY => 0,
  144. ActivityType::NEW_PRODUCT => 0,
  145. ];
  146. foreach ($sourceGoods as $key => &$goods) {
  147. if ($limitNums[$goods['type']] == 0) { // 不限制同类购买商品种数,也就是可以同时购买多款不同商品
  148. continue;
  149. }
  150. $buyNum[$goods['type']] += 1;
  151. if ($buyNum[$goods['type']] > $limitNums[$goods['type']]) {
  152. return false;
  153. }
  154. }
  155. return true;
  156. }
  157. public function getList($marketId,$page,$pagesize)
  158. {
  159. $storeTable = ApplicationContext::getContainer()->get(Store::class)->getTable();
  160. $goodsTable = ApplicationContext::getContainer()->get(GoodsActivity::class)->getTable();
  161. $builder = GoodsActivity::query()
  162. ->join($storeTable, ''.$storeTable.'.id', '=', ''.$goodsTable.'.store_id')
  163. ->with(['store'])
  164. //->where([''.$goodsTable.'.type' => $type])
  165. ->where(function ($query) use ($marketId, $goodsTable) {
  166. $query->whereJsonContains(''.$goodsTable.'.market_ids', [(string)$marketId])
  167. ->orWhereJsonLength(''.$goodsTable.'.market_ids', '=', 0);
  168. })
  169. ->where([''.$goodsTable.'.on_sale' => GoodsConstants::ON_SALE_YES])
  170. // ->where(function ($query) use ($goodsTable) {
  171. // $query->where(''.$goodsTable.'.inventory', '>', 0)->orWhere(''.$goodsTable.'.is_infinite', '=', 1);
  172. // })
  173. ->whereRaw(''.$goodsTable.'.deleted_at IS NULL')
  174. ->where([''.$storeTable.'.market_id' => $marketId])
  175. ->where([''.$storeTable.'.is_open' => \App\Constants\v3\Store::IS_OPEN_YES])
  176. ->where([''.$storeTable.'.is_rest' => \App\Constants\v3\Store::IS_REST_NO])
  177. ->where('time1', '<=', date('H:i'))
  178. ->where(function ($query) {
  179. $query->where('time2', '>=', date('H:i'))
  180. ->orWhere('time4', '>=', date('H:i'));
  181. })
  182. ->where(''.$goodsTable.'.expire_time', '>', time());
  183. $paginate = $builder->select(''.$goodsTable.'.*')->addSelect(''.$goodsTable.'.sales as total_sales')
  184. ->orderBy(''.$goodsTable.'.sort', 'DESC')
  185. ->orderBy(''.$goodsTable.'.expire_time', 'ASC')
  186. ->orderBy(''.$goodsTable.'.created_at', 'DESC')
  187. ->paginate($pagesize);
  188. $goodsArr = $paginate->toArray();
  189. $goods = collect($goodsArr['data']);
  190. $goods = $goods->sortBy(function ($product, $key) {
  191. return $product['noneffective_note'];
  192. });
  193. $goods = $goods->values()->all();
  194. return ['has_more_pages' => $paginate->hasMorePages(), 'goods' => $goods];
  195. }
  196. }