CsGoodsController.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. <?php
  2. namespace addons\CloudStockTwo\api\modules\v1\controllers;
  3. use addons\CloudStockTwo\common\enums\CloudStockTwoEnum;
  4. use addons\CloudStockTwo\common\models\CloudStockTwoAgent;
  5. use addons\CloudStockTwo\common\models\CloudStockTwoAgentGoods;
  6. use addons\CloudStockTwo\common\models\CloudStockTwoAgentOrder;
  7. use addons\CloudStockTwo\common\models\CloudStockTwoDeductionDetail;
  8. use addons\CloudStockTwo\common\models\CloudStockTwoGoods;
  9. use addons\CloudStockTwo\common\models\CloudStockTwoGoodsStockLog;
  10. use addons\CloudStockTwo\common\models\CloudStockTwoIncreaseDetail;
  11. use common\enums\StatusEnum;
  12. use common\enums\AddonsEnum;
  13. use common\helpers\ArrayHelper;
  14. use common\models\goods\Goods;
  15. use common\models\user\User;
  16. use common\models\user\UserPartitionRelationship;
  17. class CsGoodsController extends BaseController
  18. {
  19. public $modelClass = '';
  20. /**
  21. * 不用进行登录验证的方法
  22. *
  23. * 例如: ['index', 'update', 'create', 'view', 'delete']
  24. * 默认全部需要验证
  25. *
  26. * @var array
  27. */
  28. protected $authOptional = [];
  29. /**
  30. * @name:
  31. * @msg: 我的库存列表
  32. * @param {*}
  33. * @return {*}
  34. */
  35. public function actionList()
  36. {
  37. if (!\Yii::$app->request->isGet) {
  38. return $this->error('请求方式错误');
  39. }
  40. $page = \Yii::$app->request->get('page', 1);
  41. $limit = \Yii::$app->request->get('limit', $this->pageSize);
  42. $wheres[] = ['mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED];
  43. $params = [
  44. 'select' => 'id,mall_id,goods_id,agent_price,created_at,agent_price',
  45. 'where' => $wheres,
  46. 'order' => 'created_at desc',
  47. 'page' => $page,
  48. 'limit' => $limit,
  49. ];
  50. $list = CloudStockTwoGoods::listPage($params);
  51. if (empty($list['list'])) {
  52. if (!is_array($list['list'])) return $this->error(CloudStockTwoAgentGoods::getStaticError());
  53. }
  54. $good_ids = array_column($list['list'], 'goods_id');
  55. $agent_goods = CloudStockTwoAgentGoods::find()
  56. ->select('user_id,goods_id,num as agent_stock')
  57. ->where(['mall_id' => $this->mall_id, 'user_id' => $this->user_id, 'status' => StatusEnum::ENABLED, 'goods_id' => $good_ids])
  58. ->asArray()
  59. ->indexBy('goods_id')
  60. ->all();
  61. $mall_goods = Goods::find()
  62. ->select('id,goods_name,price,cover_pic')
  63. ->where(['mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED, 'id' => $good_ids, 'is_on_sale' => 1, 'is_attr' => 0])
  64. ->asArray()
  65. ->indexBy('id')
  66. ->all();
  67. // dd($list['list'], $mall_goods);
  68. foreach ($list['list'] as $index => &$lv) {
  69. if (!empty($mall_goods[$lv['goods_id']])) {
  70. $mall_good = $mall_goods[$lv['goods_id']];
  71. } else {
  72. unset($list['list'][$index]);
  73. continue;
  74. }
  75. // 当前会员是否可以补货当前商品
  76. $rr = CloudStockTwoGoods::canFillGood($this->mall_id, $lv['goods_id'], $this->stock_agent->level, $this->user_id);
  77. if (false === $rr) {
  78. unset($list['list'][$index]);
  79. continue;
  80. }
  81. $price = $mall_good['price'] ?? 0;
  82. $agent_price = json_decode($lv['agent_price'],true);
  83. $agent_price = array_column($agent_price,null,'level');
  84. $replenish_price = 0;
  85. if(!empty($agent_price[$this->stock_agent->level])){
  86. $replenish_price = $agent_price[$this->stock_agent->level]['price'];
  87. }
  88. // 如果补货价格为0,前端不显示,不可以补货
  89. if ($replenish_price <= 0) {
  90. unset($list['list'][$index]);
  91. continue;
  92. }
  93. $lv['replenish_price'] = $replenish_price;
  94. $lv['goods_name'] = $mall_good['goods_name'] ?? '';
  95. $lv['cover_pic'] = $mall_good['cover_pic'] ?? '';
  96. // 平台价格,零售价
  97. $lv['pirce'] = $price;
  98. $lv['profit'] = bcsub($price, $replenish_price, 2);
  99. $lv['user_id'] = $this->user_id;
  100. if (!empty($agent_goods[$lv['goods_id']])) {
  101. $lv = array_merge($lv, $agent_goods[$lv['goods_id']]);
  102. }
  103. $lv['is_mine'] = 0;
  104. $lv['agent_stock'] = 0;
  105. if (isset($agent_goods[$lv['goods_id']])) {
  106. $lv['agent_stock'] = $agent_goods[$lv['goods_id']]['agent_stock'];
  107. if ($lv['agent_stock'] > 0) $lv['is_mine'] = 1;
  108. }
  109. unset($lv['agent_price']);
  110. }
  111. $list['list'] = array_values($list['list']);
  112. $total_num = CloudStockTwoAgentGoods::find()->where(['mall_id' => $this->mall_id, 'user_id' => $this->user_id, 'status' => StatusEnum::ENABLED])->sum('num');
  113. $all_stock = $total_num??0;
  114. $configs = \Yii::$app->services->setting->addons->get($this->mall_id, AddonsEnum::ADDONS_NAME_CLOUD_STOCK_TWO, 'basic');
  115. $is_enable_cloud = $configs['is_enable_cloud'] ?? 0;
  116. return $this->success('success', compact('list', 'all_stock','is_enable_cloud'));
  117. }
  118. /**
  119. * @name:
  120. * @msg: 库存明细
  121. * @param {integer} $goods_id 商品id
  122. * @param {string} $date 搜索日期
  123. * @param {string} $record_type 搜索的记录类型,add:库存增加明细;sub:库存减少明细
  124. * @return {*}
  125. */
  126. public function actionStockDetails()
  127. {
  128. if (!\Yii::$app->request->isGet) {
  129. return $this->error('请求方式错误');
  130. }
  131. $page = \Yii::$app->request->get('page', 1);
  132. $limit = \Yii::$app->request->get('limit', $this->pageSize);
  133. $goods_id = \Yii::$app->request->get('goods_id');
  134. $date = \Yii::$app->request->get('date');
  135. // 记录类型,add:库存增加;sub:库存减少
  136. $record_type = \Yii::$app->request->get('record_type');
  137. if (empty($record_type) || !in_array($record_type, ['add', 'sub'])) return $this->error('参数错误');
  138. $wheres[] = ['mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED];
  139. if (!empty($good_ids)) {
  140. $wheres[] = ['goods_id' => $goods_id];
  141. $goods = Goods::find()
  142. ->select('id,goods_name,price,cover_pic')
  143. ->where(['mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED, 'id' => $good_ids, 'is_on_sale' => 1, 'is_attr' => 0])
  144. ->asArray()
  145. ->indexBy('id')
  146. ->all();
  147. }
  148. if (!empty($date)) {
  149. $start_time = strtotime($date . ' 00:00:00');
  150. $end_time = strtotime($date . ' 23:59:59');
  151. $wheres[] = ['and', ['>=', 'created_at', $start_time], ['<=', 'created_at', $end_time]];
  152. }
  153. if ('add' == $record_type) {
  154. $details = CloudStockTwoIncreaseDetail::find()
  155. ->select('stock_log_id,num')
  156. ->where(['user_id' => $this->user_id, 'status' => StatusEnum::ENABLED])
  157. ->asArray()
  158. ->indexBy('stock_log_id')
  159. ->all();
  160. $log_ids = array_column($details, 'stock_log_id');
  161. } else {
  162. $details = CloudStockTwoDeductionDetail::find()
  163. ->select('stock_log_id,num')
  164. ->where(['user_id' => $this->user_id, 'status' => StatusEnum::ENABLED])
  165. ->asArray()
  166. ->indexBy('stock_log_id')
  167. ->all();
  168. $log_ids = array_column($details, 'stock_log_id');
  169. }
  170. $wheres[] = ['id' => $log_ids];
  171. $params = [
  172. 'select' => 'id,mall_id,goods_id,changes_dir,order_id,order_type,changes_type,num,created_at',
  173. 'where' => $wheres,
  174. 'order' => 'created_at desc',
  175. 'page' => $page,
  176. 'limit' => $limit
  177. ];
  178. $detail_list = CloudStockTwoGoodsStockLog::listPage($params);
  179. if (empty($detail_list['list'])) {
  180. if (!is_array($detail_list['list'])) return $this->error(CloudStockTwoAgentGoods::getStaticError());
  181. return $this->success('success', $detail_list);
  182. }
  183. if (empty($goods)) {
  184. $good_ids = array_column($detail_list['list'], 'goods_id');
  185. $goods = Goods::find()
  186. ->select('id,goods_name,price,cover_pic')
  187. ->where(['mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED, 'id' => $good_ids, 'is_on_sale' => 1, 'is_attr' => 0])
  188. ->asArray()
  189. ->indexBy('id')
  190. ->all();
  191. }
  192. foreach ($detail_list['list'] as &$list) {
  193. $good = $goods[$list['goods_id']] ?? [];
  194. $detail = $details[$list['id']] ?? [];
  195. $list['goods_name'] = $good['goods_name'] ?? '';
  196. $list['cover_pic'] = $good['cover_pic'] ?? '';
  197. $list['price'] = $good['price'] ?? 0;
  198. switch ($list['changes_type']) {
  199. // 上级补货数量
  200. case CloudStockTwoEnum::STOCK_CHANGE_TYPE100:
  201. if (!isset($list['replenish_num'])) $list['replenish_num'] = 0;
  202. $list['replenish_num'] += $detail['num'] ?? 0;
  203. break;
  204. // 上级配货数量
  205. case CloudStockTwoEnum::STOCK_CHANGE_TYPE101:
  206. if (!isset($list['prepare_num'])) $list['prepare_num'] = 0;
  207. $list['prepare_num'] += $detail['num'] ?? 0;
  208. break;
  209. // 退货退库存数量
  210. case CloudStockTwoEnum::STOCK_CHANGE_TYPE102:
  211. if (!isset($list['refund_num'])) $list['refund_num'] = 0;
  212. $list['refund_num'] += $detail['num'] ?? 0;
  213. break;
  214. // 系统添加数量
  215. case CloudStockTwoEnum::STOCK_CHANGE_TYPE103:
  216. if (!isset($list['sys_add_num'])) $list['sys_add_num'] = 0;
  217. $list['sys_add_num'] += $detail['num'] ?? 0;
  218. break;
  219. // 平台补货赠送数量
  220. case CloudStockTwoEnum::STOCK_CHANGE_TYPE104:
  221. if (!isset($list['platfrom_give_num'])) $list['platfrom_give_num'] = 0;
  222. $list['platfrom_give_num'] += $detail['num'] ?? 0;
  223. break;
  224. // 购买礼包赠送数量
  225. case CloudStockTwoEnum::STOCK_CHANGE_TYPE105:
  226. if (!isset($list['buy_gift_give_num'])) $list['buy_gift_give_num'] = 0;
  227. $list['buy_gift_give_num'] += $detail['num'] ?? 0;
  228. break;
  229. // 会员买货数量
  230. case CloudStockTwoEnum::STOCK_CHANGE_TYPE200:
  231. if (!isset($list['member_buy_num'])) $list['member_buy_num'] = 0;
  232. $list['member_buy_num'] += $detail['num'] ?? 0;
  233. break;
  234. // 给下级配货数量
  235. case CloudStockTwoEnum::STOCK_CHANGE_TYPE201:
  236. if (!isset($list['issue_num'])) $list['issue_num'] = 0;
  237. $list['issue_num'] += $detail['num'] ?? 0;
  238. break;
  239. // 下级向自己补货数量
  240. case CloudStockTwoEnum::STOCK_CHANGE_TYPE202:
  241. if (!isset($list['sub_user_replenish_num'])) $list['sub_user_replenish_num'] = 0;
  242. $list['sub_user_replenish_num'] += $detail['num'] ?? 0;
  243. break;
  244. // 自提货到线下数量
  245. case CloudStockTwoEnum::STOCK_CHANGE_TYPE203:
  246. if (!isset($list['pick_to_offline_num'])) $list['pick_to_offline_num'] = 0;
  247. $list['pick_to_offline_num'] += $detail['num'] ?? 0;
  248. break;
  249. // 系统扣减数量
  250. case CloudStockTwoEnum::STOCK_CHANGE_TYPE204:
  251. if (!isset($list['sys_sub_num'])) $list['sys_sub_num'] = 0;
  252. $list['sys_sub_num'] += $detail['num'] ?? 0;
  253. break;
  254. default:
  255. break;
  256. }
  257. }
  258. $user = ArrayHelper::toArray($this->stock_agent->user);
  259. $stock_change_type_map = CloudStockTwoEnum::getStockChangeTypeMap();
  260. $stock_change_dir_map = CloudStockTwoEnum::getStockChangeDirMap();
  261. return $this->success('success', compact('detail_list', 'user', 'stock_change_type_map', 'stock_change_dir_map'));
  262. }
  263. public function actionStockDetail()
  264. {
  265. if (!\Yii::$app->request->isGet) {
  266. return $this->error('请求方式错误');
  267. }
  268. $page = \Yii::$app->request->get('page', 1);
  269. $limit = \Yii::$app->request->get('limit', $this->pageSize);
  270. $date = \Yii::$app->request->get('date');
  271. // 记录类型,add:库存增加;sub:库存减少
  272. $record_type = \Yii::$app->request->get('record_type');
  273. if (empty($record_type) || !in_array($record_type, ['add', 'sub'])) return $this->error('参数错误');
  274. $wheres[] = ['user_id' => $this->user_id];
  275. $wheres[] = ['user_id' => $this->user_id];
  276. if (!empty($date)) {
  277. $date = date($date . '-01');
  278. } else {
  279. $date = date('Y-m-01');
  280. }
  281. $start_time = strtotime($date);
  282. $end_time = strtotime($date . '+1 month -1 day 23:59:59');
  283. $wheres[] = ['and', ['>=', 'created_at', $start_time], ['<=', 'created_at', $end_time]];
  284. if ('add' == $record_type) {
  285. $params = [
  286. 'where' => $wheres,
  287. 'order' => 'created_at desc',
  288. 'page' => $page,
  289. 'limit' => $limit
  290. ];
  291. $detail_list = CloudStockTwoIncreaseDetail::listPage($params);
  292. } else {
  293. $params = [
  294. 'where' => $wheres,
  295. 'order' => 'created_at desc',
  296. 'page' => $page,
  297. 'limit' => $limit
  298. ];
  299. $detail_list = CloudStockTwoDeductionDetail::listPage($params);
  300. }
  301. if (!empty($detail_list['list'])) {
  302. $goods_id_arr = array_column($detail_list['list'], 'goods_id');
  303. $goods_list = Goods::find()
  304. ->select('id,goods_name,price,cover_pic')
  305. ->where(['mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED, 'id' => $goods_id_arr])
  306. ->asArray()
  307. ->indexBy('id')
  308. ->all();
  309. foreach ($detail_list['list'] as &$item) {
  310. $item['goods_name'] = $item['cover_pic'] = '';
  311. $item['price'] = 0;
  312. $item['changes_dir'] = 'add' == $record_type ? 1 : 2;
  313. if (isset($goods_list[$item['goods_id']])) {
  314. $item['goods_name'] = $goods_list[$item['goods_id']]['goods_name'];
  315. $item['cover_pic'] = $goods_list[$item['goods_id']]['cover_pic'];
  316. $item['price'] = $goods_list[$item['goods_id']]['price'];
  317. }
  318. }
  319. }
  320. $user = ArrayHelper::toArray($this->stock_agent->user);
  321. $stock_change_type_map = CloudStockTwoEnum::getStockChangeTypeMap();
  322. $stock_change_dir_map = CloudStockTwoEnum::getStockChangeDirMap();
  323. return $this->success('success', compact('detail_list', 'user', 'stock_change_type_map', 'stock_change_dir_map'));
  324. }
  325. /**
  326. * @name:
  327. * @msg: 给下级配货
  328. * @param {*}
  329. * @return {*}
  330. */
  331. public function actionIssueGive()
  332. {
  333. if (!\Yii::$app->request->isPost) {
  334. return $this->error('请求方式错误');
  335. }
  336. $post = \Yii::$app->request->post();
  337. $rules = [
  338. [['goods_id', 'number', 'target_user_id'], 'required'],
  339. [['goods_id', 'number', 'target_user_id'], 'integer'],
  340. ];
  341. $res = \Yii::$app->services->validate->validate($post, $rules);
  342. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  343. $post['user_id'] = $this->user_id;
  344. $res = CloudStockTwoGoodsStockLog::stockHandle($this->mall_id, $post, CloudStockTwoEnum::STOCK_CHANGE_TYPE201);
  345. if (false === $res) return $this->error(CloudStockTwoGoodsStockLog::getStaticError());
  346. return $this->success('操作成功');
  347. }
  348. /**
  349. * @name:
  350. * @msg: 提货到线下
  351. * @param {integer} $goods_id 商品id
  352. * @return {*}
  353. */
  354. public function actionGoodDetail()
  355. {
  356. if (!\Yii::$app->request->isGet) {
  357. return $this->error('请求方式错误');
  358. }
  359. $goods_id = \Yii::$app->request->get('goods_id');
  360. if (empty($goods_id)) return $this->error('参数错误');
  361. $good = Goods::find()
  362. ->select('id,mall_id,goods_name,cover_pic,price,stock')
  363. ->where(['mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED, 'id' => $goods_id, 'is_on_sale' => 1, 'is_attr' => 0])
  364. ->limit(1)
  365. ->asArray()
  366. ->one();
  367. $stock_good = CloudStockTwoGoods::findOne(['mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED, 'goods_id' => $goods_id]);
  368. if (empty($good)) return $this->error('商品数据异常');
  369. $agent_price = json_decode($stock_good['agent_price'],true);
  370. $agent_price = array_column($agent_price,null,'level');
  371. $replenish_price = 0;
  372. if(!empty($agent_price[$this->stock_agent->level])){
  373. $replenish_price = $agent_price[$this->stock_agent->level]['price'];
  374. }
  375. $all_stocks = CloudStockTwoGoods::allPerantAgentGoodStocks($goods_id, $this->user_id, $this->mall_id);
  376. if (false === $all_stocks) {
  377. return $this->error(CloudStockTwoGoods::getStaticError());
  378. }
  379. $good['replenish_price'] = $replenish_price;
  380. $good['profit'] = bcsub($good['price'], $replenish_price, 2);
  381. $good['pick_number_limit'] = $all_stocks;
  382. $good['is_allow_fill'] = $stock_good->is_allow_fill;
  383. return $this->success('success', $good);
  384. }
  385. /**
  386. * @name:
  387. * @msg: 提货到线下
  388. * @param {integer} addr_id 地址 id
  389. * @param {integer} goods_id 商品 id
  390. * @param {integer} number 提货数量
  391. * @param {string} password 交易密码
  392. * @return {*}
  393. */
  394. public function actionPickOffline()
  395. {
  396. if (!\Yii::$app->request->isPost) {
  397. return $this->error('请求方式错误');
  398. }
  399. $post = \Yii::$app->request->post();
  400. $rules = [
  401. [['addr_id', 'goods_id', 'number'], 'required'],
  402. [['addr_id', 'goods_id', 'number'], 'integer'],
  403. ['password', 'string']
  404. ];
  405. $res = \Yii::$app->services->validate->validate($post, $rules);
  406. if ($res === false) return $this->error(\Yii::$app->services->validate->getErrorMessage());
  407. $balance_pay_setting = json_decode(\Yii::$app->services->setting->mall->get($this->mall_id, 'pay.balance'), 'true');
  408. if (!empty($balance_pay_setting['pay_password_status'])) {
  409. $user = User::findOne(['id' => $this->user_id]);
  410. if (empty($user->transaction_password)) {
  411. return $this->error('您未设置支付密码');
  412. }
  413. if (empty($post['password'])) {
  414. return $this->error('请输入交易密码');
  415. }
  416. if (!\Yii::$app->security->validatePassword(trim($post['password']), $user->transaction_password)) {
  417. return $this->error('支付密码错误');
  418. }
  419. }
  420. $post['user_id'] = $this->user_id;
  421. // dd($post);
  422. $stock_good = CloudStockTwoAgentGoods::findOne(['mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED, 'goods_id' => $post['goods_id'], 'user_id' => $this->user_id]);
  423. if ($post['number'] > $stock_good->num) {
  424. return $this->error('提货数量超过了商品库存');
  425. }
  426. $good = Goods::findOne(['mall_id' => $this->mall_id, 'status' => StatusEnum::ENABLED, 'id' => $post['goods_id'], 'is_on_sale' => 1, 'is_attr' => 0]);
  427. if (empty($stock_good) || empty($good)) return $this->error('商品数据异常');
  428. // 提货到线下
  429. $res = CloudStockTwoAgentOrder::pickOffline($this->mall_id, $post);
  430. if (false === $res) return $this->error('提货失败:' . CloudStockTwoAgentOrder::getStaticError());
  431. return $this->success('提货成功');
  432. }
  433. }