255], [['check_remark'], 'safe'], [['stock'], 'integer', 'max' => 99999999, 'message' => '库存最大数为99999999'], [['subtitle', 'unit'], 'safe'], [['cover_pic', 'freight_type', 'video_url', 'services', 'labels', 'goods_no'], 'string', 'max' => 255], [['video_cover_pic'], 'string', 'max' => 500], [['bannar_pic'], 'string', 'max' => 1500000], ]; } /** * {@inheritdoc} */ public function attributeLabels() { return [ 'id' => 'ID', 'mall_id' => '商城id', 'mch_id' => '商家id', 'goods_name' => '商品名称', 'subtitle' => '商品副标题', 'price' => '售价', 'original_price' => '原价(划线价仅展示)', 'cost_price' => '成本价', 'unit' => '单位', 'cover_pic' => '商品缩略图', 'bannar_pic' => '商品展示bannar图', 'is_on_sale' => '上架状态【1是 0否】', 'is_attr' => '是否有规格【1是 0否】', 'attr_groups' => '规格组', 'attr_groups_format' => '格式化后的规格组', 'status' => '状态[1正常 -1删除]', 'stock' => '商品库存', 'stock_warning' => '商品库存预警值', 'is_show_stock' => '是否显示库存', 'is_show_sales' => '是否显示销量【1是 0否】', 'virtual_sales' => '虚拟销量', 'sales_num' => '累计销量', 'buy_num_limit' => '购买数量限制', 'freight_type' => '物流方式【1快递发货 2上门自提】逗号分隔', 'freight_rules_type' => '运费规则 【1运费模板 2自定义运费】', 'freight_id' => '运费模板ID', 'shipping_fee' => '自定义运费金额', 'free_shipping_num' => '商品满件包邮', 'free_shipping_money' => '商品满额包邮', 'goods_type' => '商品类型', 'detail' => '商品详情,图文', 'is_area_limit' => '是否开启区域限制', 'area_limit' => '允许购买区域', 'is_pay_limit'=>'是否开启支付限制', 'pay_limit'=>'限制的支付方式', 'video_url' => '商品视频', 'video_cover_pic' => '商品视频封面', 'services' => '商品服务', 'labels' => 'Labels', 'goods_source' => '商品来源', 'sort' => '排序', 'created_at' => '创建时间', 'updated_at' => '修改时间', 'check_status' => '审核状态', 'check_remark' => '审核备注', 'goods_no' => '货号', 'is_show' => '是否在主商城显示', 'goods_subtype' => '商品子类型 0普通商品 1药品商品', ]; } /**关联模型 */ // 分类关系 public function getGoodsCateRelate() { return $this->hasMany(GoodsCateRelate::class, ['goods_id' => 'id']); } // 分类 public function getCats() { return $this->hasMany(GoodsCate::class, ['id' => 'cate_id']) // ->where(['mch_id' => 0]) ->via('goodsCateRelate'); } // 预约商品信息 public function getReserve() { return $this->hasOne(GoodsReserve::class, ['goods_id' => 'id']); } // sku public function getAttr() { return $this->hasMany(GoodsAttr::class, ['goods_id' => 'id'])->andWhere(['status' => [StatusEnum::ENABLED]]); } // 商品额外设置 public function getExtra() { return $this->hasOne(GoodsExtra::class, ['goods_id' => 'id'])->andWhere(['status' => [StatusEnum::ENABLED]]); } public function getCollect() { return $this->hasOne(GoodsCollect::class, ['goods_id' => 'id'])->andWhere(['status' => [StatusEnum::ENABLED]]); } public function getSearchAddress() { return $this->hasOne(GoodsSearchAddress::class, ['goods_id' => 'id']); } public function getMch() { return $this->hasOne(\addons\Mch\common\models\Mch::class, ['id' => 'mch_id'])->select('id,store_name,shop_mobile,logo_img,user_id'); } /** * 畅捷通请求 * * @return \yii\db\ActiveQuery */ public function getAddonsChanjetRequest() { return $this ->hasOne(AddonsChanjetRequest::class, ['table_id' => 'id']) ->orderBy('updated_at desc') ->select('id, table_id, request_status, updated_at') ->where([ 'table' => self::tableName(), 'path' => [Request::PATHS['INVENTORY_CREATE_BATCH'], Request::PATHS['INVENTORY_UPDATE_BATCH']] ]) ->andWhere(['>', 'request_status', 0]); } /** * 保存数据 * @Author bing * @DateTime 2021-08-24 15:34:48 * @param array $params * @param string $addons 来自插件 * @param callback $call_back 插件回调函数 * @return object|boolean * @copyright: Copyright (c) 2020 广东七件事集团 */ public static function setData(array $params) { try { $wait_del_attr_id_arr = []; if (!empty($params['id'])) { $model = self::findOne(['mall_id' => $params['mall_id'], 'id' => $params['id'], 'status' => [StatusEnum::ENABLED]]); if (empty($model)) throw new Exception('商品不存在或已删除'); if ($model['is_on_sale'] != $params['is_on_sale']) $data['is_on_sale'] = $params['is_on_sale']; } else { $model = new self(); $model->loadDefaultValues(); if (isset($params['is_on_sale']) && $params['is_on_sale'] == 1) $data['is_on_sale'] = $params['is_on_sale']; } $params['can_feedback'] = (int) ($params['can_feedback'] ?? StatusEnum::ENABLED); isset($params['services']) && $params['services'] = implode(',', $params['services']); isset($params['labels']) && $params['labels'] = implode(',', $params['labels']); isset($params['freight_type']) && $params['freight_type'] = implode(',', $params['freight_type']); isset($params['freight_id']) && empty($params['freight_id']) && $params['freight_id'] = 0; isset($params['virtual_sales']) && empty($params['virtual_sales']) && $params['virtual_sales'] = 0; if (isset($params['is_attr']) && $params['is_attr'] == 1) { if (isset($params['attr_groups']) && !empty($params['attr_groups'])) { $attr_groups = $params['attr_groups']; $params['attr_groups'] = json_encode($params['attr_groups'], JSON_UNESCAPED_UNICODE); $params['attr_groups_format'] = json_encode(self::formatGoodsAttrGroup($attr_groups, JSON_UNESCAPED_UNICODE)); } } else { $params['attr_groups'] = ''; $params['attr_groups_format'] = ''; } isset($params['bannar_pic']) && $params['bannar_pic'] = json_encode($params['bannar_pic'], JSON_UNESCAPED_UNICODE); isset($params['area_limit']) && $params['area_limit'] = json_encode($params['area_limit'], JSON_UNESCAPED_UNICODE); if (!empty($params['is_area_limit']) && !empty($params['area_limit']) && strlen($params['area_limit']) > 5000) { // throw new \Exception("地区所有字节数总和超过5000字了"); } isset($params['pay_limit']) && $params['pay_limit'] = json_encode($params['pay_limit'], JSON_UNESCAPED_UNICODE); $trans = Yii::$app->db->beginTransaction(); // 分类判断当条件不满足时不导入商品 if (isset($params['cats']) && !empty($params['cats'])) { $params['cats'] = self::goodsCategorizeValidate($params); } if (!$model->load($params, '') || !$model->save()) { //添加商品统计 if (empty($params['id'])) { Yii::$app->services->statistics->global->set($params['mall_id'], ['goods_num' => 1]); } throw new Exception($model->getErrorMessage()); } //商品分类处理 if (isset($params['cats']) && !empty($params['cats'])) { $res = GoodsCateRelate::setData($model->id, $params['cats']); if ($res === false) throw new Exception('分类处理失败:' . GoodsCateRelate::getStaticError()); } if (isset($params['goods_template_id']) && !empty($params['goods_template_id'])) { $res = GoodsTemplateRelation::setData(['mall_id' => $params['mall_id'], 'template_id' => $params['goods_template_id'], 'goods_id' => $model->id, 'status' => StatusEnum::ENABLED]); if ($res === false) throw new Exception('广告模板处理失败:' . GoodsTemplateRelation::getStaticError()); } $goods = ArrayHelper::toArray($model); if ($goods['goods_type'] === GoodsTypeEnum::GoodsTypeReserved) { // 预约商品 $reserve = $params['reserve']; $res = GoodsReserve::setData($goods, $reserve); if ($res === false) throw new Exception('预约商品SKU处理失败:' . GoodsAttr::getStaticError()); } else { // 商品规格处理 if ($model->is_attr == 1) { $attrs = $params['attr'] ?? []; $res = GoodsAttr::setData($model->id, $attrs, $attr_groups, $wait_del_attr_id_arr); if ($res === false) throw new Exception('规格处理失败:' . GoodsAttr::getStaticError()); } else { //无规格商品处理 $goods['pic_url'] = $goods['cover_pic']; $goods['goods_no'] = isset($params['goods_no']) ? $params['goods_no'] : ''; $goods['weight'] = $params['goods_weight'] ?? 0; $res = GoodsAttr::setAttr($model->id, $goods); if ($res === false) throw new Exception('设置货品失败:' . GoodsAttr::getStaticError()); } } // 商品额外信息处理 if (isset($params['extra']) && !empty($params['extra'])) { //检测商品限购设置 $member_buy_limit_setting = $params['extra']['member_buy_limit_setting'] ?? []; if ($member_buy_limit_setting) { if ($member_buy_limit_setting['nums'] > 0 && $member_buy_limit_setting['every_num'] > 0 && $member_buy_limit_setting['nums'] >= $member_buy_limit_setting['every_num']) { throw new Exception('商品额外信息每次限购数量需大于起购数量'); } } $params['extra']['mall_id'] = $params['mall_id']; $res = GoodsExtra::setData($model->id, $params['extra']); if ($res === false) throw new Exception('商品额外信息处理失败:' . GoodsExtra::getStaticError()); } // 营销插件配置保存 if (!empty($params['addons'])) { GlobalInvoke::exec(GlobalInvoke::GOODS_DETAIL_EDIT, $params['mall_id'], [ 'type' => 'save', 'mall_id' => $params['mall_id'], 'goods_id' => $model->id, 'setting' => $params['addons'], ]); // $res = CouponGiveItemSetting::setGoodsSetting($params['mall_id'], $model->id, $params['coupon_selection']); // if ($res === false) throw new Exception('商品优惠券处理失败:' . CouponGiveItemSetting::getStaticError()); } // 商品营销+用户设置处理 // if (isset($params['goods_setting']) && !empty($params['goods_setting'])) { // $goodsId = $model->id ?? 0; // $mchId = $model->mch_id ?? 0; // $res = GoodsExtra::setData($params['goods_setting'], $params['mall_id'], $mchId, $goodsId); // if ($res === false) throw new Exception('营销/用户处理失败:' . GoodsExtra::getStaticError()); // } if(!empty($params['searchAddress'])){ $address_search = array_merge($params['searchAddress'], ['goods_id' => $model->id, 'mall_id' => $params['mall_id']]); if(GoodsSearchAddress::setData($address_search) === false) throw new Exception(GoodsSearchAddress::getStaticError()); } $res = GoodsAssociation::setData($model->id, $params); $trans->commit(); //编辑商品触发 $event = new GoodsEditEvent($params['mall_id']); $data['goods_id'] = $model->id; $data['mall_id'] = $params['mall_id']; $data['wait_del_attr_id_arr'] = $wait_del_attr_id_arr; $data['copy_id'] = $params['copy_id']; Yii::$app->services->events->dispatch($event, $data, $event->listeners); return $model; } catch (Exception $e) { if (isset($trans)) $trans->rollback(); self::$static_error = $e->getMessage(); return false; } } /** * 商品分类过滤验证 * @param array $params * @return array * @throws Exception */ public static function goodsCategorizeValidate(array $params): array { // 获取商品分类ID合集 $caseIds = GoodsCate::find()->where(['mall_id' => $params['mall_id'], 'status' => StatusEnum::ENABLED]) ->select(['id'])->asArray()->all(); $caseIds = array_column($caseIds, "id"); // 判断输入ID是否是数字 $is_numeric = array_filter($params['cats'], function ($val) { return !is_numeric($val); }); if (!empty($is_numeric)) throw new Exception('商品分类必须为数字,不能包含其它字符'); // 判断输入ID 是否在商品分类ID中 获取符合的ID $caseIds = array_filter($params['cats'], function ($val) use ($caseIds) { return in_array($val, $caseIds); }); if (empty($caseIds)) throw new Exception('商品分类不存在或被删除'); return $caseIds; } /** * 格式化商品规格组数据 * @Author bing * @DateTime 2021-09-03 11:06:31 * @param array $attr_group 规格组 * @return array * @copyright: Copyright (c) 2020 广东七件事集团 */ public static function formatGoodsAttrGroup(array $attr_group) { $format_attr_group = []; $group_attr_ids = []; $all_attr_groups = []; $group_attr_list = array_column($attr_group, 'attr_list', 'attr_id'); //按规格项生成全部规格组 foreach ($group_attr_list as $key => $group_attrs) { array_push($group_attr_ids, array_column($group_attrs, 'attr_id')); $attr_group_id = $attr_group[$key]['attr_group_id']; $attr_group_name = $attr_group[$key]['attr_group_name']; foreach ($group_attrs as $k => &$group_attr) { $group_attr['attr_group_id'] = $attr_group_id; $group_attr['attr_group_name'] = $attr_group_name; } $all_attr_groups = array_merge($all_attr_groups, $group_attrs); } $all_attr_groups = array_column($all_attr_groups, null, 'attr_id'); // 规格组之间的笛卡尔集组合 $attr_dika = ArrayHelper::combineDika(array_values($group_attr_ids)); // 拼装以规格id列表为key的规格组格式,格式为attr_id1:attr_id2 => [attr_id1的规格组信息, attr_id的规格组信息] foreach ($attr_dika as $key => $attr_id_arr) { asort($attr_id_arr); $sign_id = implode(':', $attr_id_arr); $format_attr_group[$sign_id] = array_map(function ($id) use ($all_attr_groups) { return $all_attr_groups[$id]; }, $attr_id_arr); } return $format_attr_group; } /** * 商品详情 * @param $params * @return mixed|void */ public static function getGoodsDetail($params) { $goods = Goods::getOne($params['where'], $params['is_array'], $params['with'], $params['order'], $params['select']); if (empty($goods)) return $goods; $goods['is_member_price'] = '0'; $goods['price_type'] = '新品'; $goods['sales_num'] += $goods['virtual_sales']; $sku_arr = $attr_name_arr = []; unset($goods['virtual_sales']); $goods_services_ids = explode(',', $goods['services']); $service_list = GoodsService::findAll([ 'mall_id' => $params['mall_id'], 'id' => $goods_services_ids, 'status' => [StatusEnum::ENABLED, StatusEnum::DISABLED] ]); $service_arr = []; foreach ($service_list as $v) { $arr = explode('|', $v['name']); array_push($service_arr, ...$arr); } $goods['service_list'] = $service_arr; return $goods; } //商品导出表头标题 public static function fieldsList($field = null) { $fields = [ 'id' => '商品ID', 'goods_name' => '商品名', 'price' => '售价', 'cost_price' => '成本价', 'goods_no' => '商品货号', 'original_price' => '划线价', 'sales_num' => '销量', 'virtual_sales' => '虚拟销量', 'is_on_sale' => '状态', 'created_at' => '商品添加时间', 'unit' => '商品单位', 'stock' => '库存', 'cats' => '商品分类', 'attr_groups' => '规格', ]; if ($field === null) return $fields; $temp = []; foreach ($field as $val) { if (isset($fields[$val])) $temp[$val] = $fields[$val]; } return $temp; } //商品导出整理数据 public static function exportHandle(array $data) { ini_set('memory_limit','512M'); $download_id = $data['download_id'] ?? 0; $download = Download::findOne(['id' => $download_id]); if ($download) { try { $params = json_decode($download->params, true); $filename = $download->name; $type = $download->type; $goods_detail_model = Goods::find(); $goods_detail_model->where(['mall_id' => $params['mall_id']]); $goods_detail_model->andWhere(['>', 'status', StatusEnum::DISABLED]); $goods_detail_model->andWhere( [ 'or', ['!=', 'g.goods_source', 'Aiyunuo'], ['is', 'g.goods_source', new \yii\db\Expression('null')] ] ); !empty($params['start']) && $goods_detail_model->andWhere(['>=', 'g.created_at', strtotime($params['start'])]); !empty($params['end']) && $goods_detail_model->andWhere(['<=', 'g.created_at', strtotime($params['end'])]); !empty($params['goods_name']) && $goods_detail_model->andWhere(['like', 'g.goods_name', '%' . trim($params['goods_name']) . '%', false]); // !empty($params['cats']) && $goods_detail_model->andWhere(['in', 'gcr.cate_id', $params['cats']]); if(!empty($params['cats'])){ $goods_cate_relate_list = GoodsCateRelate::lists(['where'=>[['cate_id'=>$params['cats']]]]); $goods_ids = array_column($goods_cate_relate_list,'goods_id'); $goods_detail_model->andWhere(['in', 'g.id', $goods_ids]); } !empty($params['goods_id']) && $goods_detail_model->andWhere(['=', 'g.id', $params['goods_id']]); !empty($params['choose_list']) && $goods_detail_model->andWhere(['in', 'g.id', $params['choose_list']]); !empty($params['goods_type']) && $goods_detail_model->andWhere(['=', 'g.goods_type', $params['goods_type']]); if (!empty($params['type'])) { switch ($params['type']) { case 'onsale': $goods_detail_model->andWhere(['=', 'g.is_on_sale', WhetherEnum::ENABLED]); break; case 'offline': $goods_detail_model->andWhere(['=', 'g.is_on_sale', WhetherEnum::DISABLED]); break; case 'sell-out': $goods_detail_model->andWhere(['=', 'g.stock', 0]); break; case 'stock-lack': $goods_detail_model->andWhere(new Expression('g.stock <= g.stock_warning')); break; } } //连表 // $goods_detail_model->join('LEFT JOIN', '{{%goods_cate_relate}} gcr', 'gcr.goods_id=g.id'); $goods_detail_model->alias('g'); $goods_detail_model->with(['cats']); $goods_detail_model->orderBy('g.id desc'); $fields = $params['fields']; $fields_arr = self::fieldsList(); //var_dump($fields); $batchSize = 5000; // 设置订单批量导出数量 $i = 0; //循环次数 $goodsCount = $goods_detail_model->count(); // 查询商品总条数 $is_goods_page = $goodsCount > $batchSize; // 判断是否需要分页 foreach ($goods_detail_model->asArray()->batch($batchSize) as $goods_details) { $goods_groups_max = 0; $goods_collective_list = []; foreach ($goods_details as $goods_detail) { $processed_goods_detail = self::processGoodsDetail($goods_detail); $goods_collective_list[] = $processed_goods_detail; $goods_groups_max = max($goods_groups_max, $processed_goods_detail['goods_group_num']); } // 处理商品规格 $goods_export_list = []; foreach ($goods_collective_list as $goods_detail) { $goods_item = []; foreach ($fields as $field) { if ($field == 'attr_groups') { // 以最大的规格数量为标准,不足的规格数量用空格补齐 foreach (range(1, $goods_groups_max) as $index) { $goods_item[] = $goods_detail['attr_groups'][$index - 1] ?? ''; } } else { $goods_item[] = $goods_detail[$field] ?? ''; } } $goods_export_list[] = $goods_item; } if (!empty($goods_export_list)) { $csv = new CsvTool(); $csv->filename = $is_goods_page ? $filename . "_1" : $filename;; $csv->file_dirname = DownloadEnum::getTypeStorageDirMap($type); $csv->export_mode = CsvTool::EXPORT_MODE_ASYNC; $have_select_field_arr = []; foreach ($fields as $value) { if ($value == 'attr_groups' && $goods_groups_max > 0) { foreach (range(1, $goods_groups_max) as $index) { $have_select_field_arr[] = '规格' . $index; } } else { $have_select_field_arr[] = $fields_arr[$value]; } } $csv->header = $have_select_field_arr; $csv->data = $goods_export_list; if ($is_goods_page && $i == 0) { // 因为订单页需要分页,所以需要设置文件名 $download->name = $filename . '_1'; $download->save(); } if ($i >= 1) { $newFileName = $filename . '_' . ($i + 1); $csv->filename = $newFileName; $downloadData = array( 'mall_id' => $download->mall_id, 'mch_id' => $download->mch_id, 'store_id' => $download->store_id, 'name' => $newFileName, 'type' => $download->type, 'handler_class' => $download->handler_class, 'method' => $download->method, 'params' => $download->params, 'data' => $goods_export_list ); $downloadModel = Download::setData($downloadData); if ($downloadModel === false) { Yii::$app->custom->logs('创建下载任务失败:' . $downloadData['name'], Download::getStaticError()); throw new Exception('创建新下载任务失败'); }; $download = $downloadModel; } $csv->export(); $csv->updateDown($download, $params['mall_id']); $i++; } unset($goods_export_list); } // 构建字段列表 return true; } catch (\Exception $e) { $download->status = 3; $res = $download->save(); self::setStaticError($e->getMessage()); return $e->getMessage(); } } } public static function processGoodsDetail(array $goods_detail = []) { if ($goods_detail['is_attr'] == 1 && !empty($goods_detail['attr_groups'])) { $attr = json_decode($goods_detail['attr_groups'], true); if ($attr === null) { // 如果解码失败,返回默认值 $attr_arr = []; } else { $attr_arr = array_map(function ($item) { $item_attr_names = array_map(function ($item) { return htmlspecialchars($item['attr_name']); // 防止 XSS 攻击 }, $item['attr_list']); return htmlspecialchars($item['attr_group_name']) . ':' . implode('、', $item_attr_names); }, $attr); } $goods_detail['goods_group_num'] = count($attr_arr); $goods_detail['attr_groups'] = $attr_arr; } else { $goods_detail['attr_groups'] = '-'; $goods_detail['goods_group_num'] = 0; } if (!empty($goods_detail['cats'])) { $goods_detail['cats'] = implode('|', array_column($goods_detail['cats'], 'name')) ?? ''; } if (!empty($goods_detail['created_at'])) { $goods_detail['created_at'] = Yii::$app->formatter->asDatetime($goods_detail['created_at'], 'Y-m-d H:i:s') ?? ''; } if (in_array($goods_detail['is_on_sale'], [0, 1])) { $goods_detail['is_on_sale'] = $goods_detail['is_on_sale'] == 1 ? '上架' : '下架'; } return $goods_detail; } /** * @return array */ public static function goodsSearchFromAddons($field, $value, $mall_id) { $model = self::find() ->select(['id', 'goods_name', 'cover_pic', 'original_price', 'price']) ->where(['=', 'status', StatusEnum::ENABLED]) ->andWhere(['=', 'mall_id', $mall_id]) ->andWhere(['>', 'stock', 1]); if ($field == 'goods_name') $model->andWhere(['like', 'goods_name', $value]); $goodsLists = []; foreach ($model->batch(500) as $goodsList) { $goodsLists = array_merge($goodsLists, $goodsList); } return $goodsLists; } public static function getGoodsList($params, $is_page = true, $count = false, $is_array = true, $is_get_query = false) { if ($is_page) return Goods::listPage($params, $count, $is_array, $is_get_query); return Goods::lists($params); } /** * 商品处理 * @Author: lun * @DateTime: 2022/1/19 0019 18:06 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $params */ public static function goodsHandle($goods_id, $params) { try { $model = self::findOne(['id' => $goods_id, 'mall_id' => $params['mall_id'], 'status' => [StatusEnum::ENABLED]]); if (empty($model)) throw new Exception('商品不存在或已删除'); if (!$model->load($params, '') || !$model->save()) throw new \yii\db\Exception($model->getErrorMessage()); //判断是否安装云盟店插件 if(MallAddons::isInstall($params['mall_id'],'Yunmeng') && $model->goods_type == 1){ //判断云盟店插件是否已存在该商品数据 $yunmeng_goods = \addons\Yunmeng\common\models\YunmengGoods::findOne(['mall_id' => $params['mall_id'], 'status'=>StatusEnum::ENABLED, 'goods_id'=>$goods_id]); if (!empty($yunmeng_goods)) { //修改云盟店商品状态 \addons\Yunmeng\common\models\YunmengGoods::updateAll(['is_on_sale' => 0], ['mall_id' => $params['mall_id'], 'goods_id' => $goods_id]); \addons\Yunmeng\common\models\YunmengStoreGoods::updateAll(['is_on_sale' => 0], ['mall_id' => $params['mall_id'], 'goods_id' => $goods_id]); //下架门店商品规格 \addons\Yunmeng\common\models\YunmengStoreGoodsAttr::updateAll(['is_on_sale' => 0], ['mall_id' => $params['mall_id'], 'goods_id' => $yunmeng_goods['goods_id']]); } } return true; } catch (Exception $e) { self::setStaticError($e->getMessage()); return false; } } //计算用户价 public static function computeMemberPrice($price, $sign_id, $user_level, $is_attr, $is_member_price, $member_price_setting, $discount) { $after_price = $price; switch ($is_member_price) { case 0: $after_price = bcdiv($price * $discount, 10, 2); break; case 1: //单独设置用户价 if (!empty($is_attr)) { //多规格 if (isset($member_price_setting['level' . $user_level][$sign_id])) $member_price_discount = $member_price_setting['level' . $user_level][$sign_id]; } else { //默认规格 if (isset($member_price_setting[$user_level])) $member_price_discount = $member_price_setting[$user_level]; } if (!empty($member_price_discount)) { // $after_price = 0; if ($price >= $member_price_discount) $after_price = bcmul($member_price_discount, 1, 2); } break; } return $after_price; } /** * 批量导入会员 * @param $params * @return array|bool */ public static function importGoods($params) { $t = Yii::$app->db->beginTransaction(); try { $csvImport = new CsvImportForm(); $data = $csvImport->setDataForm($params) ->setMaxCount(GoodsImportEnum::MAX_COUNT) ->setImportFieldConfig(GoodsImportEnum::HEAD_LIST) ->setColumnNum(GoodsImportEnum::COLUMN_NUM) ->readCsvData(); if (!$data) throw new \Exception(CsvImportForm::getStaticError()); $temp_data = array_column($data, null, 'serial_number'); if (count($temp_data) != count($data)) throw new \Exception('存在重复序号'); unset($temp_data); $result = self::handleImportData($params, $data, 1); $t->commit(); return ['counts' => $result['counts'], 'success_counts' => $result['success_counts'], 'fail_counts' => $result['fail_counts']]; } catch (\Exception $e) { self::$static_error = $e->getMessage(); $t->rollBack(); return false; } } public static function importGoodsSync($params) { $t = Yii::$app->db->beginTransaction(); try { $basePath = \Yii::$app->basePath; if (empty($_FILES) || !isset($_FILES['file'])) throw new \Exception('请上传csv文件'); $fileName = $_FILES['file']['name']; $tmpName = $_FILES['file']['tmp_name']; $basePath = $basePath . '/web/uploads/goods/'; if (!is_dir($basePath)) mkdir($basePath, 0775, true); $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION)); if ($ext != 'csv') throw new \Exception('请上传csv文件'); $uploadFile = $basePath . 'ADMIN-' . date('Y-m-d His') . '.' . $ext; //上传 move_uploaded_file($tmpName, $uploadFile); $success_counts = $fail_counts = 0; $counts = 0; $param['counts'] = $counts; $param['success_counts'] = $success_counts; $param['fail_counts'] = $fail_counts; $param['upload_file'] = $uploadFile; $param['mall_id'] = $params['mall_id']; $param['source'] = self::class; $import_log_model = ImportLog::setData($param); if (!$import_log_model) throw new \Exception(ImportLog::getStaticError()); $t->commit(); $params = ['id' => $import_log_model['id']]; Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_TASK_IMPORT_USER, RabbitMqEnum::IMPORT_USER, $params, self::class, 'syncImportGoods'); return ['counts' => $counts, 'success_counts' => $success_counts, 'fail_counts' => $fail_counts]; } catch (\Exception $e) { self::$static_error = $e->getMessage(); $t->rollBack(); return false; } } public static function handleImportData($params, $data, $sync = 1) { $success_counts = $fail_counts = 0; $counts = count($data); $fail_arr = []; $temp_data = []; $attr_suffix_arr = ['a', 'b', 'c', 'd', 'e']; $bannar_pic_suffix_arr = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i']; $goods_detail_suffix_arr = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i', 'j']; // 方便记录错误 $data = array_column($data, null, 'serial_number'); foreach ($data as $val) { $val['data_row_id'] = $val['serial_number']; $val['mall_id'] = $params['mall_id']; if (empty($val['serial_number'])) { $val['reason'] = '序号为空'; list($fail_arr, $fail_counts) = ImportFailLog::packFailArr($val, $fail_arr, $fail_counts); continue; } if (empty($val['goods_type'])) { $val['reason'] = '商品类型为空'; list($fail_arr, $fail_counts) = ImportFailLog::packFailArr($val, $fail_arr, $fail_counts); continue; } if (empty($val['goods_no'])) { $val['reason'] = '商品编号为空'; list($fail_arr, $fail_counts) = ImportFailLog::packFailArr($val, $fail_arr, $fail_counts); continue; } if (empty($val['goods_name'])) { $val['reason'] = '商品名称为空'; list($fail_arr, $fail_counts) = ImportFailLog::packFailArr($val, $fail_arr, $fail_counts); continue; } if (empty($val['cate'])) { $val['reason'] = '商品分类为空'; list($fail_arr, $fail_counts) = ImportFailLog::packFailArr($val, $fail_arr, $fail_counts); continue; } if (empty($val['price'])) { $val['reason'] = '商品售价为空'; list($fail_arr, $fail_counts) = ImportFailLog::packFailArr($val, $fail_arr, $fail_counts); continue; } if (empty($val['stock'])) { $val['reason'] = '商品库存为空'; list($fail_arr, $fail_counts) = ImportFailLog::packFailArr($val, $fail_arr, $fail_counts); continue; } if (empty($val['cover_pic'])) { $val['reason'] = '商品主图为空'; list($fail_arr, $fail_counts) = ImportFailLog::packFailArr($val, $fail_arr, $fail_counts); continue; } if (!isset($temp_data[$val['goods_no']])) { $temp_data[$val['goods_no']] = [ // 存储每一行的数据 'list' => [], // 存储规格名称与规格值 'attr_groups' => [], // 第一个规格名的规格值图片 'attr_value_pic' => [], ]; } $name = ''; $temp_attr_list = []; $exist_attr = 0; // 处理商品规格 foreach ($attr_suffix_arr as $v) { $attr_column_name = 'attr_name_' . $v; $attr_column_value = 'attr_value_' . $v; if (!isset($val[$attr_column_name])) continue; if (empty($val[$attr_column_name])) continue; if (!isset($val[$attr_column_value])) continue; if (empty($val[$attr_column_value])) continue; if (!isset($attr_column_name, $temp_data[$val['goods_no']]['attr_groups'])) { $temp_data[$val['goods_no']]['attr_groups'][$val[$attr_column_name]] = []; } $temp_data[$val['goods_no']]['attr_groups'][$val[$attr_column_name]][] = $val[$attr_column_value]; $temp_data[$val['goods_no']]['attr_groups'][$val[$attr_column_name]] = array_unique($temp_data[$val['goods_no']]['attr_groups'][$val[$attr_column_name]]); if ($v == 'a' && !empty($val['pic_url'])) { $temp_data[$val['goods_no']]['attr_value_pic'][$val[$attr_column_value]] = $val['pic_url']; } $name .= $val[$attr_column_name] . ':' . $val[$attr_column_value] . ':'; $temp_attr_list[] = [ 'attr_id' => 0, 'attr_name' => $val[$attr_column_value], 'attr_group_id' => 0, 'attr_group_name' => $val[$attr_column_name], 'pic_url' => '' ]; $exist_attr++; } if ($exist_attr <= 0) { $val['reason'] = '商品规格全为空'; list($fail_arr, $fail_counts) = ImportFailLog::packFailArr($val, $fail_arr, $fail_counts); unset($temp_data[$val['goods_no']]); continue; } $val['name'] = trim($name, ':'); $val['temp_attr_list'] = $temp_attr_list; // 处理商品轮播图 foreach ($bannar_pic_suffix_arr as $k => $bannar_item) { $bannar_pic_column = 'bannar_pic_' . $bannar_item; if (!isset($val[$bannar_pic_column])) continue; if (empty($val[$bannar_pic_column])) continue; $val['bannar_pic'][] = ['id' => $k, 'pic_url' => $val[$bannar_pic_column]]; } // 处理商品详情图片 $goods_detail_str = '
';
foreach ($goods_detail_suffix_arr as $detail_item) {
$goods_detail_column = 'goods_detail_' . $detail_item;
if (!isset($val[$goods_detail_column])) continue;
if (empty($val[$goods_detail_column])) continue;
$goods_detail_str .= '';
}
$goods_detail_str .= '