setting = Setting::getImportSetting($this->mall_id); } /** * 添加商品 * * @param string $spu_id * @return boolean|MallGoods */ public function addGoods($spu_id) { try { // spu详情 $spu_info = $this->api->getSpuBySpuIds([$spu_id]); // sku详情 $sku_list_detail = $this->api->listSkuBySpuId($spu_id); } catch (Exception $e) { throw new Exception("API接口获取商品失败:" . $e->getMessage()); // return $this->error("API接口获取商品失败:" . $e->getMessage()); } // 设置当前供应链商品ID $this->spu_id = $spu_id; try { // 是否更新 if ($goods_id = Storage::find()->where(['mall_id' => $this->mall_id, 'is_delete' => 0, 'spu_id' => $spu_id])->select('mall_goods_id')->scalar()) { $this->goods_id = $goods_id; $this->is_update = true; } // 获取商品属性 $goods_attr = $this->getGoodsAttr($spu_info[0], $sku_list_detail); // 获取规格组 $attr_groups = $this->getAttrGroups($sku_list_detail); // $attr_groups = $this->removeAttrGroups($attr_groups, $goods_attr['attr']); // 匹配规格ID $goods_attr = $this->matchingAttrId($goods_attr, $attr_groups); $goods_attr['attr_groups'] = $attr_groups; // 保存商品 $res = MallGoods::saveGoods($goods_attr); if ($res === false) { throw new Exception('商品添加到商城失败'); } } catch (Exception $e) { throw new Exception($e->getMessage()); // return $this->error($e->getMessage()); } return $res; } /** * 下架商品 * * @param array $spu_ids * @return void */ public function goodsPulled($spu_ids) { $storage_list = Storage::find()->where(['spu_id' => $spu_ids])->with('goods')->all(); try { foreach ($storage_list as $storage) { $storage->goods->goodsPulled(); // 下架 MallGoods::setData([ 'id' => $storage->mall_goods_id, 'mall_id' => $storage->mall_id, 'is_on_sale' => 0, ]); } } catch (Exception $e) { throw new Exception($e->getMessage()); } } /** * 添加商品 * * @param string $spu_id * @return boolean|MallGoods */ public function editGoods($spu_id) { // 是否更新 $goods_id = Storage::getMallGoodsIdBySpuId($this->mall_id, $spu_id); if (empty($goods_id)) { return false; } $this->goods_id = $goods_id; $this->is_update = true; try { // spu详情 $spu_info = $this->api->getSpuBySpuIds([$spu_id]); // sku详情 $sku_list_detail = $this->api->listSkuBySpuId($spu_id); } catch (Exception $e) { throw new Exception("API接口获取商品失败:" . $e->getMessage()); } // 设置当前供应链商品ID $this->spu_id = $spu_id; try { // 获取商品属性 $goods_attr = $this->getGoodsAttr($spu_info[0], $sku_list_detail); // 获取规格组 $attr_groups = $this->getAttrGroups($sku_list_detail); // $attr_groups = $this->removeAttrGroups($attr_groups, $goods_attr['attr']); // 匹配规格ID $goods_attr = $this->matchingAttrId($goods_attr, $attr_groups); $goods_attr['attr_groups'] = $attr_groups; // 保存商品 $res = MallGoods::saveGoods($goods_attr); if ($res === false) { throw new Exception('商品添加到商城失败'); } } catch (Exception $e) { throw new Exception($e->getMessage()); } return $res; } /** * 获取添加商品属性 * * @param array $goods_info * @return array */ private function getGoodsAttr($goods_info, $sku_list_detail) { // 获取匹配的Attr $specs_attr = $this->getSpecsForAttr($sku_list_detail, $goods_info['status']); $is_attr = count($specs_attr) > 1 ? 1 : 0; $stock = $this->getStock($specs_attr); $attr = [ 'attr' => $specs_attr, // 商品规格属性 'bannar_pic' => $this->getBannarPic($goods_info['carouselImgList']), 'cover_pic' => $goods_info['carouselImgList'][0], // 主图 'price' => $this->price['sell'], // 销售价 'original_price' => $this->price['original'], // 原价 'cost_price' => $this->price['cost'], // 成本价 'detail' => $this->getDetailImg($goods_info['detailImgList']), // 商品详情 'stock' => $stock > $this->max_stock_num ? $this->max_stock_num : $stock, // 总库存 'goods_name' => $goods_info['name'], // 商品名称 'goods_source' => $this->goods_source, 'is_attr' => $is_attr, 'goods_no' => '', ]; // 商品规格为空 不添加 if (empty($attr['attr'])) { throw new Exception("可售规格均已下架, 不能导入"); } // 当商品为上架时,还需要判断库存是否支持上架 if ($goods_info['status'] == GoodsStatusEnum::STATUS_0) { $goods_info['status'] = $this->goods_status ? 0 : 1; } // 上下架设置 $attr['is_on_sale'] = $goods_info['status'] == GoodsStatusEnum::STATUS_0 ? 1 : 0; if ($this->is_update) { // 当商品上架时 不需要改变系统商品状态1 if ($goods_info['status'] == 1) { unset($goods_info['status']); } $detail = MallGoods::getDetail($this->goods_id); return $this->mergeDetail($detail, $attr); } else { // 获取分类 仅新增时添加分类 $mall_cate_service = new MallCateService(['mall_id' => $this->mall_id]); $cats = $mall_cate_service->getCats( $goods_info['categoryId1'], $goods_info['categoryId2'], $goods_info['categoryId3'] ); return array_merge($attr, [ 'goods_type' => 1, // 默认1 'subtitle' => '', // 'cats' => [$cats], // 分类 'labels' => [], // 商品标签 'mchCats' => [], // 多商户分类 'services' => [], // 商品服务 'unit' => '', // 单位 'virtual_sales' => 0, // 虚拟销量 'stock_warning' => 0, 'goods_weight' => 0, // 商品权重 'goods_no' => '', // 商品货号 'is_show_stock' => 1, 'is_show_sales' => 0, // 是否显示销量 'freight_type' => [], 'freight_rules_type' => 1, 'freight_id' => '', 'shipping_fee' => 0, 'free_shipping_num' => 0, 'free_shipping_money' => 0, 'is_cross_border' => 0, 'is_id_card' => 0, 'extra' => '', // 额外属性 'coupon_selection' => [], 'goods_setting' => [], 'is_area_limit' => 0, 'area_limit' => [], 'attr_groups' => [], 'mch_id' => 0, 'mall_id' => $this->mall_id, ]); } } /** * 获取商品规格属性 * * @param array $specs * @return array */ private function getSpecsForAttr($sku_list, $status) { if (empty($sku_list)) { throw new Exception(''); } $attr = []; foreach ($sku_list as $sku) { // 仅需要上架的 if ($sku['status'] == SkuStatusEnum::STATUS_0 || $status == SkuStatusEnum::STATUS_1) { $temp = [ 'attr_list' => $this->getAttrList($sku['skuPropertyList']), // 规格 'stock' => $sku['stock'] > $this->max_stock_num ? $this->max_stock_num : $sku['stock'], // 库存 'price' => $this->getPrice($sku, 'sell'), // 价格 'original_price' => $this->getPrice($sku, 'original'), // 价格 'cost_price' => $this->getPrice($sku, 'cost'), // 价格 'goods_no' => '', 'weight' => 0, 'pic_url' => $sku['skuPicUrl'], 'distributionLevelList' => [], 'member_price' => [], 'levelPrice' => [], 'sku_id' => $sku['skuId'], 'chain_goods_id' => $this->spu_id, ]; // 如果是更新 if ($this->is_update) { $params = [ 'sku_id' => $temp['sku_id'], 'mall_id' => $this->mall_id, 'mall_goods_id' => $this->goods_id, ]; $sku_model = GoodsAttr::find()->where($params)->select('attr_id')->one(); if ($sku_model) { $temp['id'] = $sku_model->attr_id; } } // 如果库存大于0 可以上架 if ($sku['stock'] > 0) { $this->goods_status = true; } $attr[] = $temp; } } // 剔除没有规格的商品 foreach ($attr as $k => $v) { if (empty($v['attr_list'])) { unset($attr[$k]); } } return $attr; } /** * 获取规格属性 * * @param array $skus * @return array */ private function getAttrGroups($skus) { $first_key = array_key_first($skus); $sku_property_list = $skus[$first_key]['skuPropertyList']; $attr_groups = []; $attr_group_id = 1; foreach ($sku_property_list as $option) { $attr_groups[] = [ 'attr_group_id' => $attr_group_id, 'attr_group_name' => $option['specName'], ]; $attr_group_id++; } $temp = 0; $attr_name = []; $attr_id = 1; foreach ($skus as $sku) { if ($sku['skuPropertyList']) { foreach ($attr_groups as $k => $group) { foreach ($sku['skuPropertyList'] as $option) { if ( $option['specName'] == $group['attr_group_name'] && !in_array($option['specValueName'], $attr_name) ) { $attr_name[] = $option['specValueName']; $attr_groups[$k]['attr_list'][] = [ 'attr_id' => $attr_id, 'attr_name' => $option['specValueName'], // 图片仅第一个添加 'pic_url' => $sku['skuPicUrl'], ]; $attr_id++; } } $temp++; } } } $attr_id = 0; return array_map(function ($item) use (&$attr_id) { return array_merge($item, ['attr_list' => array_map(function ($attr) use (&$attr_id) { $attr_id++; return array_merge($attr, [ 'attr_id' => $attr_id, ]); }, $item['attr_list'])]); }, $attr_groups); } /** * 匹配规格ID * * @param array $goods_attr * @param array $attr_groups * @return array */ private function matchingAttrId($goods_attr, $attr_groups) { foreach ($goods_attr['attr'] as $k => $sku) { $sign = []; foreach ($sku['attr_list'] as $k1 => $attr) { $attr_group_id = $this->getAttrGroupId($attr_groups, $attr['attr_group_name']); $attr_id = $this->getAttrId($attr_groups, $attr['attr_name']); $sign[] = $attr_id; $goods_attr['attr'][$k]['attr_list'][$k1]['attr_id'] = $attr_id; $goods_attr['attr'][$k]['attr_list'][$k1]['attr_group_id'] = $attr_group_id; } // 拼接sign_id // asort($sign); count($sign) > 1 && $goods_attr['attr'][$k]['sign_id'] = implode(':', $sign); } return $goods_attr; } /** * 获取规格属性ID * * @param array $attr_groups 规格组 * @param string $name 规格名称 * @return integer|null */ private function getAttrId($attr_groups, $name) { foreach ($attr_groups as $group) { foreach ($group['attr_list'] as $attr) { if ($attr['attr_name'] == $name) { return $attr['attr_id']; } } } } /** * 获取规格属性组ID * * @param array $attr_groups 规格组 * @param string $name 属性组名称 * @return integer|null */ public function getAttrGroupId($attr_groups, $name) { foreach ($attr_groups as $group) { if ($group['attr_group_name'] == $name) { return $group['attr_group_id']; } } } /** * 获取商品规格属性 * * @param array $options * [ * [ * 'spec_name' => '颜色' * 'spec_item_name' => '纯白' * ] * [ * 'spec_name' => '尺码' * 'spec_item_name' => '39' * ] * ] * @return array */ private function getAttrList($list) { $attr = []; foreach ($list as $option) { !empty($option['specName']) && !empty($option['specValueName']) && $attr[] = [ 'attr_group_name' => $option['specName'], 'attr_name' => $option['specValueName'], ]; } return $attr; } /** * 获取商品轮播图 * * @param array $gallery * @return array */ private function getBannarPic($list) { $pic = []; foreach ($list as $v) { $pic[] = [ 'id' => 0, 'pic_url' => $v, ]; } return $pic; } /** * 获取库存 * * @param array $attr * @return integer */ private function getStock($attr) { $stock = 0; foreach ($attr as $v) { $stock = bcadd($stock, $v['stock']); } return $stock; } /** * 融合属性详情 * * @param array $detail * @param array $attr * @return array */ private function mergeDetail($detail, $attr) { // 全局设置 $setting = $this->setting; // 更新价格 自动更新为1 不更新为0 不更新的时候进入方法进行价格删除 if (!$setting['auto_present_price']) { // 删除更新获取回来的价格 unset($attr['price']); unset($attr['original_price']); unset($attr['cost_price']); unset($attr['stock']); // 查询旧属性,重组获取旧价格 $old_attr = []; // 查询所有循环重组 减少sql查询 $model = GoodsAttr::find(); $sku_id_list = $model->select('attr_id, sku_id')->where([ 'mall_goods_id' => $detail['id'], 'is_delete' => 0, ])->asArray()->indexBy('attr_id')->all(); foreach ($detail['attr'] as $k => $v) { // 按sku_id重组旧规格 if (isset($sku_id_list[$v['id']])) { $sku_id = $sku_id_list[$v['id']]['sku_id']; $old_attr[$sku_id] = $v; } } // 旧价格写入新属性 foreach ($attr['attr'] as $k => $v) { // 旧属性存在 if (isset($old_attr[$v['sku_id']])) { // 替换新属性价格为旧属性价格 $temp = $old_attr[$v['sku_id']]; $attr['attr'][$k]['price'] = $temp['price']; $attr['attr'][$k]['original_price'] = $temp['original_price']; $attr['attr'][$k]['cost_price'] = $temp['cost_price']; } } } // 更新属性 自动更新为1 不更新为0 不更新的时候进入方法进行价格删除 if (!$setting['auto_base_info']) { unset($attr['detail']); unset($attr['name']); unset($attr['goods_num']); } return array_merge($detail, $attr); } /** * 获取详情 * * @param array $imgs * @return string */ private function getDetailImg($imgs) { $str = ''; foreach ($imgs as $v) { $str .= '

'; } return $str; } /** * 获取价格 * * @param array $info * @param array $type * @return float */ private function getPrice($info, $type) { $setting = $this->setting; $price_field = $setting[$type . '_name']; $price_value = $setting[$type . '_value']; if (empty($price_field) || empty($price_value)) { throw new Exception('自动设置价格字段有误'); } $price = $info[$price_field]; if (empty($price)) { throw new Exception('自动设置价格不存在'); } $last_price = bcdiv(bcmul($price, $price_value, 2), 100, 2); // 商品详情不存在价格 存储规格中对应最低价格作为商品详情的价格 empty($this->price[$type]) ? $this->price[$type] = $last_price : ($last_price > $this->price[$type] ?: $this->price[$type] = $last_price); return $last_price; } }