// +---------------------------------------------------------------------- declare (strict_types=1); namespace app\store\model\groupon; use app\store\model\Goods as GoodsModel; use app\store\model\GoodsSpecRel as GoodsSpecRelModel; use app\store\model\groupon\GoodsSku as GoodsSkuModel; use app\common\model\groupon\Goods as GrouponGoodsModel; use app\common\enum\goods\SpecType as SpecTypeEnum; use app\common\enum\groupon\ActiveType as ActiveTypeEnum; use app\common\library\helper; use cores\exception\BaseException; /** * 拼团商品模型 * Class Goods * @package app\store\model\groupon */ class Goods extends GrouponGoodsModel { const EVENT_ADD = 'add'; const EVENT_EDIT = 'edit'; /** * 获取列表 * @param array $param * @return \think\Paginator * @throws \think\db\exception\DbException */ public function getList(array $param): \think\Paginator { // 设置基础查询条件 $query = $this->setBaseQuery($this->alias, [['goods', 'goods_id']]); // 检索查询条件 $filter = $this->getFilter($param); // 获取活动列表 $list = $query->where($filter) ->where("{$this->alias}.is_delete", '=', 0) ->order(["{$this->alias}.sort" => 'asc', "{$this->alias}.create_time" => 'desc']) ->paginate(15); // 设置商品数据 return !$list->isEmpty() ? $this->setGoodsListData($list, true) : $list; } /** * 检索查询条件 * @param array $param * @return array */ private function getFilter(array $param): array { // 设置默认查询参数 $params = $this->setQueryDefaultValue($param, [ 'search' => '', // 商品名称 'activeType' => 0, // 拼团类型 'status' => 0, // 拼单状态 ]); // 检索查询条件 $filter = []; !empty($params['search']) && $filter[] = ['goods.goods_name', 'like', "%{$params['search']}%"]; $params['activeType'] > 0 && $filter[] = ["{$this->alias}.active_type", '=', (int)$params['activeType']]; $params['status'] > 0 && $filter[] = ["{$this->alias}.status", '=', (int)$params['status']]; return $filter; } /** * 获取拼团商品详情 * @param int $grouponGoodsId 拼团商品ID * @return Goods|array|null * @throws BaseException * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function getDetail(int $grouponGoodsId) { // 获取商品记录 $goodsInfo = static::detail($grouponGoodsId, ['skuList']); empty($goodsInfo) && throwError('很抱歉,商品信息不存在'); // 商品多规格处理 if ($goodsInfo['spec_type'] == SpecTypeEnum::MULTI) { // 拼团商品SKU填充主商品参数(商品价格、库存数量、商品sku编码) $goodsInfo['skuList'] = GoodsSkuModel::getCommonSkuList($goodsInfo['skuList'], $goodsInfo['goods_id']); // 商品规格属性列表 $goodsInfo['specList'] = GoodsSpecRelModel::getSpecList($goodsInfo['goods_id']); } return $goodsInfo; } /** * 添加拼团商品 * @param array $data * @return bool * @throws BaseException * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function add(array $data): bool { // 验证主商品能否被添加为拼团商品 if (!$this->validateGoodsId((int)$data['goods_id'])) { return false; } // 获取主商品基本信息 $goodsInfo = (new GoodsModel)->getBasic((int)$data['goods_id']); // 记录商品ID、规格类型、拼团价格及库存 $data['goods_id'] = $goodsInfo['goods_id']; $data['spec_type'] = $goodsInfo['spec_type']; $data['groupon_price'] = $goodsInfo['goods_price_min']; // 默认的阶梯价格 if ($data['active_type'] == ActiveTypeEnum::STEPS) { $data['steps_price_config'] = array_map(function () use ($goodsInfo) { return $goodsInfo['goods_price_min']; }, $data['steps_config']); } // 创建拼团商品数据 $data = $this->createData($data, self::EVENT_ADD); // 事务处理 $this->transaction(function () use ($data) { // 添加商品 $this->save($data); // 更新商品sku信息 GoodsSkuModel::add((int)$this['groupon_goods_id'], $this['spec_type'], $data['newSkuList']); }); return true; } /** * 编辑商品 * @param array $data * @return bool * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function edit(array $data): bool { // 记录商品ID和规格类型 $data['active_type'] = $this['active_type']; $data['goods_id'] = $this['goods_id']; $data['spec_type'] = $this['spec_type']; // 创建拼团商品数据 $data = $this->createData($data, self::EVENT_EDIT); // 事务处理 $this->transaction(function () use ($data) { // 更新商品 $this->save($data); // 更新商品sku信息 GoodsSkuModel::edit((int)$this['groupon_goods_id'], $this['spec_type'], $data['newSkuList']); }); return true; } /** * 创建商品数据 * @param array $data * @param string $event * @return array * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ private function createData(array $data, string $event): array { // 默认数据 $data = array_merge([ 'newSkuList' => [], 'betweenTime' => [], 'store_id' => self::$storeId, ], $data); // 规格和sku数据处理 $data['newSkuList'] = $this->getNewSkuList($data, $event); // 是否为阶梯团 $isSteps = $data['active_type'] == ActiveTypeEnum::STEPS; // 商品价格 最低最高 if ($data['spec_type'] == SpecTypeEnum::MULTI) { [$data['groupon_price_min'], $data['groupon_price_max']] = GoodsSkuModel::getGoodsPrices($data['newSkuList'], $isSteps); } elseif ($data['spec_type'] == SpecTypeEnum::SINGLE) { // 阶梯价格 if ($isSteps) { $data['groupon_price_min'] = min($data['steps_price_config']); $data['groupon_price_max'] = max($data['steps_price_config']); } else { $data['groupon_price_min'] = $data['groupon_price_max'] = $data['groupon_price']; } } // 格式化活动时间 $times = between_time($data['betweenTime'], true); $data['start_time'] = $times['start_time']; $data['end_time'] = $times['end_time']; return $data; } /** * 生成新的SKU列表数据 * @param array $data * @param string $event * @return array * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ private function getNewSkuList(array $data, string $event = self::EVENT_ADD): array { if ($event === self::EVENT_ADD) { // 生成默认的skuList if ($data['spec_type'] == SpecTypeEnum::MULTI) { return GoodsSkuModel::getDefaultSkuList($data['goods_id']); } return helper::pick($data, ['groupon_price', 'steps_price_config']); } return $this->getNewSkuListByEdit($data, $event); } /** * 生成新的SKU列表数据(用于编辑事件) * @param array $data * @param string $event * @return array * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ private function getNewSkuListByEdit(array $data, string $event = self::EVENT_ADD): array { // 规格和sku数据处理 if ($data['spec_type'] == SpecTypeEnum::MULTI) { // 生成skuList ( 携带goods_sku_id ) return GoodsSkuModel::getNewSkuList($data['goods_id'], $data['specData']['skuList']); } elseif ($data['spec_type'] == SpecTypeEnum::SINGLE) { // 生成skuItem return helper::pick($data, ['groupon_price', 'steps_price_config']); } return []; } /** * 验证主商品能否被添加为拼团商品 * @param int $goodsId 主商品ID * @return bool */ private function validateGoodsId(int $goodsId): bool { if (empty($goodsId)) { $this->error = '很抱歉,您还没有选择商品'; return false; } // 验证是否存在拼团商品 if ($this->isExistGoodsId($goodsId)) { $this->error = '很抱歉,该商品已存在,无需重复添加'; return false; } return true; } /** * 验证指定商品是否已添加拼团商品 * @param int $goodsId 主商品ID * @return bool */ public static function isExistGoodsId(int $goodsId): bool { return (bool)(new static)->where('goods_id', '=', $goodsId) ->where('is_delete', '=', 0) ->value('groupon_goods_id'); } /** * 软删除 * @return mixed */ public function setDelete() { return $this->transaction(function () { // 删除所有的sku记录 GoodsSkuModel::deleteAll(['groupon_goods_id' => $this['groupon_goods_id']]); // 标记当前拼团商品已删除 return $this->save(['is_delete' => 1]); }); } }