| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479 |
- <?php
- namespace addons\Store\common\models;
- use addons\Store\common\enums\StoreEnum;
- use addons\Store\common\events\goods\GoodsEditEvent;
- use common\components\export\CsvTool;
- use common\enums\AddonsEnum;
- use common\enums\DownloadEnum;
- use common\enums\GoodsTypeEnum;
- use common\enums\import\GoodsImportEnum;
- use common\enums\RabbitMqEnum;
- use common\enums\StatusEnum;
- use common\enums\WhetherEnum;
- use common\globals\GlobalInvoke;
- use common\helpers\ArrayHelper;
- use common\helpers\csv\CsvImportForm;
- use common\models\base\BaseActiveRecord;
- use common\models\common\Download;
- use common\models\common\ImportFailLog;
- use common\models\common\ImportLog;
- use common\models\goods\GoodsAttr;
- use common\models\goods\GoodsCateRelate;
- use common\models\goods\GoodsExtra;
- use common\models\goods\GoodsAssociation;
- use common\models\goods\GoodsReserveSku;
- use common\models\mall\MallAddons;
- use Exception;
- use Yii;
- use yii\db\Expression;
- /**
- * This is the model class for table "qimall_addons_store_goods".
- *
- * @property int $id
- * @property int $mall_id 商城id
- * @property int $mall_goods_id 主商城goods_id
- * @property int $store_id 门店id
- * @property string $goods_name 商品名称
- * @property string $subtitle 商品副标题
- * @property float $price 售价
- * @property float $original_price 原价(划线价仅展示)
- * @property float $cost_price 成本价
- * @property string $unit 单位
- * @property string $cover_pic 商品缩略图
- * @property string $bannar_pic 商品展示bannar图
- * @property string $video_url 商品视频
- * @property string $video_cover_pic 商品视频封面
- * @property int $is_on_sale 上架状态【1是 0否】
- * @property int $is_attr 是否有规格【1是 0否】
- * @property string|null $attr_groups 规格组
- * @property string|null $attr_groups_format 格式化规格组
- * @property int $status 状态[1正常 -1删除]
- * @property int $stock 商品库存
- * @property int $stock_warning 商品库存预警
- * @property int $is_show_stock 是否显示库存
- * @property int $is_show_sales 是否显示销量【1是 0否】
- * @property int $virtual_sales 虚拟销量
- * @property int $sales_num 累计销量
- * @property int $buy_num_limit 购买数量限制
- * @property string $freight_type 物流方式【1快递发货 2上门自提】逗号分隔
- * @property int $freight_rules_type 运费规则 【1运费模板 2自定义运费】
- * @property int $freight_id 运费模板ID
- * @property float $shipping_fee 自定义运费金额
- * @property int $free_shipping_num 商品满件包邮
- * @property float $free_shipping_money 商品满额包邮
- * @property int $goods_type 商品类型
- * @property string|null $detail 商品详情,图文
- * @property int $is_area_limit 是否开启限购区域
- * @property string|null $area_limit 限购区域
- * @property string $services 商品服务
- * @property string $labels 商品标签
- * @property string|null $goods_source 商品来源
- * @property int $supplier_type 供应者类型:0:自身;1:商城;2:o2o;3:多商户
- * @property int $supplier_id 供应者id
- * @property int $supplier_goods_id 供应品id
- * @property int $sort 排序
- * @property int $check_status 审核状态 0:待审核;1;:已通过;2:未通过
- * @property string $check_remark 审核备注
- * @property int $created_at 创建时间
- * @property int $updated_at 修改时间
- * @property int $show_style 商品展示风格
- * @property int $is_recommend 店铺推荐
- * @property float $credit_rate 赊账比例
- * @property string $package_data 套餐json数据
- */
- class StoreGoods extends BaseActiveRecord
- {
- /**
- * {@inheritdoc}
- */
- public static function tableName()
- {
- return '{{%addons_store_goods}}';
- }
- /**
- * {@inheritdoc}
- */
- public function rules()
- {
- return [
- [['mall_id', 'mall_goods_id', 'store_id', 'is_on_sale', 'is_attr', 'status', 'stock', 'stock_warning', 'is_show_stock', 'is_show_sales', 'virtual_sales', 'sales_num', 'buy_num_limit', 'freight_rules_type', 'freight_id', 'free_shipping_num', 'goods_type', 'is_area_limit', 'supplier_type', 'supplier_id', 'supplier_goods_id', 'sort', 'check_status', 'created_at', 'updated_at',
- 'is_recommend','show_style'], 'integer'],
- [['price', 'original_price', 'cost_price', 'shipping_fee', 'free_shipping_money','credit_rate'], 'number'],
- [['attr_groups', 'attr_groups_format', 'detail', 'area_limit', 'package_data'], 'string'],
- [['goods_name'], 'string', 'max' => 120],
- [['subtitle'], 'string', 'max' => 150],
- [['unit', 'cover_pic', 'video_url', 'freight_type', 'goods_no'], 'string', 'max' => 255],
- [['check_remark'], 'safe'],
- [['bannar_pic'], 'string', 'max' => 1500],
- [['video_cover_pic', 'services', 'labels'], 'string', 'max' => 500],
- [['goods_source'], 'string', 'max' => 32],
- ];
- }
- /**
- * {@inheritdoc}
- */
- public function attributeLabels()
- {
- return [
- 'id' => 'ID',
- 'mall_id' => '商城id',
- 'mall_goods_id' => '主商城goods_id',
- 'store_id' => '门店id',
- 'goods_name' => '商品名称',
- 'subtitle' => '商品副标题',
- 'price' => '售价',
- 'original_price' => '原价(划线价仅展示)',
- 'cost_price' => '成本价',
- 'unit' => '单位',
- 'cover_pic' => '商品缩略图',
- 'bannar_pic' => '商品展示bannar图',
- 'video_url' => '商品视频',
- 'video_cover_pic' => '商品视频封面',
- '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' => '限购区域',
- 'services' => '商品服务',
- 'labels' => '商品标签',
- 'goods_source' => '商品来源',
- 'supplier_type' => '供应者类型:0:自身;1:商城;2:o2o;3:多商户',
- 'supplier_id' => '供应者id',
- 'supplier_goods_id' => '供应品id',
- 'sort' => '排序',
- 'check_status' => '审核状态 0:待审核;1;:已通过;2:未通过',
- 'check_remark' => '审核备注',
- 'created_at' => '创建时间',
- 'updated_at' => '修改时间',
- 'show_style' => '商品展示风格',
- 'is_recommend' => '店铺推荐',
- 'package_data' => '套餐json数据',
- 'goods_no' => '商品货号',
- ];
- }
- // 分类关系
- public function getStoreGoodsCateRelate()
- {
- return $this->hasMany(StoreGoodsCateRelate::class, ['goods_id' => 'id']);
- }
- // 分类
- public function getCats()
- {
- return $this->hasMany(StoreGoodsCate::class, ['id' => 'cate_id'])->via('storeGoodsCateRelate');
- }
- // 商品额外设置
- public function getExtra()
- {
- return $this->hasOne(StoreGoodsExtra::class, ['goods_id' => 'id'])->andWhere(['status' => [StatusEnum::ENABLED]]);
- }
- // sku
- public function getAttr()
- {
- return $this->hasMany(StoreGoodsAttr::class, ['goods_id' => 'id'])->andWhere(['status' => [StatusEnum::ENABLED]]);
- }
- // 预约商品信息
- public function getReserve()
- {
- return $this->hasOne(StoreGoodsReserve::class, ['goods_id' => 'id']);
- }
- public function getStore()
- {
- return $this->hasOne(Store::class, ['id' => 'store_id']);
- }
- /**
- * 保存数据
- * @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)
- {
- $store_id = $params['store_id'];
- $mall_id = $params['mall_id'];
- 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('商品不存在或已删除');
- } else {
- $model = new self();
- $model->loadDefaultValues();
- }
- // 如果是预约商品
- if ($params['goods_type'] == GoodsTypeEnum::GoodsTypeReserved) {
- // 取出最低价
- if (!empty($params['reserve']['skus'])) {
- $params['stock'] = array_sum(array_column($params['reserve']['skus'], 'reserve_max_buy'));
- } else {
- $params['stock'] = $params['reserve']['reserve_max_buy'];
- }
- }
- self::priceLimit($mall_id,$params['price']);
- 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;
- 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);
- isset($params['package_data']) && $params['package_data'] = json_encode($params['package_data'], 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()) {
- throw new \Exception($model->getErrorMessage());
- }
- //商品分类处理
- if (isset($params['cats']) && !empty($params['cats'])) {
- $res = StoreGoodsCateRelate::setData($model->id, $params['cats']);
- if ($res === false) throw new \Exception('分类处理失败:' . GoodsCateRelate::getStaticError());
- }
- $goods = ArrayHelper::toArray($model);
- if ($goods['goods_type'] === GoodsTypeEnum::GoodsTypeReserved) {
- // 预约商品
- $reserve = $params['reserve'];
- $res = StoreGoodsReserve::setData($goods, $reserve);
- if ($res === false) throw new Exception('预约商品SKU处理失败:' . StoreGoodsAttr::getStaticError());
- } else {
- // 商品规格处理
- if ($model->is_attr == 1) {
- $attrs = $params['attr'] ?? [];
- $res = StoreGoodsAttr::setData($model->id, $attrs, $attr_groups, $mall_id, $wait_del_attr_id_arr);
- if ($res === false) throw new \Exception('规格处理失败:' . GoodsAttr::getStaticError());
- } else {
- //无规格商品处理
- $goods = ArrayHelper::toArray($model);
- $goods['pic_url'] = $goods['cover_pic'];
- $goods['weight'] = $params['goods_weight'] ?? 0;
- if ($goods['supplier_type'] == StoreEnum::SELF_MALL_WUZHOU && $goods['mall_goods_id']) {
- // 五洲供应链商品,记录规格id
- $mall_goods_attr = GoodsAttr::findOne(['goods_id' => $goods['mall_goods_id'], 'status' => StatusEnum::ENABLED]);
- $goods['mall_attr_id'] = $mall_goods_attr->id ?? 0;
- }
- $res = StoreGoodsAttr::setAttr($model->id, $goods);
- if ($res === false) throw new \Exception('设置货品失败:' . GoodsAttr::getStaticError());
- }
- }
- // 商品额外信息处理
- if (isset($params['extra']) && !empty($params['extra'])) {
- if (isset($params['extra']['platform_score_give_setting'])) unset($params['extra']['platform_score_give_setting']);
- $params['extra']['store_id'] = $store_id;
- $params['extra']['mall_id'] = $mall_id;
- $res = StoreGoodsExtra::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());
- }
- $is_install = MallAddons::isInstall($mall_id, AddonsEnum::ADDONS_NAME_COUPON);
- if($is_install){
- $res = StoreCouponGiveItemSetting::setGoodsSetting($params['mall_id'], $params['store_id'],$model['id'], $params);
- if ($res === false) throw new \Exception('商品设置赠送优惠券信息处理失败:' . StoreCouponGiveItemSetting::getStaticError());
- }
- $res = GoodsAssociation::setData($model->id, $params);
- $trans->commit();
- $event = new GoodsEditEvent($model['mall_id']);
- $data['goods_id'] = $model['id'];
- $data['mall_id'] = $model['mall_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 = StoreGoodsCate::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;
- }
- public static function priceLimit($mall_id,$price){
- $goodsStore = \Yii::$app->services->setting->addons->get($mall_id, StoreEnum::ADDONS_NAME, 'goodsStore');
- if(!empty($goodsStore['min_price'])){
- if($price<$goodsStore['min_price']){
- throw new \Exception('最低价格不能低于'.$goodsStore['min_price']);
- }
- }
- if(isset($goodsStore['is_limit_max_price'])&&$goodsStore['is_limit_max_price']=='false'){
- if(!empty($goodsStore['min_price'])) {
- if ($price > $goodsStore['max_price']) {
- throw new \Exception('最高价格不能高于' . $goodsStore['max_price']);
- }
- }
- }
- }
- /**
- * 格式化商品规格组数据
- * @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;
- }
- /**
- * 商品处理
- * @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());
- return true;
- } catch (\Exception $e) {
- self::setStaticError($e->getMessage());
- return false;
- }
- }
- /**
- * 商品详情
- * @param $params
- * @return mixed|void
- */
- public static function getGoodsDetail($params)
- {
- $goods = StoreGoods::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'];
- unset($goods['virtual_sales']);
- return $goods;
- }
- public static function getGoodListInDiy(int $mall_id, array $params)
- {
- $wheres[] = ['sg.mall_id' => $mall_id, 'sg.status' => StatusEnum::ENABLED, 'sg.check_status' => StoreEnum::CHECK_ADOPT, 'sg.is_on_sale' => 1, 's.status' => StatusEnum::ENABLED, 's.check_status' => StoreEnum::CHECK_ADOPT];
- $wheres[] = ['or', ['>', 'expire_time', time()], ['expire_time' => 0]];
- if (!empty($params['keyword'])) {
- $wheres[] = ['like', 'sg.goods_name', $params['keyword']];
- }
- if (!empty($params['store_id'])) {
- $wheres[] = ['sg.store_id' => $params['store_id']];
- }
- $params = [
- 'alias' => 'sg',
- 'select' => 'sg.*,s.store_name',
- 'join' => [['INNER JOIN', Store::tableName() . ' as s', 'sg.store_id = s.id']],
- 'where' => $wheres,
- 'order' => 'sg.sort asc,sg.created_at desc',
- 'page' => $params['page'] ?? 1,
- 'limit' => $params['limit'] ?? 15,
- ];
- $list = self::listPage($params);
- if (false === $list) {
- return self::$static_error;
- }
- foreach ($list['list'] as &$lv) {
- $lv['title'] = $lv['goods_name'];
- $lv['img'] = $lv['cover_pic'];
- }
- return $list;
- }
- public static function getRecommendGoodListInDiy(int $mall_id, array $params)
- {
- $wheres[] = [
- 'sg.mall_id' => $mall_id,
- 'sg.is_recommend' => 1,
- 'sg.status' => StatusEnum::ENABLED,
- 'sg.check_status' => StoreEnum::CHECK_ADOPT,
- 'sg.is_on_sale' => 1, 's.status' => StatusEnum::ENABLED,
- 's.check_status' => StoreEnum::CHECK_ADOPT
- ];
- $wheres[] = ['or', ['>', 'expire_time', time()], ['expire_time' => 0]];
- if (!empty($params['keyword'])) {
- $wheres[] = ['like', 'sg.goods_name', $params['keyword']];
- }
- if (!empty($params['store_id'])) $wheres[] = ['sg.store_id' => $params['store_id']];
- $params = [
- 'alias' => 'sg',
- 'select' => 'sg.id,sg.goods_name,sg.cover_pic,sg.price,sg.original_price,sg.show_style,(sg.virtual_sales+sg.sales_num) as sales_num,sg.created_at,s.store_name ',
- 'join' => [
- ['INNER JOIN', Store::tableName() . ' as s', 'sg.store_id = s.id'],
- ],
- 'where' => $wheres,
- 'order' => 'sg.sort asc,sg.created_at desc',
- 'page' => $params['page'] ?? 1,
- 'limit' => $params['limit'] ?? 15,
- ];
- $list = StoreGoods::listPage($params);
- if (false === $list) {
- return self::$static_error;
- }
- foreach ($list['list'] as &$val) {
- $val['title'] = $val['goods_name'];
- $val['img'] = $val['cover_pic'];
- $val['discount'] = bcsub($val['original_price'],$val['price'],2);
- if($val['discount']<0) $val['discount'] = 0;
- }
- return $list;
- }
- public static function getRecommendList($mall_id,$store_id){
- $goods_list = StoreGoods::lists([
- 'where'=>[
- ['mall_id'=>$mall_id,'store_id'=>$store_id,'status'=>StatusEnum::ENABLED,'is_recommend'=>1,'check_status'=>1,'is_on_sale'=>1]
- ],
- 'select'=>'id,goods_name,price,original_price,cover_pic'
- ]);
- return $goods_list;
- }
- public static function syncMallGoods($params){
- try{
- $mall_id = $params['mall_id'];
- $selected_goods_ids = $params['selected_goods_ids'];
- $selected_store_ids = $params['selected_store_ids'];
- $sync_type = $params['sync_type'];
- // 同步商品到全部门店
- if($sync_type == 1){
- $store_where[] = ['mall_id' => $mall_id, 'check_status' => StoreEnum::CHECK_ADOPT, 'status' => StatusEnum::ENABLED];
- $store_ids = Store::lists([
- 'where' => $store_where,
- 'select' => 'id'
- ]);
- $selected_store_ids = array_column($store_ids, 'id') ?? [];
- }
- $store_goods_cate = self::getPlatformGoodsCate($mall_id);
- if(empty($store_goods_cate)){
- $cate = ['mall_id' => $mall_id, 'name' => '平台', 'store_id' => 0, 'cate_id' => 0,'parent_id' => 0];
- if(!$store_goods_cate = StoreGoodsCate::setData($cate)) throw new \Exception(StoreGoodsCate::getStaticError());
- }
- /**
- * @var $goods_list \common\models\goods\Goods[]
- */
- $goods_list = \common\models\goods\Goods::findAll(['mall_id' => $mall_id, 'id' => $selected_goods_ids]);
- foreach ($goods_list as $goods) {
- foreach ($selected_store_ids as $store_id) {
- try{
- $store_goods = self::findOne(['mall_id' => $mall_id, 'store_id' => $store_id, 'mall_goods_id' => $goods['id'], 'status' => StatusEnum::ENABLED]);
- $base_params = [
- 'mall_id' => $mall_id,
- 'store_id' => $store_id,
- 'supplier_id' => $store_id,
- 'cats' => [$store_goods_cate['id']],
- 'mall_goods_id' => $goods['id'],
- 'id' => $store_goods['id'] ?? 0,
- 'coupon_selection' => [],
- 'check_status' => StatusEnum::ENABLED
- ];
- $mall_goods = $goods['attributes'];
- $base_params['extra'] = !empty($goods->extra) ? ArrayHelper::toArray($goods->extra) : [];
- if(isset($base_params['extra']['goods_id'])) unset($base_params['extra']['goods_id']);
- if(empty($mall_goods['services'])){
- $mall_goods['services'] = [];
- }else{
- $mall_goods['services'] = explode(',', $mall_goods['services']);
- }
- if(empty($mall_goods['labels'])){
- $mall_goods['labels'] = [];
- }else{
- $mall_goods['labels'] = explode(',', $mall_goods['labels']);
- }
- if(empty($mall_goods['freight_type'])){
- $mall_goods['freight_type'] = [];
- }else{
- $mall_goods['freight_type'] = explode(',', $mall_goods['freight_type']);
- }
- !empty($mall_goods['attr_groups']) && $mall_goods['attr_groups'] = json_decode($mall_goods['attr_groups'], true);
- !empty($mall_goods['bannar_pic']) && $mall_goods['bannar_pic'] = json_decode($mall_goods['bannar_pic'], true);
- !empty($mall_goods['area_limit']) && $mall_goods['area_limit'] = json_decode($mall_goods['area_limit'], true);
- // 预约商品
- if ($mall_goods['goods_type'] == GoodsTypeEnum::GoodsTypeReserved) {
- $reserve = ArrayHelper::toArray($goods->reserve);
- unset($reserve['id'], $reserve['goods_id']);
- $skus = GoodsReserveSku::lists([
- 'where' => [['goods_id' => $goods['id']]],
- 'with' => ['times' => function($query) {
- $query->with(['timeSpec']);
- }]
- ]);
- foreach ($skus as &$sku) {
- $signId = $sku['sign_id'];
- $attr_groups_format = json_decode($goods['attr_groups_format'], true) ?? [];
- $sku['attr_list'] = $attr_groups_format[$signId] ?? [];
- unset($sku['id'], $sku['goods_id']);
- foreach ($sku['times'] as &$time) {
- unset($time['id'], $time['reserve_sku_id']);
- if (!empty($time['timeSpec'])) {
- foreach ($time['timeSpec'] as &$time_spec) {
- unset($time_spec['id'], $time_spec['reserve_time_id'], $time_spec['reserve_sku_id']);
- }
- $time['time_spec'] = $time['timeSpec'];
- unset($time_spec, $time['timeSpec']);
- }
- }
- unset($time);
- }
- unset($sku);
- $reserve['skus'] = $skus;
- $mall_goods['reserve'] = $reserve;
- } else {
- if ($mall_goods['is_attr'] == 1) {
- $temp_attrs = ArrayHelper::toArray($goods->attr);
- $attr_groups = $mall_goods['attr_groups'];
- $attr = [];
- foreach ($temp_attrs as $val) {
- unset($val['id']);
- unset($val['goods_id']);
- $sku_group_name = explode(',', $val['name']);
- $attr_list = [];
- foreach($sku_group_name as $name){
- $name_arr = explode(':', $name);
- foreach($attr_groups as $group){
- if($group['attr_group_name'] == $name_arr[0]){
- foreach($group['attr_list'] as $v){
- if($v['attr_name'] == $name_arr[1]){
- $attr_list[] = [
- 'attr_id' => $v['attr_id'],
- 'attr_name' => $v['attr_name'],
- 'pic_url' => '',
- 'attr_group_id' => $group['attr_group_id'],
- 'attr_group_name' => $group['attr_group_name'],
- ];
- break;
- }
- }
- break;
- }
- }
- }
- $val['attr_list'] = $attr_list;
- $attr[] = $val;
- }
- $base_params['attr'] = $attr;
- }
- }
- unset($mall_goods['id']);
- if(!self::setData(array_merge($mall_goods, $base_params))) throw new \Exception(self::getStaticError());
- }catch(\Exception $e){
- \Yii::error(self::class.'->'.__FUNCTION__.'//errMsg2:'.$e->getMessage().'//params:'.json_encode(array_merge($mall_goods, $base_params)));
- }
- }
- }
- }catch(\Exception $e){
- \Yii::error(self::class.'->'.__FUNCTION__.'//errMsg1:'.$e->getMessage());
- }finally{
- return true;
- }
- }
- public static function getPlatformGoodsCate($mall_id)
- {
- return StoreGoodsCate::findOne(['mall_id' => $mall_id, 'store_id' => 0, 'name' => '平台']);
- }
- 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;
- }
- public static function syncMchGoods($params)
- {
- try {
- $selected_goods_ids = $params['selected_goods_ids'];
- $store_id = $params['store_id'];
- $mall_id = $params['mall_id'];
- $goods_list = \common\models\goods\Goods::findAll(['id' => $selected_goods_ids]);
- /** @var \common\models\goods\Goods $goods */
- foreach ($goods_list as $goods) {
- try {
- $cats = ArrayHelper::toArray($goods->cats);
- $goods_cats_name = array_column($cats, 'name') ?? [];
- if(empty($goods_cats_name)) continue;
- $store_goods_cates = StoreGoodsCate::lists([
- 'where' => [
- ['mall_id' => $mall_id], ['name' => $goods_cats_name], ['status' => StatusEnum::ENABLED],
- ],
- 'select' => 'id, name, parent_id'
- ]);
- $idx_name = array_column($store_goods_cates, 'id', 'name') ?? [];
- $need_insert = $idx_name ? array_diff($idx_name, $goods_cats_name) : $goods_cats_name;
- if(!empty($need_insert)){
- $need_insert_cate = \common\models\goods\GoodsCate::lists([
- 'where' => [
- ['mall_id' => $goods->mall_id],
- ['name' => $need_insert]
- ],
- 'select' => 'id,mall_id, name, mch_id, parent_id, pic, big_pic, advert_pic, advert_url, advert_params, is_show',
- 'with' => ['parent.parent']
- ]);
- self::loopSaveGoodsCate($need_insert_cate, $store_id, $mall_id, $idx_name);
- }
- $store_goods = self::findOne(['mall_id' => $mall_id, 'store_id' => $store_id, 'mall_goods_id' => $goods['id'], 'status' => StatusEnum::ENABLED]);
- $base_params = [
- 'mall_id' => $mall_id,
- 'store_id' => $store_id,
- 'cats' => array_values($idx_name),
- 'mall_goods_id' => $goods['id'],
- 'id' => $store_goods['id'] ?? 0,
- 'coupon_selection' => [],
- 'check_status' => StatusEnum::ENABLED,
- 'is_on_sale' => StatusEnum::DISABLED
- ];
- $mall_goods = $goods['attributes'];
- $base_params['extra'] = !empty($goods->extra) ? ArrayHelper::toArray($goods->extra) : [];
- if (isset($base_params['extra']['goods_id'])) unset($base_params['extra']['goods_id']);
- if (empty($mall_goods['services'])) {
- $mall_goods['services'] = [];
- } else {
- $mall_goods['services'] = explode(',', $mall_goods['services']);
- }
- if (empty($mall_goods['labels'])) {
- $mall_goods['labels'] = [];
- } else {
- $mall_goods['labels'] = explode(',', $mall_goods['labels']);
- }
- if (empty($mall_goods['freight_type'])) {
- $mall_goods['freight_type'] = [];
- } else {
- $mall_goods['freight_type'] = explode(',', $mall_goods['freight_type']);
- }
- !empty($mall_goods['attr_groups']) && $mall_goods['attr_groups'] = json_decode($mall_goods['attr_groups'], true);
- !empty($mall_goods['bannar_pic']) && $mall_goods['bannar_pic'] = json_decode($mall_goods['bannar_pic'], true);
- !empty($mall_goods['area_limit']) && $mall_goods['area_limit'] = json_decode($mall_goods['area_limit'], true);
- if ($mall_goods['is_attr'] == 1) {
- $temp_attrs = ArrayHelper::toArray($goods->attr);
- $attr_groups = $mall_goods['attr_groups'];
- $attr = [];
- foreach ($temp_attrs as $val) {
- unset($val['id']);
- unset($val['goods_id']);
- $sku_group_name = explode(',', $val['name']);
- $attr_list = [];
- foreach ($sku_group_name as $name) {
- $name_arr = explode(':', $name);
- foreach ($attr_groups as $group) {
- if ($group['attr_group_name'] == $name_arr[0]) {
- foreach ($group['attr_list'] as $v) {
- if ($v['attr_name'] == $name_arr[1]) {
- $attr_list[] = [
- 'attr_id' => $v['attr_id'],
- 'attr_name' => $v['attr_name'],
- 'pic_url' => '',
- 'attr_group_id' => $group['attr_group_id'],
- 'attr_group_name' => $group['attr_group_name'],
- ];
- }
- }
- break;
- }
- }
- }
- $val['attr_list'] = $attr_list;
- $attr[] = $val;
- }
- $base_params['attr'] = $attr;
- }
- unset($mall_goods['id']);
- if (!self::setData(array_merge($mall_goods, $base_params))) throw new \Exception(self::getStaticError());
- } catch (\Exception $e) {
- dd($e->getMessage());
- \Yii::error(__METHOD__ . '//errMsg2:' . $e->getMessage() . '//params:' . json_encode(array_merge($mall_goods, $base_params)));
- }
- }
- } catch (\Exception $e) {
- dd($e->getMessage());
- \Yii::error(__METHOD__ . '//errMsg1:' . $e->getMessage());
- } finally {
- return true;
- }
- }
- public static function loopSaveGoodsCate($cats, $store_id, $mall_id, &$idx_name)
- {
- foreach ($cats as $item) {
- $item['store_id'] = $store_id;
- $item['mall_id'] = $mall_id;
- unset($item['id'], $item['mch_id']);
- if ($item['parent']) {
- self::loopSaveGoodsCate([$item['parent']], $store_id, $mall_id, $idx_name);
- } else {
- $saveRes = StoreGoodsCate::setData($item);
- if ($saveRes === false) throw new \Exception(StoreGoodsCate::getStaticError());
- $idx_name['name'] = $saveRes->id;
- }
- }
- }
- //商品导出整理数据
- 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 = StoreGoods::find();
- $goods_detail_model->where(['mall_id' => $params['mall_id'],'store_id' => $params['store_id']]);
- $goods_detail_model->andWhere(['>', 'status', StatusEnum::DISABLED]);
- !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 = StoreGoodsCateRelate::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 'checking':
- $goods_detail_model->andWhere(['=', 'g.check_status', 0]);
- break;
- case 'onsale':
- $goods_detail_model->andWhere(['=', 'g.is_on_sale', WhetherEnum::ENABLED]);
- $goods_detail_model->andWhere(['=', 'g.check_status', 1]);
- $goods_detail_model->andWhere(['>', 'g.stock', 0]);
- 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++;
- }
- }
- 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'] = date("Y-m-d H:i:s", $goods_detail['created_at']) ?? '';
- }
- if (in_array($goods_detail['is_on_sale'], [0, 1])) {
- $goods_detail['is_on_sale'] = $goods_detail['is_on_sale'] == 1 ? '上架' : '下架';
- }
- return $goods_detail;
- }
- 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;
- }
- /**
- * 批量导入商品
- * @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;
- }
- }
- /**
- * 商品数据入库
- * @param $params
- * @param $data
- * @param $sync
- * @return array|void
- * @throws Exception
- */
- 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'] . $val['goods_name']])) {
- $temp_data[$val['goods_no'] . $val['goods_name']] = [
- // 存储每一行的数据
- 'list' => [],
- // 存储规格名称与规格值
- 'attr_groups' => [],
- // 第一个规格名的规格值图片
- 'attr_value_pic' => [],
- ];
- }
- $name = '';
- $temp_attr_list = [];
- $exist_attr = 0;
- // 判断门店是否需要审核商品
- $isGoodsAuth = Yii::$app->services->setting->addons->get($params['mall_id'], StoreEnum::ADDONS_NAME, 'basic.goods_auth');
- // 处理商品规格
- 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'] . $val['goods_name']]['attr_groups'])) {
- $temp_data[$val['goods_no'] . $val['goods_name']]['attr_groups'][$val[$attr_column_name]] = [];
- }
- $temp_data[$val['goods_no'] . $val['goods_name']]['attr_groups'][$val[$attr_column_name]][] = $val[$attr_column_value];
- $temp_data[$val['goods_no'] . $val['goods_name']]['attr_groups'][$val[$attr_column_name]] = array_unique($temp_data[$val['goods_no'] . $val['goods_name']]['attr_groups'][$val[$attr_column_name]]);
- if ($v == 'a' && !empty($val['pic_url'])) {
- $temp_data[$val['goods_no'] . $val['goods_name']]['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'] . $val['goods_name']]);
- 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 = '<p>';
- 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 .= '<img src="' . $val[$goods_detail_column] . '" />';
- }
- $goods_detail_str .= '</p>';
- $val['goods_detail'] = $goods_detail_str;
- if (!empty($val['cate'])) {
- $val['cate'] = explode(',', $val['cate']);
- // 查询是否存在分类
- $caste_ids=StoreGoodsCate::find()->select(['id'])
- ->where(['mall_id' => $params['mall_id'], 'store_id' => $params['store_id']
- , 'name' => $val['cate'], 'status' => StatusEnum::ENABLED])->all();
- if ($caste_ids) {
- $val['cats'] = array_column($caste_ids, "id");
- }
- }
- $temp_data[$val['goods_no'] . $val['goods_name']]['list'][] = $val;
- }
- $extra = [
- 'full_reduce_price_limit' => 0,
- 'full_reduce_money' => 0,
- 'is_member_price' => 0,
- 'is_show_price' => 0,
- 'member_price_switch' => 0,
- 'score_give_setting' => [
- 'code' => 'score',
- 'name' => '积分',
- 'give_num' => 0,
- 'give_type' => 1,
- ],
- 'member_buy_limit_setting' => [
- 'member_level' => [],
- 'every_num' => 0,
- 'every_day_num' => 0,
- 'every_week_num' => 0,
- 'every_month_num' => 0,
- 'nums' => 0,
- 'total_num' => 0,
- ],
- 'currency_deduct_setting' => [],
- 'score_deduct_setting' => [
- 'code'=>'score',
- 'name'=> '积分',
- 'is_enable'=> 0,
- 'deduct_num'=> 0,
- 'deduct_type' => 1,
- ],
- ];
- foreach ($temp_data as $goods_no => $list) {
- $sku = $list['list'];
- $attr_groups = $list['attr_groups'];
- $attr_value_pic = $list['attr_value_pic'];
- $is_attr = count($sku) > 1 ? 1 : 0;
- $goods_type_res = array_search($sku[0]['goods_type'], GoodsImportEnum::GOODS_TYPE);
- $temp = [
- 'goods_name' => $sku[0]['goods_name'],
- 'subtitle' => $sku[0]['subtitle'] ?? '',
- 'cats' => $sku[0]['cate'],
- 'is_attr' => $is_attr,
- 'check_status' => empty($isGoodsAuth) ? 1 : 0,
- 'price' => !empty($sku[0]['price']) ? $sku[0]['price'] : 0,
- 'cost_price' => !empty($sku[0]['cost_price']) ? $sku[0]['cost_price'] : 0,
- 'original_price' => !empty($sku[0]['original_price']) ? $sku[0]['original_price'] : 0,
- 'sales_num' => !empty($sku['sales_num']) ? $sku['sales_num'] : 0,
- 'virtual_sales' => !empty($sku[0]['virtual_sales']) ? $sku[0]['virtual_sales'] : 0,
- 'unit' => $sku[0]['unit'] ?? '',
- 'stock' => !empty($sku[0]['stock']) ? $sku[0]['stock'] : 0,
- 'cover_pic' => $sku[0]['cover_pic'] ?? '',
- 'bannar_pic' => $sku[0]['bannar_pic'] ? $sku[0]['bannar_pic'] : [],
- 'freight_type' => ['1'],
- 'freight_rules_type' => 2,
- 'freight_id' => 3,
- 'shipping_fee' => 0,
- 'free_shipping_num' => 0,
- 'free_shipping_money' => 0,
- 'is_on_sale' => 1, //上架状态
- 'goods_type' => $goods_type_res ? $goods_type_res : 1, //商品类型
- 'mall_id' => $params['mall_id'],
- 'store_id' => $params['store_id'],
- 'detail' => $sku[0]['goods_detail'],
- 'extra' => $extra,
- 'serial_number' => $sku[0]['serial_number']
- ];
- // 处理多规格
- if ($is_attr == 1) {
- $attr = [];
- $temp_attr_groups = [];
- $attr_groups_index = 1;
- $attr_list_index = 2;
- $temporary_attr_list = [];
- $temporary_attr_group_list = [];
- foreach ($attr_groups as $group_name => $group) {
- $attr_list = [];
- foreach ($group as $attr_item) {
- $attr_list[] = [
- 'attr_id' => $attr_list_index,
- 'attr_name' => $attr_item,
- 'pic_url' => $attr_value_pic[$attr_item] ?? '',
- ];
- $temporary_attr_list[$attr_item] = $attr_list_index;
- $attr_list_index++;
- }
- $temp_attr_groups[] = [
- 'attr_group_id' => $attr_groups_index,
- 'attr_group_name' => $group_name,
- 'attr_list' => $attr_list
- ];
- $temporary_attr_group_list[$group_name] = $attr_groups_index;
- $attr_groups_index++;
- }
- $temp['attr_groups'] = $temp_attr_groups;
- foreach ($sku as $ku) {
- $temp_sku = [];
- $temp_sku['price'] = !empty($ku['price']) ? $ku['price'] : 0;
- $temp_sku['stock'] = !empty($ku['stock']) ? $ku['stock'] : 0;
- $temp_sku['original_price'] = !empty($ku['original_price']) ? $ku['original_price'] : 0;
- $temp_sku['cost_price'] = !empty($ku['cost_price']) ? $ku['cost_price'] : 0;
- $temp_sku['name'] = $ku['name'];
- $temp_sku['weight'] = 0;
- $temp_sku['goods_no'] = $goods_no;
- $temp_sku['attr_list'] = $ku['temp_attr_list'];
- $temp_sku['data_row_id'] = $ku['data_row_id'];
- foreach ($temp_sku['attr_list'] as &$sku_attr) {
- $sku_attr['attr_id'] = $temporary_attr_list[$sku_attr['attr_name']];
- $sku_attr['attr_group_id'] = $temporary_attr_group_list[$sku_attr['attr_group_name']];
- }
- unset($sku_attr);
- $temp_sku['sign_id'] = implode(':', array_column($temp_sku['attr_list'], 'attr_id'));
- $attr[] = $temp_sku;
- }
- $temp['attr'] = $attr;
- }
- $res = self::setData($temp);
- if ($res) {
- $success_counts += $is_attr == 1 ? count($temp['attr']) : 1;
- } else {
- $reason = self::getStaticError();
- if ($is_attr == 1) {
- foreach ($temp['attr'] as $temp_attr) {
- $temp_params = $data[$temp_attr['data_row_id']];
- $temp_params['reason'] = $reason;
- list($fail_arr, $fail_counts) = ImportFailLog::packFailArr($temp_params, $fail_arr, $fail_counts);
- }
- } else {
- $temp_params = $data[$temp['serial_number']];
- $temp_params['reason'] = $reason;
- list($fail_arr, $fail_counts) = ImportFailLog::packFailArr($temp_params, $fail_arr, $fail_counts);
- }
- }
- }
- $param['counts'] = $counts;
- $param['success_counts'] = $success_counts;
- $param['fail_counts'] = $fail_counts;
- $param['source'] = self::class;
- $param['mall_id'] = $params['mall_id'];
- $param['store_id'] = $params['store_id'];
- if ($sync == 0) {
- $param['fail_arr'] = $fail_arr;
- // 异步返回数据
- return $param;
- } else {
- $import_log_model = ImportLog::setData($param);
- if (!$import_log_model) throw new \Exception(ImportLog::getStaticError());
- if (!empty($fail_arr)) {
- $res = ImportFailLog::setData($fail_arr, $import_log_model->id);
- if (!$res) throw new \Exception(ImportFailLog::getStaticError());
- }
- }
- }
- /**
- * 异步批量导入商品
- * @param $params
- * @return false|int[]
- */
- 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['store_id'] = $params['store_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;
- }
- }
- /**
- * 异步执行
- * @param $params
- * @return void
- */
- public static function syncImportGoods($params)
- {
- try {
- if (empty($params['id'])) throw new Exception('缺少参数id');
- $model = ImportLog::findOne(['id' => $params['id']]);
- if (empty($model['upload_file'])) throw new Exception('缺少参数upload_file');
- $upload_file = $model['upload_file'];
- $mall_id = $model['mall_id'];
- $store_id = $model['store_id'];
- $cvsFile = fopen($upload_file, 'r'); //开始读取csv文件数据
- $i = 0;
- $head_list = GoodsImportEnum::HEAD_LIST;
- $head_list_fields = array_column($head_list, 'field');
- $rows = [];
- while ($fileData = fgetcsv($cvsFile)) {
- $i++;
- if ($i == 1) continue; //过滤表头
- $temp_row = [];
- foreach ($fileData as $k => $val) {
- $val = mb_convert_encoding(trim($val), "UTF-8", "GBK");
- foreach ($head_list_fields as $key => $field) {
- if ($k == $key) {
- $temp_row[$field] = $val;
- continue;
- }
- }
- }
- $rows[] = $temp_row;
- }
- $temp_rows = array_column($rows, null, 'serial_number');
- if (count($temp_rows) == count($rows)) {
- $result = self::handleImportData(['mall_id' => $mall_id,'store_id' => $store_id], $rows, 0);
- $model->counts = $result['counts'];
- $model->success_counts = $result['success_counts'];
- $model->fail_counts = $result['fail_counts'];
- } else {
- $model->counts = count($rows);
- $model->success_counts = 0;
- $model->fail_counts = $model->counts;
- $result = [];
- }
- if (!$model->save()) throw new \Exception($model->getErrorMessage());
- $fail_arr = $result['fail_arr'] ?? [];
- if (!empty($fail_arr)) {
- $res = ImportFailLog::setData($fail_arr, $model->id);
- if (!$res) throw new \Exception(ImportFailLog::getStaticError());
- }
- } catch (\Exception $e) {
- $msg = __METHOD__ . ' msg: ' . $e->getMessage();
- \Yii::error($msg);
- }
- }
- }
|