GoodsController.php 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917
  1. <?php
  2. namespace addons\Store\client\controllers;
  3. use addons\Coupon\common\models\AddonsCoupon;
  4. use addons\Store\common\enums\StoreEnum;
  5. use addons\Store\common\models\StoreCoupon;
  6. use addons\Store\common\models\StoreCouponGiveItemSetting;
  7. use addons\Store\common\models\StoreFreightRules;
  8. use addons\Store\common\models\StoreGoods;
  9. use addons\Store\common\models\StoreGoodsAttr;
  10. use addons\Store\common\models\StoreGoodsCateRelate;
  11. use addons\Store\common\models\StoreGoodsModel;
  12. use addons\Store\common\models\StoreSettings;
  13. use common\components\CsvExport;
  14. use common\enums\AddonsEnum;
  15. use common\enums\DownloadEnum;
  16. use common\enums\GoodsTypeEnum;
  17. use common\enums\import\GoodsImportEnum;
  18. use common\enums\RabbitMqEnum;
  19. use common\enums\StatusEnum;
  20. use common\enums\WhetherEnum;
  21. use common\globals\GlobalInvoke;
  22. use common\helpers\csv\CsvExportHelper;
  23. use common\helpers\TaskHelper;
  24. use common\logic\common\AddonsLimit;
  25. use common\models\common\ImportFailLog;
  26. use common\models\common\ImportLog;
  27. use common\models\common\Region;
  28. use common\models\goods\Goods;
  29. use common\models\goods\GoodsCateRelate;
  30. use common\models\mall\Mall;
  31. use common\models\mall\MallAddons;
  32. use common\models\user\UserLevel;
  33. use common\models\goods\GoodsAssociation;
  34. use PhpAmqpLib\Message\AMQPMessage;
  35. use common\helpers\StringHelper;
  36. use Yii;
  37. use addons\Store\common\models\Store;
  38. use addons\Store\common\services\SyncMallGoodsService;
  39. class GoodsController extends BaseController
  40. {
  41. public $enableCsrfValidation = false;
  42. /**
  43. * Renders the index view for the module
  44. * @return string
  45. */
  46. public function actionIndex()
  47. {
  48. if (\Yii::$app->request->isAjax) {
  49. if (\Yii::$app->request->isGet) {
  50. //商品列表筛选
  51. $get = Yii::$app->request->get();
  52. $rules = [
  53. [['goods_id', 'goods_type'], 'integer'],
  54. [['goods_name', 'sort_field'], 'string'],
  55. [['type'], 'in', 'range' => ['all', 'checking', 'onsale', 'offline', 'sell-out', 'stock-lack']],
  56. [['sort_type'], 'in', 'range' => ['asc', 'desc']],
  57. [['cats'], 'each', 'rule' => ['integer']],
  58. [['start', 'end'], 'datetime', 'format' => 'php:Y-m-d H:i:s']
  59. ];
  60. $res = Yii::$app->services->validate->validate($get, $rules);
  61. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  62. $where = [['g.mall_id' => $this->mall_id, 'g.store_id' => $this->store_id, 'g.status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]]];
  63. // 筛选
  64. isset($get['start']) && $where[] = ['>=', 'g.created_at', strtotime($get['start'])];
  65. isset($get['end']) && $where[] = ['<=', 'g.created_at', strtotime($get['end'])];
  66. isset($get['goods_name']) && $where[] = ['like', 'g.goods_name', '%' . trim($get['goods_name']) . '%', false];
  67. if(!empty($get['cats'])){
  68. $goods_cate_relate_list = StoreGoodsCateRelate::lists(['where'=>[['cate_id'=>$get['cats']]]]);
  69. $goods_ids = array_column($goods_cate_relate_list,'goods_id');
  70. $where[] = ['in', 'g.id', $goods_ids];
  71. }
  72. isset($get['goods_id']) && $where[] = ['=', 'g.id', $get['goods_id']];
  73. !empty($get['goods_type']) && $where[] = ['=', 'g.goods_type', $get['goods_type']];
  74. if (isset($get['type'])) {
  75. switch ($get['type']) {
  76. case 'checking':
  77. $where[] = ['=', 'g.check_status', 0];
  78. break;
  79. case 'onsale':
  80. $where[] = ['=', 'g.is_on_sale', WhetherEnum::ENABLED];
  81. $where[] = ['=', 'g.check_status', 1];
  82. $where[] = ['>', 'g.stock', 0];
  83. break;
  84. case 'offline':
  85. $where[] = ['=', 'g.is_on_sale', WhetherEnum::DISABLED];
  86. break;
  87. case 'sell-out':
  88. $where[] = ['=', 'g.stock', 0];
  89. break;
  90. case 'stock-lack':
  91. $where[] = new \yii\db\Expression('`stock` <= `stock_warning`');
  92. break;
  93. }
  94. }
  95. // with
  96. $with = ['cats', 'attr'];
  97. // 排序
  98. $sort = '';
  99. if (isset($get['sort_field']) && isset($get['sort_type'])) $sort = 'g.' . $get['sort_field'] . ' ' . $get['sort_type'];
  100. $sort = !empty($sort) ? $sort . ',g.sort ASC,g.id DESC' : 'g.sort ASC,g.id DESC';
  101. $params = array('alias' => 'g', 'where' => $where, 'with' => $with, 'limit' => 20, 'order' => $sort);
  102. $page_data = StoreGoods::listPage($params, false, true);
  103. if ($page_data === false) return $this->error(Goods::getStaticError());
  104. $platform_goods_cate = StoreGoods::getPlatformGoodsCate($this->mall_id);
  105. $page_data["export_list"] = Goods::fieldsList();
  106. if (!empty($page_data['list'])) {
  107. foreach ($page_data['list'] as &$item) {
  108. $addons_name = '';
  109. $item['addons_name'] = $addons_name;
  110. $item['show_sync_goods'] = 0;
  111. $cate_ids = array_column($item['cats'], 'id') ?? [];
  112. in_array($platform_goods_cate['id'], $cate_ids) && $item['show_sync_goods'] = 1;
  113. $item['option_limit'] = 0;
  114. if ($item['supplier_type'] == StoreEnum::SELF_MALL_WUZHOU) $item['option_limit'] = 1;
  115. }
  116. }
  117. // 是否需要设置支付成功后跳转
  118. $page_data['pay_success_jump'] = StatusEnum::DISABLED;
  119. if (MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_PAY_SUCCESS_JUMP)) {
  120. $pay_jump_config = \Yii::$app->services->setting->addons->get($this->mall_id,
  121. AddonsEnum::ADDONS_NAME_PAY_SUCCESS_JUMP, 'basic');
  122. if (!empty($pay_jump_config['is_enable'])) {
  123. $page_data['pay_success_jump'] = intval($pay_jump_config['is_enable_jump']);
  124. }
  125. }
  126. // 是否显示同步多商户商品按钮
  127. $is_sync_mchgoods_2store = isset(Yii::$app->params['is_sync_mchgoods_2store']) ? Yii::$app->params['is_sync_mchgoods_2store'] : false;
  128. $page_data['synchronize_goods_dialog'] = StatusEnum::DISABLED;
  129. if ($is_sync_mchgoods_2store && MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_MCH)) {
  130. $page_data['synchronize_goods_dialog'] = StatusEnum::ENABLED;
  131. }
  132. return $this->success('操作成功', $page_data);
  133. } else {
  134. // 商品操作
  135. $form = Yii::$app->request->post();
  136. $rules = [[['id'], 'required'], [['id'], 'integer']];
  137. switch ($form['type']) {
  138. case 'sort': //排序
  139. $rules[] = [['sort'], 'required'];
  140. break;
  141. case 'destroy': //删除
  142. $form['status'] = -1;
  143. $rules[] = [['status'], 'required'];
  144. break;
  145. case 'goods_name': //修改商品名称
  146. $rules[] = [['goods_name'], 'required'];
  147. break;
  148. case 'is_on_sale': //上下架
  149. $rules[] = [['is_on_sale'], 'required'];
  150. $rules[] = [['is_on_sale'], 'in', 'range' => [WhetherEnum::ENABLED, WhetherEnum::DISABLED]];
  151. break;
  152. }
  153. $res = Yii::$app->services->validate->validate($form, $rules);
  154. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  155. $form['mall_id'] = $this->mall_id;
  156. $goods_id = $form['id'];
  157. unset($form['id']);
  158. $res = StoreGoods::goodsHandle($goods_id, $form);
  159. if ($res === false) return $this->error(StoreGoods::getStaticError());
  160. //修改商品的规格
  161. if ($form['status']) {
  162. $attr_goods = StoreGoodsAttr::find()->where(['goods_id' => $goods_id])->all();
  163. foreach ($attr_goods as $model) {
  164. $model->status = $form['status'];
  165. $model->updated_at = time();
  166. $model->update(false);
  167. }
  168. }
  169. if ($form['status'] == -1) {
  170. // 五洲供应链商品删除
  171. SyncMallGoodsService::deleteGoods($goods_id, $this->mall_id);
  172. }
  173. return $this->success();
  174. }
  175. }
  176. return $this->render($this->action->id, ['pay_success_jump_component' =>
  177. MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_PAY_SUCCESS_JUMP)]);
  178. }
  179. /**
  180. * 商品编辑
  181. * @Author bing
  182. * @DateTime 2021-08-20 14:49:55
  183. * @return mixed
  184. * @copyright: Copyright (c) 2020 广东七件事集团
  185. */
  186. public function actionEdit()
  187. {
  188. $is_reserve_type = $this->reserveGoodsType();
  189. if (\Yii::$app->request->isAjax) {
  190. if (\Yii::$app->request->isGet) {
  191. // 反显商品信息
  192. $get = \Yii::$app->request->get();
  193. $res = Yii::$app->services->validate->validate($get, [[['id'], 'integer']]);
  194. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  195. $detail = isset($get['id']) ? StoreGoods::getOne([['id' => $get['id'], 'mall_id' => $this->mall_id,
  196. 'store_id' => $this->store_id]], true, ['cats', 'attr', 'extra', 'reserve', 'reserve.skus', 'reserve.skus.times', 'reserve.skus.times.timeSpec']) : [];
  197. $detail['freight_type'] = !empty($detail['freight_type']) ? explode(',', $detail['freight_type']) : [];
  198. $detail['services'] = !empty($detail['services']) ? explode(',', $detail['services']) : [];
  199. $detail['labels'] = !empty($detail['labels']) ? explode(',', $detail['labels']) : [];
  200. $detail['attr_groups'] = !empty($detail['attr_groups']) ? json_decode($detail['attr_groups'], true) : [];
  201. $detail['bannar_pic'] = !empty($detail['bannar_pic']) ? json_decode($detail['bannar_pic'], true) : [];
  202. $detail['attr_groups_format'] = !empty($detail['attr_groups_format']) ? json_decode($detail['attr_groups_format'], true) : [];
  203. $detail['area_limit'] = !empty($detail['area_limit']) ? json_decode($detail['area_limit'], true) : [];
  204. $detail['cats'] = $detail['cats'] ?? [];
  205. $detail['attr'] = StoreGoodsAttr::formatFormAttr($detail['attr'] ?? [], $detail['attr_groups_format']);
  206. $detail['goods_weight'] = isset($detail['attr'][0]['weight']) ? $detail['attr'][0]['weight'] : 0;
  207. $detail['package_data'] = !empty($detail['package_data']) ? json_decode($detail['package_data'], true) : [];
  208. $default_goods_style = \Yii::$app->services->setting->addons->get($this->mall_id, StoreEnum::ADDONS_NAME, 'decoration');
  209. $detail['show_style'] = !empty($detail['show_style']) ? $detail['show_style'] : ($default_goods_style['default_goods_style'] ?? 1);
  210. if (isset($detail['extra'])) {
  211. $extra = &$detail['extra'];
  212. $extra['score_give_setting'] = !empty($extra['score_give_setting']) ? json_decode($extra['score_give_setting'], true) : [];
  213. $extra['score_deduct_setting'] = !empty($extra['score_deduct_setting']) ? json_decode($extra['score_deduct_setting'], true) : [];
  214. $extra['currency_deduct_setting'] = !empty($extra['currency_deduct_setting']) ? json_decode($extra['currency_deduct_setting'], true) : [];
  215. $extra['member_price_setting'] = !empty($extra['member_price_setting']) ? json_decode($extra['member_price_setting'], true) : [];
  216. $extra['member_buy_limit_setting'] = !empty($extra['member_buy_limit_setting']) ? json_decode($extra['member_buy_limit_setting'], true) : [];
  217. }
  218. if (!isset($extra['score_give_setting']['settlement'])) $extra['score_give_setting']['settlement'] = 1;
  219. if(!isset($extra['score_give_setting']['condition']))$extra['score_give_setting']['condition'] = 0;
  220. $platform_score_give_setting = \Yii::$app->services->setting->addons->get($this->mall_id, StoreEnum::ADDONS_NAME, 'scoreGive.score_give_setting');
  221. $extra['platform_score_give_setting'] = !empty($platform_score_give_setting) ? json_decode($platform_score_give_setting, true) : [];
  222. // 预约商品字段处理
  223. if (!empty($detail['reserve'])) {
  224. $reserve = &$detail['reserve'];
  225. !empty($reserve['reserve_date']) && $reserve['reserve_date'] = json_decode($reserve['reserve_date'], true);
  226. !empty($reserve['reserve_time_slot']) && $reserve['reserve_time_slot'] = json_decode($reserve['reserve_time_slot'], true);
  227. !empty($reserve['reserve_time_slot_price']) && $reserve['reserve_time_slot_price'] = json_decode($reserve['reserve_time_slot_price'], true);
  228. !empty($reserve['service_type']) && $reserve['service_type'] = json_decode($reserve['service_type'], true);
  229. !empty($reserve['reserve_week']) && $reserve['reserve_week'] = explode(',',$reserve['reserve_week']);
  230. if (!empty($reserve['skus'])) {
  231. foreach($reserve['skus'] as &$sku){
  232. $signId = $sku['sign_id'];
  233. $sku['attr_list'] = $detail['attr_groups_format'][$signId] ?? [];
  234. !empty($sku['reserve_date']) && $sku['reserve_date'] = json_decode($sku['reserve_date'], true);
  235. !empty($sku['reserve_week']) && $sku['reserve_week'] = explode(',',$sku['reserve_week']);
  236. !empty($sku['reserve_time_slot']) && $sku['reserve_time_slot'] = json_decode($sku['reserve_time_slot'], true);
  237. !empty($sku['reserve_time_slot_price']) && $sku['reserve_time_slot_price'] = json_decode($sku['reserve_time_slot_price'], true);
  238. }
  239. }
  240. $reserve['cancel_rule'] = $reserve['cancel_rule'] ? json_decode($reserve['cancel_rule'], true) : [];
  241. $reserve['appointments_number'] = !empty($reserve['appointments_number'])?$reserve['appointments_number']:'';
  242. }
  243. // 用户等级
  244. // 用户等级
  245. $levels = UserLevel::getUserLevel([['mall_id' => $this->mall_id], ['status' => StatusEnum::ENABLED]], [], true, 'id,level,name');
  246. $levels = array_merge([['level' => 0, 'name' => '普通用户']], $levels);
  247. // 运费模板
  248. $cond = [['mall_id' => $this->mall_id, 'store_id' => $this->store_id]];
  249. $freight_rules = StoreFreightRules::getFreightRules($cond, [], true, 'id,name');
  250. // 商品类型
  251. $goods_type = GoodsTypeEnum::getGoodsType();
  252. // 判断是否需要移除预约商品
  253. if ($is_reserve_type == StatusEnum::DELETE) {
  254. unset($goods_type[GoodsTypeEnum::GoodsTypeReserved]);
  255. }
  256. unset($detail['attr_groups_format']);
  257. $where = [
  258. ['mall_id' => $this->mall_id],
  259. ['store_id' => $this->store_id],
  260. ['item_id' => $get['id']],
  261. ['item_type' => 'goods'],
  262. ['status' => StatusEnum::ENABLED]
  263. ];
  264. $store_coupon_item_setting = StoreCouponGiveItemSetting::getOne($where, true, ['detail' => function ($query) {
  265. $query->where(['status' => StatusEnum::ENABLED]);
  266. }]);
  267. $detail['coupon_is_enable'] = $store_coupon_item_setting['is_enable'] ?? 0;
  268. if (!empty($store_coupon_item_setting['detail'])) {
  269. $coupon_ids = $store_coupon_ids = [];
  270. foreach ($store_coupon_item_setting['detail'] as $item) {
  271. $item['from_type'] == 1 ? $coupon_ids[] = $item['coupon_id'] : $store_coupon_ids[] = $item['coupon_id'];
  272. }
  273. $select = 'id,name,type,discount,sub_price';
  274. $coupon_arr[2] = StoreCoupon::lists(['where' => [['id' => $store_coupon_ids]], 'select' => $select, 'index' => 'id']);
  275. $is_install = MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_COUPON);
  276. if ($is_install) $coupon_arr[1] = AddonsCoupon::lists(['where' => [['id' => $coupon_ids]], 'select' => $select, 'index' => 'id']);
  277. foreach ($store_coupon_item_setting['detail'] as &$item) {
  278. $item['type_text'] = $item['from_type'] == 1 ? '平台优惠券' : '门店优惠券';
  279. $item['discount_method'] = $item['name'] = $item['total_count'] = '';
  280. if (!empty($coupon_arr[$item['from_type']])) {
  281. $coupons = $coupon_arr[$item['from_type']];
  282. $res = StoreCoupon::formatData($coupons[$item['coupon_id']]);
  283. $item = array_merge($item, $res);
  284. }
  285. }
  286. }
  287. $goods_association = GoodsAssociation::getOne([['goods_id'=>$detail['id']], ['store_id' => $this->store_id], ['mall_id' => $this->mall_id],['status'=>StatusEnum::ENABLED]],true);
  288. $extra1_goods_list = [];
  289. $extra2_goods_list = [];
  290. $extra1_goods_id = [];
  291. $extra2_goods_id = [];
  292. if($goods_association){
  293. $extra1_goods_id = json_decode($goods_association['extra1_goods_id'],true);
  294. $extra2_goods_id = json_decode($goods_association['extra2_goods_id'],true);
  295. $extra1_goods_list = StoreGoods::lists(['where'=>[['id'=>$extra1_goods_id]],'select'=>'id as goods_id,price,status,stock as goods_stock,goods_name,cover_pic,store_id'],true);
  296. $extra2_goods_list = StoreGoods::lists(['where'=>[['id'=>$extra2_goods_id]],'select'=>'id as goods_id,price,status,stock as goods_stock,goods_name,cover_pic,store_id'],true);
  297. }
  298. $detail['extra1_goods_id'] = $extra1_goods_id;
  299. $detail['extra2_goods_id'] = $extra2_goods_id;
  300. $detail['coupon_selection'] = $store_coupon_item_setting['detail'] ?? [];
  301. $detail['store_id'] = $detail['store_id'] ?? $this->store_id;
  302. $score_give_is_store_alone = \Yii::$app->services->setting->addons->get($this->mall_id, StoreEnum::ADDONS_NAME, 'scoreGive.score_give_is_store_alone');
  303. $score_give_is_store_alone = $score_give_is_store_alone ?? 0;
  304. $storeDetail = Store::getOne([['id' => $this->store_id], ['mall_id' => $this->mall_id]], true);
  305. $detail['store_freight_type'] = json_decode($storeDetail['freight_type'],true);
  306. if (!empty($get['id']) && !empty($detail['store_freight_type'])) {
  307. foreach ($detail['freight_type'] as $key => $itemFreight) { // 因为商品优惠券使用了&$item 所以这里不能在重复使用修改为$itemFreight
  308. if ($itemFreight == 1 && $detail['store_freight_type']['express_delivery'] == 0) { // 快递发送
  309. $detail['store_freight_type']['express_delivery'] = 1;
  310. } else if ($itemFreight == 2 && $detail['store_freight_type']['self_mention'] == 0) { // 自提
  311. $detail['store_freight_type']['self_mention'] = 1;
  312. } else if ($itemFreight == 3 && $detail['store_freight_type']['merchant_distribution'] == 0) { // 同城配送
  313. $detail['store_freight_type']['merchant_distribution'] = 1;
  314. }
  315. }
  316. }
  317. return $this->success('操作成功', compact('detail', 'levels', 'goods_type', 'freight_rules','extra1_goods_list','extra2_goods_list','score_give_is_store_alone'));
  318. } else {
  319. // 编辑商品
  320. $form = json_decode(Yii::$app->request->post('form'), true);
  321. $form['mall_id'] = $this->mall_id;
  322. $form['store_id'] = $this->store_id;
  323. $form['supplier_type'] = StoreEnum::SUPPLIER_SELF;
  324. $form['supplier_id'] = $this->store_id;
  325. $form['supplier_goods_id'] = 0;
  326. if (empty($form['check_status'])) {
  327. $form['check_status'] = 0;
  328. $form['is_on_sale'] = 0;
  329. } else {
  330. if ($form['check_status'] == 2) {
  331. $form['check_status'] = 0;
  332. }
  333. }
  334. if ($form['goods_type'] == 1 && empty($form['freight_type'])) {
  335. return $this->error('请选择物流方式');
  336. }
  337. $basic = \Yii::$app->services->setting->addons->get($this->mall_id, StoreEnum::ADDONS_NAME, 'basic');
  338. if (empty($basic['goods_auth'])) {
  339. $form['check_status'] = 1;
  340. } else {
  341. $form['check_status'] = 0; // 开启了审核,保存都要重新审核
  342. }
  343. $res = StoreGoods::setData($form);
  344. if ($res === false) {
  345. return $this->error(StoreGoods::getStaticError());
  346. }
  347. return $this->success('操作成功');
  348. }
  349. }
  350. // 公共调用
  351. $install_addons = GlobalInvoke::exec(GlobalInvoke::GOODS_DETAIL_EDIT, $this->mall_id, [
  352. 'type' => 'show_store_component',
  353. 'mall_id' => $this->mall_id,
  354. ]);
  355. foreach ($install_addons as $key => $val) {
  356. if (!is_array($val)) {
  357. unset($install_addons[$key]);
  358. }
  359. $component = $val['component'] ?? '';
  360. if ($component != 'com-higo') {
  361. unset($install_addons[$key]);
  362. }
  363. }
  364. return $this->render($this->action->id, ['components' => $install_addons, 'is_reserve_type' => $is_reserve_type, 'store_id' => $this->store_id]);
  365. }
  366. public function actionSearch()
  367. {
  368. if (\Yii::$app->request->isAjax) {
  369. if (\Yii::$app->request->isGet) {
  370. //商品列表筛选
  371. $get = Yii::$app->request->get();
  372. $rules = [
  373. [['keyword'], 'string'],
  374. [['store_id', 'goods_id'], 'safe']
  375. ];
  376. $res = Yii::$app->services->validate->validate($get, $rules);
  377. if ($res === false)
  378. return $this->error(Yii::$app->services->validate->getErrorMessage());
  379. $where = [['mall_id' => $this->mall_id, 'store_id' => $this->store_id, 'is_on_sale' => 1,'check_status'=>1, 'status' => [StatusEnum::ENABLED]]];
  380. if (isset($get['goods_id']) && !empty($get['goods_id'])) {
  381. $where[] = ['!=', 'id', $get['goods_id']];
  382. }
  383. isset($get['keyword']) && $where[] = ['or', ['like', 'goods_name', $get['keyword']], ['=', 'id', $get['keyword']]];
  384. $sort = !empty($sort) ? $sort . ',sort ASC,id DESC' : 'sort ASC,id DESC';
  385. $params = array('where' => $where, 'limit' => 15, 'order' => $sort, 'group' => 'id');
  386. $page_data = StoreGoods::listPage($params, false, true);
  387. if ($page_data === false)
  388. return $this->error(StoreGoods::getStaticError());
  389. return $this->success('操作成功', $page_data);
  390. }
  391. }
  392. return $this->render($this->action->id);
  393. }
  394. /**
  395. * @return void
  396. */
  397. public function actionImportStoreGoods()
  398. {
  399. set_time_limit(0);
  400. if (\Yii::$app->request->isAjax) {
  401. $params = \Yii::$app->request->post();
  402. $res = \Yii::$app->services->validate->validate($params, [
  403. [['current_num'], 'required'],
  404. [['file'], 'file', 'extensions' => ['csv']],
  405. [['file_path'], 'string'],
  406. [['sync'], 'safe'],
  407. ]);
  408. if ($res === false)
  409. return $this->error(Yii::$app->services->validate->getErrorMessage());
  410. $params['mall_id'] = $this->mall_id;
  411. $params['store_id'] = $this->store_id;
  412. if (!empty($params['sync'])) {
  413. $res = StoreGoods::importGoodsSync($params);
  414. } else {
  415. $res = StoreGoods::importGoods($params);
  416. }
  417. if ($res === false)
  418. return $this->error(StoreGoods::getStaticError());
  419. if (empty($res['fail_counts']))
  420. return $this->success('操作成功', $res);
  421. if (!empty($res['fail_counts']))
  422. return $this->error('导入失败' . $res['fail_counts'] . '条');
  423. } else {
  424. return $this->render($this->action->id);
  425. }
  426. }
  427. /**
  428. * 商品导出
  429. * @return void
  430. */
  431. public function actionExportExcel()
  432. {
  433. if (\Yii::$app->request->isPost) {
  434. $post = \Yii::$app->request->post();
  435. $post['mall_id'] = $this->mall_id;
  436. $post['store_id'] = $this->store_id;
  437. $filename = '商品列表-' . date('YmdHis') . '_' . rand(10000, 99999);
  438. $res = CsvExportHelper::exportDownLoadCenter($this->mall_id, $filename, DownloadEnum::TYPE_GOODS, StoreGoods::class, 'exportHandle', $post,0,$this->store_id);
  439. if ($res === false)
  440. return $this->error('加入导出任务失败' . CsvExportHelper::getStaticError());
  441. return $this->success('添加导出任务成功,任务完成后请在下载中心进行下载!');
  442. }
  443. }
  444. /**
  445. * 预约商品
  446. * @return int -1两个插件都没有安装,0仅限预约商品,1仅限预约服务,2商品/服务
  447. */
  448. protected function reserveGoodsType()
  449. {
  450. // 是否有安装家政服务
  451. $is_install_home_making = MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_HOME_MAKING);
  452. // 是否有安装预约服务
  453. $is_install_reserve_service = MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_RESERVATION_SERVICE);
  454. $diff = $is_install_home_making <=> $is_install_reserve_service;
  455. if ($diff < 0) { // 如果没有安装预约服务
  456. return 1;
  457. } else if ($diff == 0 && $is_install_home_making == 0) { // 如果两个都没有安装
  458. return -1;
  459. } else if ($diff == 0) { // 两个都有安装
  460. return 2;
  461. } else { // 如果仅安装了家政服务
  462. return 0;
  463. }
  464. }
  465. /**
  466. * 选品中心
  467. * @Author bing
  468. * @DateTime 2022-04-26 18:05:56
  469. * @return void
  470. * @copyright: Copyright (c) 2022 广东七件事集团
  471. */
  472. public function actionSupply()
  473. {
  474. return $this->render($this->action->id);
  475. }
  476. public function actionGoodsModel()
  477. {
  478. $basic = \Yii::$app->services->setting->addons->get($this->mall_id, StoreEnum::ADDONS_NAME, 'basic');
  479. $addons_setting = AddonsLimit::getGlobalSetting($this->mall_id);
  480. $addons_arr = [];
  481. if (!empty($basic['store_agent_status'])) $addons_arr[] = AddonsEnum::ADDONS_NAME_AGENT;
  482. if (!empty($basic['store_area_status'])) $addons_arr[] = AddonsEnum::ADDONS_NAME_AREA;
  483. if (!empty($basic['store_distribution_status'])) $addons_arr[] = AddonsEnum::ADDONS_NAME_DISTRIBUTION;
  484. if(!empty($basic['double_copy_status'])) $addons_arr[] = AddonsEnum::ADDONS_NAME_DOUBLE_COPY;
  485. if(!empty($basic['store_rebate_status'])) $addons_arr[] = AddonsEnum::ADDONS_NAME_REBATE;
  486. if ($addons_setting) {
  487. foreach ($addons_setting as $key => $val) {
  488. if (!in_array($key, $addons_arr)) unset($addons_setting[$key]);
  489. }
  490. } else {
  491. $addons_setting = [];
  492. }
  493. //门店存在的插件
  494. if (MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_STORE_BOSS_AGENT)){
  495. $setting = \Yii::$app->services->setting->addons->get($this->mall_id, AddonsEnum::ADDONS_NAME_STORE_BOSS_AGENT, 'basic');
  496. if (!empty($setting['is_enable'])){
  497. $addons_setting[AddonsEnum::ADDONS_NAME_STORE_BOSS_AGENT] = [
  498. 'components' => 'com-' . StringHelper::toUnderScore(AddonsEnum::ADDONS_NAME_STORE_BOSS_AGENT),
  499. 'class' => '',
  500. ];
  501. $addons_arr[] = AddonsEnum::ADDONS_NAME_STORE_BOSS_AGENT;
  502. }
  503. }
  504. if (\Yii::$app->request->isAjax) {
  505. if (\Yii::$app->request->isGet) {
  506. // 商品列表筛选
  507. $params = Yii::$app->request->get();
  508. $res = Yii::$app->services->validate->validate($params, [[['id'], 'required'], [['id'], 'integer']]);
  509. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  510. // 获取商品详情
  511. $detail = StoreGoods::getOne([['id' => $params['id'], 'mall_id' => $this->mall_id, 'store_id' => $this->store_id]], true, ['attr']);
  512. $goods_model = StoreGoodsModel::getOne([['goods_id' => $params['id'], 'mall_id' => $this->mall_id, 'store_id' => $this->store_id]], true);
  513. $setting = [];
  514. if (!empty($goods_model['content'])) {
  515. $content = json_decode($goods_model['content'], true);
  516. foreach ($content as $key => $item) {
  517. if (in_array($key, $addons_arr)) {
  518. $setting[$key] = json_decode($item, true);
  519. }
  520. }
  521. }
  522. // 获取等级
  523. $level_params = ['where' => [['=', 'mall_id', $this->mall_id], ['=', 'status', StatusEnum::ENABLED]], 'select' => 'level,name'];
  524. $level_params['mall_id'] = $this->mall_id;
  525. $level = GlobalInvoke::exec(GlobalInvoke::GOODS_MODEL_LEVEL, $this->mall_id, $level_params);
  526. $commission_type_map = GoodsTypeEnum::getCommissionTypeMap($this->mall_id);
  527. unset($commission_type_map['digital']);
  528. // 商品支持的插件分佣币种
  529. // $addons_commission_type = GlobalInvoke::exec(GlobalInvoke::INVOKE_COMMISSION_TYPE, $this->mall_id, ['mall_id' => $this->mall_id]);
  530. // $addons_commission_type = [];
  531. // foreach ($addons_commission_type as $type) {
  532. // $commission_type_map = array_merge($commission_type_map, array_column($type, 'label', 'name'));
  533. // }
  534. return $this->success('操作成功', compact('detail', 'level', 'setting', 'commission_type_map'));
  535. } else {
  536. $store_setting = StoreSettings::findOne(['store_id'=>$this->store_id,'mall_id'=>$this->mall_id, 'status' => StatusEnum::ENABLED]);
  537. if(!empty($store_setting)){
  538. if($store_setting['store_settle_type']!=3 && $store_setting['store_settle_type']!=4){
  539. if(empty($store_setting['is_allow_editing'])){
  540. return $this->error('分佣由平台承担,门店无权编辑');
  541. }
  542. }
  543. }else{
  544. if($basic['settle_type']!=3 && $basic['settle_type']!=4){
  545. return $this->error('分佣由平台承担,门店无权编辑');
  546. }
  547. }
  548. $params = Yii::$app->request->post('form');
  549. $res = Yii::$app->services->validate->validate($params, [
  550. [['goods_id'], 'required'],
  551. [['goods_id'], 'integer'],
  552. [array_keys($addons_setting), 'string']
  553. ]);
  554. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  555. try {
  556. $param = [
  557. 'mall_id' => $this->mall_id,
  558. 'store_id' => $this->store_id,
  559. 'goods_id' => $params['goods_id'],
  560. 'content' => json_encode($params),
  561. ];
  562. $res = StoreGoodsModel::setData($param);
  563. if ($res === false) return $this->error(StoreGoodsModel::getStaticError());
  564. return $this->success("保存成功");
  565. } catch (\Exception $e) {
  566. return $this->error("保存失败,msg=" . $e->getMessage());
  567. }
  568. }
  569. }
  570. return $this->render($this->action->id, ['addons_setting' => $addons_setting]);
  571. }
  572. public function actionMutipleOff()
  573. {
  574. if (!\Yii::$app->request->isPost) {
  575. return $this->error('请求方式错误');
  576. }
  577. $good_ids = \Yii::$app->request->post('good_ids');
  578. if (empty($good_ids) || !is_array($good_ids)) {
  579. return $this->error('参数错误');
  580. }
  581. if (empty($good_ids)) {
  582. return $this->success('操作成功');
  583. }
  584. $res = StoreGoods::updateAll(
  585. [
  586. 'is_on_sale' => 0,
  587. 'updated_at' => time(),
  588. 'check_status' => StoreEnum::CHECK_WAITING
  589. ],
  590. [
  591. 'mall_id' => $this->mall_id,
  592. 'store_id' => $this->store_id,
  593. 'id' => $good_ids
  594. ]
  595. );
  596. if (!$res) {
  597. return $this->error('操作失败:' . StoreGoods::getStaticError());
  598. }
  599. return $this->success('操作成功');
  600. }
  601. public function actionMutipleOn()
  602. {
  603. if (!\Yii::$app->request->isPost) {
  604. return $this->error('请求方式错误');
  605. }
  606. $good_ids = \Yii::$app->request->post('good_ids');
  607. if (empty($good_ids) || !is_array($good_ids)) {
  608. return $this->error('参数错误');
  609. }
  610. if (empty($good_ids)) {
  611. return $this->success('操作成功');
  612. }
  613. $res = StoreGoods::updateAll(
  614. [
  615. 'is_on_sale' => 1,
  616. 'updated_at' => time(),
  617. ],
  618. [
  619. 'mall_id' => $this->mall_id,
  620. 'store_id' => $this->store_id,
  621. 'id' => $good_ids
  622. ]
  623. );
  624. if (!$res) {
  625. return $this->error('操作失败:' . StoreGoods::getStaticError());
  626. }
  627. return $this->success('操作成功');
  628. }
  629. public function actionGetList()
  630. {
  631. $where=[];
  632. $where[]=['=','store_id',$this->store_id];
  633. $where[]=['=','mall_id',$this->mall_id];
  634. $where[]=['=','status',1];
  635. $with = ['detail'];
  636. $order = "id desc";
  637. $params = [
  638. 'select' => '*',
  639. 'where' => $where,
  640. 'order' => 'id asc',
  641. 'page' => 1,
  642. 'limit' => 10,
  643. ];
  644. $goodsLists = StoreGoods::listPage($params);
  645. return $this->success('返回成功', $goodsLists);
  646. }
  647. public function actionIsRecommend()
  648. {
  649. if (\Yii::$app->request->isAjax) {
  650. $params = Yii::$app->request->post();
  651. $rules = [[['id'], 'required'], [['id'], 'integer']];
  652. $rules[] = [['is_recommend'], 'required'];
  653. $rules[] = [['is_recommend'], 'in', 'range' => [0, 1]];
  654. $res = Yii::$app->services->validate->validate($params, $rules);
  655. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  656. $params['mall_id'] = $this->mall_id;
  657. // $params['store_id'] = $this->admin->store_id;
  658. try {
  659. $recommend_nums = \Yii::$app->services->setting->addons->get($params['mall_id'], StoreEnum::ADDONS_NAME, 'basic.recommend_nums');
  660. if (empty($recommend_nums)) throw new \Exception('允许推荐商品数为0');
  661. if ($params['is_recommend'] == 1) {
  662. $counts = StoreGoods::find()->where(['store_id' => $params['store_id'], 'mall_id' => $params['mall_id'], 'status' => StatusEnum::ENABLED, 'is_recommend' => 1])->count();
  663. if ($counts >= $recommend_nums) throw new \Exception('允许推荐商品数为' . $recommend_nums);
  664. $goods = StoreGoods::findOne(['id'=>$params['id']]);
  665. if(empty($goods)) throw new \Exception('商品不存在');
  666. // if(empty($goods->is_on_sale)) throw new \Exception('商品未上架');
  667. // if($goods->check_status!=1) throw new \Exception('只有审核通过的商品,才允许设置成推荐商品');
  668. }
  669. $goods_id = $params['id'];
  670. unset($params['id']);
  671. $res = StoreGoods::goodsHandle($goods_id, $params);
  672. if ($res === false) throw new \Exception(StoreGoods::getStaticError());
  673. return $this->success();
  674. }catch (\Exception $e){
  675. return $this->error($e->getMessage());
  676. }
  677. }
  678. }
  679. public function actionSyncGoodsList()
  680. {
  681. if (\Yii::$app->request->isAjax && \Yii::$app->request->isGet) {
  682. $params = Yii::$app->request->get();
  683. $mall_id = $params['mall_id'];
  684. $goods_id = $params['goods_id'];
  685. $name = $params['name'];
  686. $cats = $params['cats'];
  687. $where = [
  688. ['g.is_on_sale' => StatusEnum::ENABLED],
  689. ['g.status' => StatusEnum::ENABLED],
  690. ['g.check_status' => StatusEnum::ENABLED],
  691. ];
  692. $mall_list = Mall::getEnableMallList();
  693. $mall_list = array_column($mall_list, null, 'id');
  694. $mall_ids = array_column($mall_list, 'id') ?? [];
  695. if(!empty($mall_ids) && $mall_id > 0){
  696. $mall_ids = $mall_id;
  697. $where[] = ['g.mall_id' => $mall_ids];
  698. if(!empty($cats)){
  699. $goods_cate_relate = GoodsCateRelate::lists([
  700. 'where' => [
  701. ['cate_id' => $cats]
  702. ],
  703. 'select' => 'goods_id'
  704. ]);
  705. $where[] = ['g.id' => array_column($goods_cate_relate, 'goods_id') ?? []];
  706. }
  707. }
  708. if(!empty($goods_id)){
  709. $search_goods = Goods::find()->where(['or', ['id' => $goods_id], ['like', 'goods_name', $goods_id]])
  710. ->andWhere(['is_on_sale' => StatusEnum::ENABLED, 'status' => StatusEnum::ENABLED, 'check_status' => StatusEnum::ENABLED])
  711. ->select('id')
  712. ->asArray()
  713. ->all();
  714. $where[] = ['g.id' => array_column($search_goods, 'id') ?? []];
  715. }
  716. $mch_where = [
  717. ['mall_id' => $mall_ids], ['status' => StatusEnum::ENABLED], ['check_status' => StatusEnum::ENABLED]
  718. ];
  719. /** @var \addons\Mch\common\models\Mch $mch_class */
  720. $mch_class = \addons\Mch\common\models\Mch::class;
  721. if(!empty($name)){
  722. $search_mch_ids = $mch_class::find()->where(['or', ['like', 'shop_owner', $name], ['like', 'store_name', $name]])
  723. ->select('id')->asArray()->all();
  724. $mch_where[] = ['id' => array_column($search_mch_ids, 'id') ?? []];
  725. }
  726. $mch_list = $mch_class::lists([
  727. 'where' => $mch_where,
  728. 'select' => 'id,shop_owner,store_name',
  729. 'index' => 'id'
  730. ]);
  731. $mch_ids = array_column($mch_list, 'id') ?? [];
  732. $where[] = ['g.mch_id' => $mch_ids];
  733. $joins = array(['LEFT JOIN', '{{%goods_cate_relate}} gcr', 'gcr.goods_id=g.id']);
  734. $goods_list = Goods::listPage([
  735. 'where' => $where,
  736. 'select' => 'g.id,g.mall_id,g.mch_id,g.goods_name,g.price',
  737. 'with' => [
  738. 'cats'
  739. ],
  740. 'join' => $joins,
  741. 'alias' => 'g',
  742. 'limit' => $params['limit'] ?? 10,
  743. 'order' => 'g.mall_id DESC'
  744. ]);
  745. if($goods_list === false) return $this->error(Goods::getStaticError());
  746. foreach($goods_list['list'] as &$goods){
  747. $goods['shop_owner'] = isset($mch_list[$goods['mch_id']]) ? $mch_list[$goods['mch_id']]['shop_owner'] : '-';
  748. $goods['store_name'] = isset($mch_list[$goods['mch_id']]) ? $mch_list[$goods['mch_id']]['store_name'] : '-';
  749. $goods['mall_name'] = isset($mall_list[$goods['mall_id']]) ? $mall_list[$goods['mall_id']]['name'] : '-';
  750. }
  751. unset($goods);
  752. return $this->success('请求成功',$goods_list);
  753. }
  754. }
  755. public function actionSyncGoodsStore()
  756. {
  757. try{
  758. $params = Yii::$app->request->post();
  759. $res = Yii::$app->services->validate->validate($params, [
  760. [['selected_goods_ids'], 'required'],
  761. [['selected_goods_ids'], 'safe']
  762. ]);
  763. if ($res === false) throw new \Exception(Yii::$app->services->validate->getErrorMessage());
  764. $params['store_id'] = $this->store_id;
  765. $params['mall_id'] = $this->mall_id;
  766. TaskHelper::pushTaskQueue(RabbitMqEnum::EXCHANGE_TASK,RabbitMqEnum::TASK_QUEUE,$params,StoreGoods::class,'syncMchGoods',function(AMQPMessage $message){
  767. // 生产错误
  768. Yii::error('发送异步任务失败');
  769. });
  770. return $this->success('同步成功');
  771. }catch(\Exception $e){
  772. return $this->error($e->getMessage());
  773. }
  774. }
  775. public function actionGetMallList()
  776. {
  777. if(\Yii::$app->request->isAjax && \Yii::$app->request->isGet){
  778. $mall_list = Mall::getEnableMallList();
  779. array_unshift($mall_list, ['id' => '', 'name' => '全部商城']);
  780. return $this->success('数据请求成功', $mall_list);
  781. }
  782. }
  783. /**
  784. * 获取地区
  785. * @return mixed|null
  786. */
  787. public function actionRegions()
  788. {
  789. $params = Yii::$app->request->get();
  790. $res = Yii::$app->services->validate->validate($params, [
  791. [['id'], 'integer'],
  792. [['id'], 'required'],
  793. ]);
  794. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  795. $regions = Region::find()
  796. ->select('id,name,lng,lat')
  797. ->asArray()
  798. ->where(['parent_id' => $params['id']])
  799. ->indexBy('id')
  800. ->all();
  801. return $this->success('获取成功', $regions);
  802. }
  803. /**
  804. * @Description: 根据地区id获取第一层子级地区信息列表
  805. * @Author: zhngsan
  806. * @DateTime 2023-02-08 11:22:11
  807. * @return mixed
  808. */
  809. public function actionGetRegions()
  810. {
  811. if (!\Yii::$app->request->isGet) {
  812. return $this->error('请求方式错误');
  813. }
  814. $region_id = \Yii::$app->request->get('region_id');
  815. if (empty($region_id)) {
  816. return $this->error('参数错误');
  817. }
  818. $region = Region::findOne($region_id);
  819. if (empty($region)) {
  820. return $this->error('地区信息未找到');
  821. }
  822. $region_list = Region::find()
  823. ->select('id,name,lng,lat')
  824. ->where(['parent_id' => $region->id])
  825. ->asArray()
  826. ->all();
  827. return $this->success('success', $region_list);
  828. }
  829. /**
  830. * 日志记录
  831. * @return mixed|null
  832. */
  833. public function actionGetGoodsImportLog()
  834. {
  835. $params = \Yii::$app->request->get();
  836. $params['where'] = [
  837. ['mall_id' => $this->mall_id],
  838. ['store_id' => $this->store_id],
  839. ['source' => StoreGoods::class]
  840. ];
  841. $params['order'] = 'id desc';
  842. $data = ImportLog::listPage($params, false, true);
  843. if (!empty($data['list'])) {
  844. foreach ($data['list'] as &$v) {
  845. $v['url'] = '';
  846. if ($v['fail_counts'])
  847. $v['url'] = \Yii::$app->urlManager->createUrl(['store/client/goods/export-fail', 'import_log_id' => $v['id']]);
  848. }
  849. }
  850. return $this->success('操作成功', $data);
  851. }
  852. /**
  853. * 导出失败日志
  854. */
  855. public function actionExportFail()
  856. {
  857. ImportFailLog::exportFailLog(\Yii::$app->request->get());
  858. }
  859. /**
  860. * 会员批量导入模板下载
  861. */
  862. public function actionGoodsBatchSendModel()
  863. {
  864. $csv = new CsvExport();
  865. $file_name = '商品批量导入模板-' . date('YmdHis', time());
  866. $head_list = array_column(GoodsImportEnum::HEAD_LIST, 'field_name');
  867. return $csv->export([], $head_list, $file_name);
  868. }
  869. }