From 1c8da064d3875f80f0922bce7b33b519af34cdf1 Mon Sep 17 00:00:00 2001 From: ctexthuang Date: Mon, 31 Mar 2025 10:07:54 +0800 Subject: [PATCH] feat : cart --- app/Constants/Api/CartCode.php | 13 ++ app/Service/Api/Order/CheckCartService.php | 239 +++++++++++++++++++- app/Service/Api/Order/CheckStockService.php | 2 + 3 files changed, 252 insertions(+), 2 deletions(-) create mode 100644 app/Constants/Api/CartCode.php diff --git a/app/Constants/Api/CartCode.php b/app/Constants/Api/CartCode.php new file mode 100644 index 0000000..563667f --- /dev/null +++ b/app/Constants/Api/CartCode.php @@ -0,0 +1,13 @@ +siteId = (int)$this->request->input('site_id'); $this->orderType = (int)$this->request->input('order_type'); - $this->check(); + $todayFlag = $this->checkTodayCutOffTimeByCart(); - return $this->return->success(); +// $this->check(); + $siteFlag = $this->checkSiteByCart($this->siteId); + + $goodInfoFlag = $this->getGoodInfoByCart(); + + $this->__buildCartData($this->request->input('cart')); + + $this->checkGoodByCart(); + + $res = $this->buildRes( $todayFlag, $siteFlag, $goodInfoFlag); + + return $this->return->success('success', ['cart' => $res]); } + + /** + * @param bool $todayFlag + * @param bool $siteFlag + * @param bool $goodInfoFlag + * @return array + */ + private function buildRes(bool $todayFlag, bool $siteFlag, bool $goodInfoFlag): array + { + + if (!$todayFlag || !$siteFlag || !$goodInfoFlag) { + $status = CartCode::GOOD_STATUS_HIDDEN; + } + $res = []; + foreach ($this->cartSecondData as $oneCopies) { + $oneCopiesTotalPrice = '0.00'; + + $oneCopiesGoodInfo = []; + + foreach ($oneCopies as $key => $oneGood) { + if (empty($oneCopiesGoodInfo[$key])) { + $oneCopiesGoodInfo[$key] = [ + 'num' => $oneGood, + 'good_name' => $this->skuArr[$key]['spu_title'] ?? '' . $this->skuArr[$key]['title'] ?? '', + 'good_url' => $this->skuArr[$key]['url'] ?? '', + 'unit_price' => $this->skuArr[$key]['price'], + 'type' => $this->skuArr[$key]['type'], + 'id' => $key, + 'spu_id' => $this->skuArr[$key]['spu_id'], + 'is_add_staple_food' => $this->skuArr[$key]['is_add_staple_food'], + 'meal_copies' => $this->skuArr[$key]['is_add_staple_food'] == GoodCode::IS_ADD_STAPLE_FOOD ? 0 : 1, + 'status' => !empty($status) ? $status : ($this->cartFirstData[$key]['status'] ?? CartCode::GOOD_STATUS_HIDDEN), + ]; + } else { + $oneCopiesGoodInfo[$key]['num'] += $oneGood; + } + + $oneCopiesTotalPrice = bcadd($oneCopiesTotalPrice, bcmul($this->skuArr[$key]['price'],(string)$oneGood,2),2); + } + + $res[] = [ + 'good_info' => array_values($oneCopiesGoodInfo), + 'price' => $oneCopiesTotalPrice, + ]; + } + + return $res; + } + + /** + * 检测商品 + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + private function checkGoodByCart(): void + { + foreach ($this->cartFirstData as $key => &$one) { + if (!in_array($key, $this->goodIds)) $one['status'] = CartCode::GOOD_STATUS_HIDDEN; + + if ($this->orderType == 0) $this->orderType = $this->skuArr[$key]['type']; + if ($this->skuArr[$key]['type'] != $this->orderType) throw new ErrException('自选菜品跟套餐菜品请分开订单下单'); + + if ($this->orderType != OrderCode::ORDER_TYPE_MEAL) return; + + if ($this->isMealCateringByCache($this->siteId, $key, $this->cycleId)) $one['status'] = CartCode::GOOD_STATUS_HIDDEN; + + if (($this->redis->zScore($this->stockKey,$key) ?? 0) < $one['num']) $one['status'] = CartCode::GOOD_STATUS_HIDDEN; + + } + } + + /** + * @return bool + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + protected function checkTodayCutOffTimeByCart(): bool + { + $todayCutOffTime = $this->configCache->getConfigValue(ConfigCode::TODAY_CUT_OFF_TIME_KEY); + $newCycleTime = $this->configCache->getConfigValue(ConfigCode::START_OF_THE_NEW_CYCLE); + + if (date('H:i:s') >= $todayCutOffTime && date('H:i:s') < $newCycleTime) return false; + + return true; + } + + /** + * 生成购物车数据 + * @param array $data + * @return void + */ + private function __buildCartData(array $data): void + { + $copies = 0; + foreach ($data as $oneCopies) { + $one = []; + foreach ($oneCopies as $oneGood) { + if (empty($this->cartFirstData[$oneGood])) { + $this->cartFirstData[$oneGood] = [ + 'status' => CartCode::GOOD_STATUS_NORMAL, + 'num' => 0 + ]; + } + $this->cartFirstData[$oneGood]['num'] = ($this->cartFirstData[$oneGood]['num'] ?? 0) + 1; + $one[$oneGood] = ($one[$oneGood] ?? 0) + 1; + } + + $this->cartSecondData[] = $one; + + $copies++; + } + + $this->copies = $copies; + } + + /** + * 检测地点 + * @param int $siteId + * @return bool + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + private function checkSiteByCart(int $siteId): bool + { + $siteInfo = $this->siteCache->getSiteInfo($siteId); + if (empty($siteInfo)) return false; + + $kitchenId = (int)($siteInfo['kitchen_id'] ?? 0); + if ($kitchenId <= 0) return false; + + $closeOrderFlag = match ($this->orderType) { + OrderCode::ORDER_TYPE_OPTIONAL => $this->checkIsStopOrder($siteId, $this->cycleId), + OrderCode::ORDER_TYPE_MEAL => $this->checkMealIsStopOrder($siteId, $this->cycleId), + }; + + if ($closeOrderFlag) return false; + + $this->kitchenId = $kitchenId; + return true; + } + + /** + * @var int + */ + private int $kitchenId; + + + /** + * 获取商品信息 + * @return bool + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + private function getGoodInfoByCart(): bool + { + $this->stockKey = ApiRedisKey::goodStockKey($this->cycleId,$this->kitchenId); + if (!$this->redis->exists($this->stockKey)) return false; + + $skuArr = []; +// $skuImageArr = []; + switch ($this->orderType) { + case OrderCode::ORDER_TYPE_OPTIONAL: + $optionalGoodKey = ApiRedisKey::optionalGoodListKey($this->cycleId,$this->kitchenId); + $optionalGood = $this->redis->get($optionalGoodKey); + if (empty($optionalGood)) return false; + + $optionalGood = json_decode($optionalGood, true); + + foreach ($optionalGood as $one){ + $newSkuList = array_map(function($sku) use($one) { + $sku['spu_title'] = strtolower($one['title']); + $sku['type'] = GoodCode::SPU_TYPE_OPTIONAL; + return $sku; + }, $one['sku_list']); +// +// $skuImageArr = array_merge($skuImageArr,[ +// $one['id'] => $one['url'] +// ]); + $skuArr = array_merge($skuArr,$newSkuList); + } + + break; + case OrderCode::ORDER_TYPE_MEAL: + $mealGoodKey = ApiRedisKey::mealGoodListKey($this->cycleId,$this->kitchenId); + $mealGood = $this->redis->get($mealGoodKey); + if (empty($mealGood)) return false; + + $mealGood = json_decode($mealGood, true); + + foreach ($mealGood as $one){ + $newSkuList = array_map(function($sku) use($one) { + $sku['spu_title'] = $one['title']; + $sku['type'] = GoodCode::SPU_TYPE_MEAL; + return $sku; + }, $one['sku_list']); + +// $skuImageArr = array_merge($skuImageArr,[ +// $one['id'] => $one['url'] +// ]); +// $skuImageArr = array_merge($skuImageArr,$one['image_list']); + $skuArr = array_merge($skuArr,$newSkuList); + } + + break; + default: + return false; + } + + $this->skuArr = array_column($skuArr,null,'id'); +// $this->skuImageArr = array_column($skuArr,null,'id'); + $this->goodIds = array_column($skuArr,'id'); + + unset($skuArr); + return true; + } + } \ No newline at end of file diff --git a/app/Service/Api/Order/CheckStockService.php b/app/Service/Api/Order/CheckStockService.php index c8e8e19..35dd5a5 100644 --- a/app/Service/Api/Order/CheckStockService.php +++ b/app/Service/Api/Order/CheckStockService.php @@ -28,6 +28,8 @@ class CheckStockService extends BaseOrderService $this->siteId = (int)$this->request->input('site_id'); $skuId = (int)$this->request->input('sku_id'); + $this->checkTodayCutOffTime(); + $kitchenId = $this->checkSite($this->siteId); $this->stockKey = ApiRedisKey::goodStockKey($this->cycleId,$kitchenId);