feat : cart

This commit is contained in:
2025-03-31 10:07:54 +08:00
parent e9ead2bd6b
commit 1c8da064d3
3 changed files with 252 additions and 2 deletions

View File

@@ -0,0 +1,13 @@
<?php
namespace App\Constants\Api;
class CartCode
{
/**
* 商品 1= 正常 2= 错误
*/
const GOOD_STATUS_NORMAL = 1;
const GOOD_STATUS_HIDDEN = 2;
}

View File

@@ -10,6 +10,13 @@ declare(strict_types=1);
namespace App\Service\Api\Order;
use App\Cache\Redis\Api\ApiRedisKey;
use App\Constants\Api\CartCode;
use App\Constants\ApiCode;
use App\Constants\Common\GoodCode;
use App\Constants\Common\OrderCode;
use App\Constants\ConfigCode;
use App\Exception\ErrException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
@@ -25,8 +32,236 @@ class CheckCartService extends BaseOrderService
$this->siteId = (int)$this->request->input('site_id');
$this->orderType = (int)$this->request->input('order_type');
$this->check();
$todayFlag = $this->checkTodayCutOffTimeByCart();
// $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 $this->return->success();
}
}
/**
* @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;
}
}

View File

@@ -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);