From 39be37f9a5180c78f39e5b896ba188711d60034a Mon Sep 17 00:00:00 2001 From: ctexthuang Date: Tue, 15 Apr 2025 10:54:31 +0800 Subject: [PATCH] feat : sts --- app/Constants/Common/GoodCode.php | 9 +- app/Constants/ConfigCode.php | 6 +- app/Controller/Admin/GoodController.php | 20 ++- app/Model/Sku.php | 4 + app/Model/Spu.php | 5 +- app/Service/Admin/Good/FavorableService.php | 159 +++++++++++++++++- app/Service/Admin/Good/SkuService.php | 31 +++- app/Service/Admin/Good/SpuService.php | 12 +- .../Api/Evaluation/EvaluationService.php | 2 +- app/Service/Api/Good/OptionalListService.php | 17 +- 10 files changed, 249 insertions(+), 16 deletions(-) diff --git a/app/Constants/Common/GoodCode.php b/app/Constants/Common/GoodCode.php index 99b1ef9..7f94478 100644 --- a/app/Constants/Common/GoodCode.php +++ b/app/Constants/Common/GoodCode.php @@ -17,10 +17,11 @@ class GoodCode const int SKU_IS_DELETE = 2; /** - * @var int 1=自选 2=套餐 + * @var int 1=自选 2=套餐 3=特惠(列表) */ CONST INT SPU_TYPE_OPTIONAL = 1; CONST INT SPU_TYPE_MEAL = 2; + CONST INT SPU_TYPE_FAVORABLE = 3; /** * @var int 1=上架 2=下架 @@ -33,4 +34,10 @@ class GoodCode */ CONST INT IS_ADD_STAPLE_FOOD = 1; CONST INT IS_NOT_ADD_STAPLE_FOOD = 2; + + /** + * @var int 特惠 1=是 2=否 + */ + CONST INT IS_FAVORABLE = 1; + CONST INT NOT_FAVORABLE = 2; } \ No newline at end of file diff --git a/app/Constants/ConfigCode.php b/app/Constants/ConfigCode.php index 7b2ead4..e7a8ef1 100644 --- a/app/Constants/ConfigCode.php +++ b/app/Constants/ConfigCode.php @@ -22,6 +22,8 @@ class ConfigCode const string APP_LOGO = 'AppLogo'; // app 图标 const string ONE_CLICK_SHOPPING_FOR_CATEGORY_NAME = 'OneClickShoppingForCategoryName'; // 一键选购分类名称 const string ONE_CLICK_SHOPPING_FOR_CATEGORY_IMAGE = 'OneClickShoppingForCategoryImage'; // 一键选购分类图片 + const string SPECIALS_CATEGORY_NAME = 'SpecialsCategoryName'; //特惠商品分类名称 + const string SPECIALS_CATEGORY_IMAGE = 'SpecialsCategoryImage'; // 特惠商品分类图片 /** @@ -55,8 +57,10 @@ class ConfigCode self::USER_AGREEMENT => 'https://www.baidu.com', self::USER_PRIVACY_AGREEMENT => 'https://www.baidu.com', self::APP_LOGO => 0, - self::ONE_CLICK_SHOPPING_FOR_CATEGORY_NAME => '一件选购', + self::ONE_CLICK_SHOPPING_FOR_CATEGORY_NAME => '一键选购', self::ONE_CLICK_SHOPPING_FOR_CATEGORY_IMAGE => 0, + self::SPECIALS_CATEGORY_NAME => '特惠商品', + self::SPECIALS_CATEGORY_IMAGE => 0, //CouponConfiguration self::COUPONS_FOR_NEWCOMERS => '0', self::NEWBIE_COUPON_VALIDITY => '0', diff --git a/app/Controller/Admin/GoodController.php b/app/Controller/Admin/GoodController.php index eab93fc..13910dd 100644 --- a/app/Controller/Admin/GoodController.php +++ b/app/Controller/Admin/GoodController.php @@ -189,10 +189,26 @@ class GoodController extends AbstractController return (new CategoryService)->add(); } - + /** + * 添加特惠 + * @return array + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + #[RequestMapping(path: "add_favorable", methods: "POST")] + #[Scene(scene: "add_favorable")] public function addFavorable() { - //todo return (new FavorableService())->handle(); } + + /** + * @return array + */ + #[RequestMapping(path: "list_favorable", methods: "GET")] + #[Scene(scene: "list_favorable")] + public function listFavorable(): array + { + return (new FavorableService)->list(); + } } diff --git a/app/Model/Sku.php b/app/Model/Sku.php index 91e27ef..6693a42 100644 --- a/app/Model/Sku.php +++ b/app/Model/Sku.php @@ -30,6 +30,8 @@ use Hyperf\DbConnection\Model\Model; * @property int $is_del * @property int $code_number * @property int $occupied + * @property int $favorable + * @property int $origin_sku_id * @property int $is_add_staple_food * @property string $create_time * @property string $update_time @@ -66,6 +68,8 @@ class Sku extends Model 'is_add_staple_food' => 'integer', 'code_number' => 'integer', 'occupied' => 'integer', + 'favorable' => 'integer', + 'origin_sku_id' => 'integer', ]; const string CREATED_AT = 'create_time'; diff --git a/app/Model/Spu.php b/app/Model/Spu.php index 39c6fac..c2978fe 100644 --- a/app/Model/Spu.php +++ b/app/Model/Spu.php @@ -22,6 +22,7 @@ use Hyperf\DbConnection\Model\Model; * @property int $category_id * @property int $saleable * @property int $type + * @property int $favorable * @property int $sort * @property int $is_del * @property string $create_time @@ -44,7 +45,7 @@ class Spu extends Model /** * The attributes that should be cast to native types. */ - protected array $casts = ['id' => 'integer', 'cycle_id' => 'integer', 'city_id' => 'integer', 'kitchen_id' => 'integer','chef_id' => 'integer','caterer_id' => 'integer','category_id' => 'integer', 'saleable' => 'integer','type' => 'integer','sort' => 'integer']; + protected array $casts = ['id' => 'integer', 'cycle_id' => 'integer', 'city_id' => 'integer', 'kitchen_id' => 'integer','chef_id' => 'integer','caterer_id' => 'integer','category_id' => 'integer', 'saleable' => 'integer','type' => 'integer','sort' => 'integer','favorable' => 'integer']; const string CREATED_AT = 'create_time'; const string UPDATED_AT = 'update_time'; @@ -84,7 +85,7 @@ class Spu extends Model ->where('type',$type) ->where('saleable',GoodCode::LISTING) ->orderBy('sort') - ->select(['id','cycle_id','chef_id','title','title','sub_title','category_id']) + ->select(['id','cycle_id','chef_id','title','title','sub_title','category_id','favorable']) ->get(); } diff --git a/app/Service/Admin/Good/FavorableService.php b/app/Service/Admin/Good/FavorableService.php index f9a6f77..87965eb 100644 --- a/app/Service/Admin/Good/FavorableService.php +++ b/app/Service/Admin/Good/FavorableService.php @@ -10,9 +10,17 @@ declare(strict_types=1); namespace App\Service\Admin\Good; +use App\Cache\Redis\Api\GoodCache; +use App\Constants\Common\GoodCode; +use App\Exception\ErrException; use App\Model\Sku; +use App\Model\Spu; use App\Service\Admin\BaseService; +use Hyperf\DbConnection\Db; use Hyperf\Di\Annotation\Inject; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; +use const _PHPStan_14faee166\GO; class FavorableService extends BaseService { @@ -22,10 +30,157 @@ class FavorableService extends BaseService #[Inject] protected Sku $skuModel; - public function handle() + /** + * @var GoodCache + */ + #[Inject] + protected GoodCache $goodCache; + + /** + * @var Spu + */ + #[Inject] + protected Spu $spuModel; + + /** + * @return array + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function handle(): array { - //todo + $stock = $this->request->input('stock'); $skuId = $this->request->input('sku_id'); + $skuInfo = $this->skuModel->find($skuId); + if (empty($skuInfo)) throw new ErrException('该商品不存在'); + $spuInfo = $this->spuModel->find($skuInfo->spu_id); + if (empty($spuInfo)) throw new ErrException('该商品spu不存在'); + + if ($stock > $skuInfo->surplus_stock) throw new ErrException('该商品库存不支持参与如此的秒杀库存,请减少至小于剩余库存,剩余库存为'.$skuInfo->surplus_stock); + + if ($skuInfo->favorable == GoodCode::IS_FAVORABLE) throw new ErrException('该商品已参与秒杀,不支持重复参与秒杀'); + + if ($skuInfo->is_add_staple_food == GoodCode::IS_ADD_STAPLE_FOOD) throw new ErrException('该商品为 staple food 商品,不支持参与秒杀'); + + if ($spuInfo->type == GoodCode::SPU_TYPE_MEAL) throw new ErrException('该商品为套餐商品,不支持参与秒杀'); + + $favorable = $this->spuModel->where('type',GoodCode::SPU_TYPE_OPTIONAL)->where('kitchen_id',$spuInfo->kitchen_id)->where('cycle_id',$spuInfo->cycle_id)->where('favorable',GoodCode::IS_FAVORABLE)->first(); + + Db::transaction(function () use ($skuId, $stock, $skuInfo, $favorable, $spuInfo) { + if (empty($favorable)) { + $favorable = new Spu(); + + $favorable->city_id = $spuInfo->city_id; + $favorable->cycle_id = $spuInfo->cycle_id; + $favorable->kitchen_id = $spuInfo->kitchen_id; +// $insertModel->chef_id = $this->request->input('chef_id'); + $favorable->title = '特惠商品'; + $favorable->sub_title = $spuInfo->sub_title; + $favorable->caterer_id = $spuInfo->caterer_id; + $favorable->category_id = $spuInfo->category_id; + $favorable->saleable = $spuInfo->saleable; + $favorable->type = $spuInfo->type; + $favorable->sort = $spuInfo->sort; + $favorable->favorable = GoodCode::IS_FAVORABLE; + + if (!$favorable->save()) throw new ErrException('添加特惠 spu 失败'); + } + + $insertModel = new Sku(); + + $insertModel->spu_id = $favorable->id; + $insertModel->title = $skuInfo->title; + $insertModel->sub_title = $skuInfo->sub_title; + $insertModel->price = $this->request->input('price'); + $insertModel->chef_id = $skuInfo->chef_id; + $insertModel->image_ids = $skuInfo->image_ids; + $insertModel->param = $skuInfo->param; + $insertModel->extra = $skuInfo->extra; + $insertModel->total_stock = $stock; + $insertModel->surplus_stock = $stock; + $insertModel->sales_num = 0; + $insertModel->order_num = 0; + $insertModel->cancel_num = 0; + $insertModel->refund_num = 0; + $insertModel->occupied = $skuInfo->occupied; +// $insertModel->behind_refund_num = 0; + $insertModel->saleable = $skuInfo->saleable; + $insertModel->is_add_staple_food = $skuInfo->is_add_staple_food; + $insertModel->code_number = $skuInfo->code_number; + $insertModel->sort = $skuInfo->sort; + $insertModel->origin_sku_id = $skuInfo->id; + $insertModel->favorable = GoodCode::IS_FAVORABLE; + + if (!$insertModel->save()) throw new ErrException('添加sku失败'); + + + $skuInfo->total_stock = $skuInfo->total_stock - $stock; + $skuInfo->surplus_stock = $skuInfo->surplus_stock - $stock; + + if ($skuInfo->total_stock <= 0 || $skuInfo->surplus_stock <= 0) throw new ErrException('库存不足'); + + if (!$skuInfo->save()) throw new ErrException('修改原 sku 库存失败'); + }); + + //删除缓存 + $this->goodCache->delCache($spuInfo->kitchen_id,$spuInfo->cycle_id); + return $this->return->success(); } + + /** + * @return array + */ + public function list(): array + { + $cycleId = (int)$this->request->input('cycle_id'); + $kitchenId = (int)$this->request->input('search_kitchen_id'); + $cityId = (int)$this->request->input('search_city_id'); + + $spuIds = $this->spuModel + ->where('cycle_id',$cycleId) + ->where('city_id',$cityId) + ->where('kitchen_id',$kitchenId) + ->where('is_del',GoodCode::SPU_IS_NO_DEL) + ->where('type',GoodCode::SPU_TYPE_OPTIONAL) + ->where('favorable',GoodCode::NOT_FAVORABLE) +// ->orderByDesc('id') + ->pluck('id') + ->toArray(); + + $skuList = $this->skuModel + ->whereIn('spu_id',$spuIds) + ->where('is_del',GoodCode::SKU_IS_NO_DEL) + ->orderBy('sort') + ->pluck('title','id') + ->toArray(); + + $favorableSpuId = $this->spuModel + ->where('cycle_id',$cycleId) + ->where('city_id',$cityId) + ->where('kitchen_id',$kitchenId) + ->where('is_del',GoodCode::SPU_IS_NO_DEL) + ->where('type',GoodCode::SPU_TYPE_OPTIONAL) + ->where('favorable',GoodCode::NOT_FAVORABLE) + ->value('id'); + + $favorableOriginSkuIds = $this->skuModel + ->where('spu_id',$favorableSpuId) + ->where('is_del',GoodCode::SKU_IS_NO_DEL) + ->pluck('origin_sku_id') + ->toArray(); + + if (empty($skuList)) return $this->return->success('success', ['list' => []]); + + $res = []; + foreach ($skuList as $sku => $title) { + $res[] = [ + 'id' => $sku, + 'title' => $title, + 'is_favorable' => (empty($favorableSpuId) || empty($favorableSpuId[$sku]) || !in_array($sku,$favorableOriginSkuIds)) ? GoodCode::NOT_FAVORABLE : GoodCode::IS_FAVORABLE, + ]; + } + + return $this->return->success('success', ['list' => $res]); + } } \ No newline at end of file diff --git a/app/Service/Admin/Good/SkuService.php b/app/Service/Admin/Good/SkuService.php index 5d08a24..9c20670 100644 --- a/app/Service/Admin/Good/SkuService.php +++ b/app/Service/Admin/Good/SkuService.php @@ -129,6 +129,8 @@ class SkuService extends BaseService $insertModel->is_add_staple_food = $this->request->input('is_add_staple_food'); $insertModel->code_number = $this->request->input('code_number'); $insertModel->sort = $this->request->input('sort'); + $insertModel->origin_sku_id = 0; + $insertModel->favorable = GoodCode::NOT_FAVORABLE; if (!$insertModel->save()) throw new ErrException('添加失败'); @@ -167,19 +169,38 @@ class SkuService extends BaseService $spuInfo = $this->spuModel->getInfoById($skuInfo->spu_id); if (empty($spuInfo)) throw new ErrException('数据出错'); + $originSkuInfo = null; + if ($skuInfo->favorable == GoodCode::IS_FAVORABLE) { + $originSkuInfo = $this->skuModel->find($skuInfo->origin_sku_id); + if (empty($originSkuInfo)) throw new ErrException('原sku数据不存在,无法修改'); + } + $stock = $this->request->input('stock'); $forceCleanStockCache = 0; + if ($skuInfo->order_num > 0) { //已产生订单 修改库存需要强制删除库存缓存 $forceCleanStockCache = 1; - + $originTotalStock = $skuInfo->total_stock; if ($skuInfo->total_stock < $stock) $skuInfo->total_stock = $stock; - if ($skuInfo->total_stock > $stock) { + else { $skuInfo->total_stock = $stock; if ($skuInfo->order_num >= $stock) throw new ErrException('库存不能小于已下单量'); } - } - $skuInfo->surplus_stock = $skuInfo->total_stock - $skuInfo->order_num; + if ($originSkuInfo && $skuInfo->total_stock > $originSkuInfo->total_stock) throw new ErrException('修改后的库存不能大于原商品库存'); + + $skuInfo->surplus_stock = $skuInfo->total_stock - $skuInfo->order_num; + if ($originSkuInfo) { + $originSkuInfo->total_stock = $originSkuInfo->total_stock - $originTotalStock + ($originTotalStock - $skuInfo->order_num); + $originSkuInfo->surplus_stock = $originSkuInfo->surplus_stock - $originTotalStock + ($originTotalStock - $skuInfo->order_num); + + if ($originSkuInfo->total_stock < 0 || $originSkuInfo->surplus_stock < 0) throw new ErrException('秒杀库存数据过多,原商品库存不足'); + } + + } else { + $skuInfo->total_stock = $stock; + $skuInfo->surplus_stock = $stock; + } if ($skuInfo->order_num > 0 && $skuInfo->price != $this->request->input('price')) throw new ErrException('已有订单不可改价,退单后即可操作'); else $skuInfo->price = $this->request->input('price'); @@ -199,7 +220,7 @@ class SkuService extends BaseService $skuInfo->sub_title = $this->request->input('sub_title'); $skuInfo->param = $this->request->input('param',''); $skuInfo->extra = $this->request->input('extra',''); - $skuInfo->total_stock = $this->request->input('stock'); +// $skuInfo->total_stock = $this->request->input('stock'); $skuInfo->saleable = $this->request->input('saleable'); $skuInfo->title = $this->request->input('title'); $skuInfo->sort = $this->request->input('sort'); diff --git a/app/Service/Admin/Good/SpuService.php b/app/Service/Admin/Good/SpuService.php index c328f50..ddf3895 100644 --- a/app/Service/Admin/Good/SpuService.php +++ b/app/Service/Admin/Good/SpuService.php @@ -71,7 +71,16 @@ class SpuService extends BaseService ->where('city_id',$cityId) ->where('kitchen_id',$kitchenId) ->where('is_del',GoodCode::SPU_IS_NO_DEL) - ->where('type',$this->request->input('type')) + ->when($this->request->input('type'), function ($query) { + $type = (int)$this->request->input('type'); +// $query->where('type',$type); + if ($type == GoodCode::SPU_TYPE_FAVORABLE) { + $query->where('favorable',GoodCode::IS_FAVORABLE)->where('type',GoodCode::SPU_TYPE_OPTIONAL); + } else { + $query->where('favorable',GoodCode::NOT_FAVORABLE)->where('type',$type); + } + }) +// ->where('type',$this->request->input('type')) ->paginate($limit) ->toArray(); @@ -156,6 +165,7 @@ class SpuService extends BaseService $insertModel->saleable = $this->request->input('saleable'); $insertModel->type = $this->request->input('type'); $insertModel->sort = $this->request->input('sort'); + $insertModel->favorable = GoodCode::NOT_FAVORABLE; if (!$insertModel->save()) throw new ErrException('添加菜品失败'); diff --git a/app/Service/Api/Evaluation/EvaluationService.php b/app/Service/Api/Evaluation/EvaluationService.php index c5f540f..d42a645 100644 --- a/app/Service/Api/Evaluation/EvaluationService.php +++ b/app/Service/Api/Evaluation/EvaluationService.php @@ -96,7 +96,7 @@ class EvaluationService extends BaseService $orderGoodInfo->is_comment = OrderCode::GOOD_COMMENT_FINISH; if (!$orderGoodInfo->save()) throw new ErrException('评论失败-002'); - //todo 厨师商品评分] + // 厨师商品评分] return $insertModel; }); diff --git a/app/Service/Api/Good/OptionalListService.php b/app/Service/Api/Good/OptionalListService.php index 9421c9b..252ce35 100644 --- a/app/Service/Api/Good/OptionalListService.php +++ b/app/Service/Api/Good/OptionalListService.php @@ -14,6 +14,7 @@ use App\Cache\Redis\Api\ApiRedisKey; use App\Cache\Redis\Api\GoodCache; use App\Cache\Redis\Api\SiteCache; use App\Cache\Redis\RedisCache; +use App\Constants\Common\GoodCode; use App\Constants\ConfigCode; use App\Exception\ErrException; use App\Model\Category; @@ -98,11 +99,17 @@ class OptionalListService extends BaseService $res = []; $stockKey = ApiRedisKey::goodStockKey($this->goodCache->cycleId, $this->goodCache->kitchenId); - foreach ($data as &$item) { + $favorable = []; + foreach ($data as $key => &$item) { foreach ($item['sku_list'] as &$v) { $v['surplus_stock'] = $this->redisCache->zScore($stockKey,$v['id']) ?? 0; } + if ($item['favorable'] == GoodCode::IS_FAVORABLE) { + unset($data[$key]); + $favorable = $item; + } + if (empty($res[$item['category_id']])) { $res[$item['category_id']] = [ 'category_name' => $categoryList[$item['category_id']]['name'] ?? '', @@ -122,6 +129,14 @@ class OptionalListService extends BaseService ]); } + if (!empty($favorable)) { + array_unshift($res,[ + 'category_name' => $this->configCache->getConfigValueByKey(ConfigCode::SPECIALS_CATEGORY_NAME), + 'category_image' => $this->configCache->getConfigValueByKey(ConfigCode::SPECIALS_CATEGORY_IMAGE), + 'spu_list' => $favorable + ]); + } + return array_values($res); } } \ No newline at end of file