CloudStockPriceDifferenceGiftPackageOrderService.php 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  1. <?php
  2. namespace addons\CloudStock\common\services;
  3. use addons\CloudStock\common\enums\CloudStockEnum;
  4. use addons\CloudStock\common\events\order\FillOrderPaidEvent;
  5. use addons\CloudStock\common\events\order\PriceDifferenceOrderPaidEvent;
  6. use addons\CloudStock\common\models\CloudStockAgent;
  7. use addons\CloudStock\common\models\CloudStockAgentOrder;
  8. use addons\CloudStock\common\models\CloudStockBuyingOrder;
  9. use addons\CloudStock\common\models\CloudStockDeductionDetail;
  10. use addons\CloudStock\common\models\CloudStockFillOrder;
  11. use addons\CloudStock\common\models\CloudStockFillOrderRelation;
  12. use addons\CloudStock\common\models\CloudStockGoods;
  13. use addons\CloudStock\common\models\CloudStockPriceDifferenceGiftPackage;
  14. use addons\CloudStock\common\models\CloudStockPriceDifferenceOrder;
  15. use addons\CloudStock\common\models\CloudStockPriceDifferenceOrderDetail;
  16. use addons\FireProtection\common\enums\FireProtectionEnum;
  17. use common\components\export\CsvTool;
  18. use common\enums\AppEnum;
  19. use common\enums\DownloadEnum;
  20. use common\enums\OrderStatusEnum;
  21. use common\enums\PayTypeEnum;
  22. use common\enums\PreviewTypeEnum;
  23. use common\enums\StatusEnum;
  24. use common\helpers\StringHelper;
  25. use common\logic\order\marketing\BaseMarketing;
  26. use common\logic\order\marketing\FreeShippingMarketing;
  27. use common\logic\order\OrderFormLogic;
  28. use common\logic\order\OrderInitDataLogic;
  29. use common\models\common\Download;
  30. use common\models\common\PaymentTrade;
  31. use common\models\goods\Goods;
  32. use common\models\order\Order;
  33. use common\models\user\User;
  34. use common\models\user\UserAddress;
  35. use common\models\user\UserPartitionRelationship;
  36. use Exception;
  37. use services\common\UserWalletService;
  38. use Yii;
  39. use function Clue\StreamFilter\fun;
  40. class CloudStockPriceDifferenceGiftPackageOrderService extends BaseService
  41. {
  42. public static $expire_time = 7 * 24 * 3600;//购物车内商品的有效期
  43. public static $key = 'cloud_stock_price_difference_gift_package_cart_';//购物车hash key
  44. public static $field = '';//字段
  45. public static $self_pickup = 'self_pickup';//字段
  46. public static $cloud_warehouse = 'cloud_warehouse';//字段
  47. public function getExportFields()
  48. {
  49. $fields = [
  50. 'user_id' => '用户ID',
  51. 'nickname' => '用户昵称',
  52. 'created_at' => '订单创建时间',
  53. 'order_no' => '订单编号',
  54. 'goods_name' => '商品名称',
  55. 'goods_price' => '价格',
  56. 'total_num' => '总数',
  57. 'self_pickup_num' => '自提',
  58. 'cloud_warehouse_num' => '云仓',
  59. 'pay_money' => '实际支付金额(元)',
  60. 'shipping_money' => '运费',
  61. 'from_user' => '补货上级',
  62. 'receiver_name' => '收货人',
  63. 'receiver_mobile' => '收货人手机号',
  64. 'address' => '收货地址',
  65. 'rand_fee' => '随机减金额(元)',
  66. 'payment_type' => '支付方式',
  67. ];
  68. return $fields;
  69. }
  70. public function index($params)
  71. {
  72. $params['where'] = $this->getQueryWhere($params);
  73. $params['order'] = 'id desc';
  74. $params['select'] = 'id,user_id,trade_id,address_id,pay_money,shipping_money,payment_type,created_at,address,receiver_name,receiver_mobile,order_no';
  75. $params['with'] = [
  76. 'detail' => function ($q) {
  77. $q->select('id,price_difference_order_id,self_pickup_num,cloud_warehouse_num,goods_price');
  78. },
  79. 'fillOrder' => function ($q) {
  80. $q->select('id,price_difference_order_id,price_difference_order_detail_id,order_no,goods_id')
  81. ->with(['goods' => function ($g) {
  82. $g->select('id,goods_name,cover_pic');
  83. }]);
  84. },
  85. 'user' => function ($q) {
  86. $q->select('id,nickname');
  87. },
  88. 'paymentTrade' => function ($q) {
  89. $q->select('id,rand_fee');
  90. }
  91. ];
  92. $pageData = CloudStockPriceDifferenceOrder::listPage($params, false);
  93. if (!empty($pageData['list'])) {
  94. $deduction_user_id_arr = [];
  95. $deduction_user_list = $this->getDeductionUserList($pageData, $deduction_user_id_arr);
  96. foreach ($pageData['list'] as &$item) {
  97. $item['rand_fee'] = $item['paymentTrade']['rand_fee'] ?? 0;
  98. $detail_list = array_column($item['detail'], null, 'id');
  99. foreach ($item['fillOrder'] as &$val) {
  100. $val['from_user'] = [];
  101. $val['self_pickup_num'] = $val['cloud_warehouse_num'] = $val['goods_price'] = 0;
  102. if (isset($detail_list[$val['price_difference_order_detail_id']])) {
  103. $val['self_pickup_num'] = $detail_list[$val['price_difference_order_detail_id']]['self_pickup_num'];
  104. $val['cloud_warehouse_num'] = $detail_list[$val['price_difference_order_detail_id']]['cloud_warehouse_num'];
  105. $val['goods_price'] = $detail_list[$val['price_difference_order_detail_id']]['goods_price'];
  106. }
  107. if (!isset($deduction_user_id_arr[$val['id']])) {
  108. continue;
  109. }
  110. foreach ($deduction_user_id_arr[$val['id']] as $uid) {
  111. if (!isset($deduction_user_list[$uid])) {
  112. continue;
  113. }
  114. $val['from_user'][] = [
  115. 'id' => $uid,
  116. 'nickname' => $deduction_user_list[$uid]['nickname'],
  117. 'mobile' => $deduction_user_list[$uid]['mobile'],
  118. 'avatar_url' => $deduction_user_list[$uid]['avatar_url'],
  119. ];
  120. }
  121. }
  122. unset($item['detail']);
  123. unset($item['paymentTrade']);
  124. }
  125. }
  126. $pageData['export_list'] = $this->getExportFields();
  127. $pageData['payment_type_list'] = PayTypeEnum::getMap();
  128. return $pageData;
  129. }
  130. public function getQueryWhere($params)
  131. {
  132. $where = [
  133. ['mall_id' => $this->mall_id],
  134. ['status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]],
  135. ['is_pay' => OrderStatusEnum::PAY],
  136. ];
  137. if (!empty($params['keyword'])) {
  138. $keyword = trim($params['keyword']);
  139. $user_id_arr = User::find()->where(['or',
  140. ['id' => $keyword],
  141. ['like', 'nickname', $keyword],
  142. ['like', 'mobile', $keyword]])
  143. ->select('id')->column();
  144. $where[] = ['user_id' => $user_id_arr];
  145. }
  146. if (!empty($params['goods_name'])) {
  147. $goods_name = trim($params['goods_name']);
  148. $goods_ids = Goods::find()->where(['and',
  149. ['mall_id' => $this->mall_id],
  150. ['like', 'goods_name', $goods_name]])
  151. ->select('id')->column();
  152. $price_difference_order_ids = CloudStockPriceDifferenceOrderDetail::find()->where(['goods_id' => $goods_ids])->select('price_difference_order_id')->column();
  153. $where[] = ['id' => $price_difference_order_ids];
  154. }
  155. if (!empty($params['start'])) {
  156. $where[] = ['>=', 'created_at', strtotime($params['start'])];
  157. }
  158. if (!empty($params['end'])) {
  159. $where[] = ['<=', 'created_at', strtotime($params['end'])];
  160. }
  161. if (!empty($params['payment_type'])) {
  162. $where[] = ['payment_type' => $params['payment_type']];
  163. }
  164. if (!empty($params['order_no'])) {
  165. $order_no = trim($params['order_no']);
  166. $price_difference_order_id = CloudStockFillOrder::find()->where(['and',
  167. ['mall_id' => $this->mall_id],
  168. ['like', 'order_no', $order_no]])
  169. ->select('price_difference_order_id')->column();
  170. $where[] = ['id' => $price_difference_order_id];
  171. }
  172. return $where;
  173. }
  174. public function getDeductionUserList($pageData, &$deduction_user_id_arr)
  175. {
  176. $fill_order_id_arr = [];
  177. foreach ($pageData['list'] as $item) {
  178. $item['rand_fee'] = $item['paymentTrade']['rand_fee'] ?? 0;
  179. foreach ($item['fillOrder'] as $val) {
  180. $fill_order_id_arr[] = $val['id'];
  181. }
  182. }
  183. $deduction_list = CloudStockDeductionDetail::lists([
  184. 'where' => [
  185. ['order_id' => $fill_order_id_arr],
  186. ['order_type' => CloudStockEnum::STOCK_ORDER_TYPE_REPLENISH],
  187. ['changes_type' => [CloudStockEnum::STOCK_CHANGE_TYPE200, CloudStockEnum::STOCK_CHANGE_TYPE202,]],
  188. ],
  189. 'select' => 'user_id,order_id',
  190. ]
  191. );
  192. $deduction_user_ids = array_column($deduction_list, 'user_id');
  193. foreach ($deduction_list as $val) {
  194. $deduction_user_id_arr[$val['order_id']][] = $val['user_id'];
  195. }
  196. $deduction_user_list = User::lists([
  197. 'where' => [
  198. ['id' => $deduction_user_ids]
  199. ],
  200. 'index' => 'id',
  201. 'select' => 'id,nickname,mobile,avatar_url',
  202. ]
  203. );
  204. $deduction_user_list[0] = ['id' => 0,
  205. 'nickname' => '平台',
  206. 'mobile' => '',
  207. 'avatar_url' => '',
  208. ];
  209. return $deduction_user_list;
  210. }
  211. public function addCart($params)
  212. {
  213. //传入的插件名和识别value
  214. $key = $this->getCacheKey($params['price_difference_gift_package_id']);
  215. $field = $this->getCacheField($params['type'], $params['goods_id']);
  216. if (empty($params['num'])) {
  217. $res = \Yii::$app->redis->hdel($key, $field);
  218. return true;
  219. }
  220. \Yii::$app->redis->hset($key, $field, json_encode($params));
  221. \Yii::$app->redis->expire($key, self::$expire_time);
  222. return true;
  223. }
  224. public function delCart($params)
  225. {
  226. //传入的插件名和识别value
  227. foreach ($params['goods_id'] as $goods_id) {
  228. $key = $this->getCacheKey($params['price_difference_gift_package_id']);
  229. $field = $this->getCacheField(self::$self_pickup, $goods_id);
  230. \Yii::$app->redis->hdel($key, $field);
  231. $field = $this->getCacheField(self::$cloud_warehouse, $goods_id);
  232. \Yii::$app->redis->hdel($key, $field);
  233. }
  234. return true;
  235. }
  236. public function indexCart($params)
  237. {
  238. $cart_list = $this->getCartAll($params['price_difference_gift_package_id']);
  239. $goods_ids = array_keys($cart_list);
  240. $main_goods_list = Goods::lists(['where' => [['id' => $goods_ids]], 'index' => 'id', 'select' => 'id,goods_name,cover_pic,price']);
  241. $list = [];
  242. $package = CloudStockPriceDifferenceGiftPackage::findOne(['id' => $params['price_difference_gift_package_id']]);
  243. $goods_ids = explode(',', $package['goods_id']);
  244. $obj = new CloudStockPriceDifferenceGiftPackageService(['user_id' => $this->user_id, 'mall_id' => $this->mall_id]);
  245. foreach ($main_goods_list as $item) {
  246. if (!in_array($item['id'], $goods_ids)) {
  247. continue;
  248. }
  249. $price = $item['price'];
  250. $obj->getPrice($item['id'], $goods_ids, $price, $package['level']);
  251. $list[] = [
  252. 'goods_id' => $item['id'],
  253. 'goods_name' => $item['goods_name'],
  254. 'price' => $price,
  255. 'cover_pic' => $item['cover_pic'],
  256. 'self_pickup_num' => $cart_list[$item['id']]['self_pickup'] ?? 0,
  257. 'cloud_warehouse_num' => $cart_list[$item['id']]['cloud_warehouse'] ?? 0,
  258. ];
  259. }
  260. return ['list' => $list];
  261. }
  262. public function getCacheKey($price_difference_gift_package_id)
  263. {
  264. return self::$key . ':' . $this->user_id . ':' . $price_difference_gift_package_id;
  265. }
  266. public function getCacheField($type, $goods_id)
  267. {
  268. return self::$field . $type . ':' . $goods_id;
  269. }
  270. public function orderPreview($params)
  271. {
  272. try {
  273. //传入的插件名和识别value
  274. $cart_list = $this->getCartAll($params['price_difference_gift_package_id']);
  275. if (empty($params['goods_ids'])) {
  276. throw new \Exception('请选择商品');
  277. }
  278. if (empty($cart_list)) {
  279. throw new \Exception('购物车为空');
  280. }
  281. $package = CloudStockPriceDifferenceGiftPackage::find()->where(['id' => $params['price_difference_gift_package_id']])->one();//所选的价差礼包
  282. if (empty($package)) {
  283. throw new \Exception('价差礼包不存在');
  284. }
  285. $cloud_stock_agent_level = 0;
  286. $cloud_stock_agent = CloudStockAgent::findOne(['mall_id' => $this->mall_id, 'user_id' => $this->user_id, 'status' => StatusEnum::ENABLED]);
  287. $goods_ids = array_keys($cart_list);
  288. $goods_ids = array_intersect($goods_ids, $params['goods_ids']);
  289. $main_goods_list = Goods::lists(['where' => [['id' => $goods_ids]], 'with' => ['attr'], 'index' => 'id', 'select' => 'id,goods_name,cover_pic,price']);
  290. if (!empty($cloud_stock_agent)) {
  291. $cloud_stock_agent_level = $cloud_stock_agent['level'];
  292. }
  293. $list = [];
  294. $is_show_address = 0;
  295. $pay_money = 0;
  296. $freight_attr = [];
  297. $obj = new CloudStockPriceDifferenceGiftPackageService(['user_id' => $this->user_id, 'mall_id' => $this->mall_id]);
  298. foreach ($main_goods_list as $item) {
  299. $price = $item['price'];
  300. $obj->getPrice($item['id'], $goods_ids, $price, $package['level']);
  301. $self_pickup_num = $cloud_warehouse_num = 0;
  302. if (isset($cart_list[$item['id']])) {
  303. $self_pickup_num = $cart_list[$item['id']][self::$self_pickup];
  304. $cloud_warehouse_num = $cart_list[$item['id']][self::$cloud_warehouse];
  305. }
  306. if ($self_pickup_num > 0) {
  307. $is_show_address = 1;
  308. $freight_attr[] = [
  309. 'attr_id' => $item['attr'][0]['id'],
  310. 'num' => $self_pickup_num,
  311. ];
  312. }
  313. $list[] = [
  314. 'goods_id' => $item['id'],
  315. 'goods_name' => $item['goods_name'],
  316. 'price' => $price,
  317. 'cover_pic' => $item['cover_pic'],
  318. 'self_pickup_num' => $self_pickup_num,
  319. 'cloud_warehouse_num' => $cloud_warehouse_num,
  320. ];
  321. $pay_money += $price * ($self_pickup_num + $cloud_warehouse_num);
  322. }
  323. $this->check($cloud_stock_agent_level, $package, $pay_money);
  324. $shipping_fee = 0;
  325. $address_info = [];
  326. if (!empty($freight_attr)) {
  327. $form = $this->getShippingFee($params, $freight_attr);//获取运费
  328. $shipping_fee = $form['marketing']['deduct']['shipping_fee']['money'] ?? 0;
  329. $address_info = UserAddress::getUserAddress($this->user_id, $params['address_id'] ?? 0);
  330. }
  331. return ['list' => $list, 'address_info' => $address_info, 'is_show_address' => $is_show_address, 'shipping_fee' => $shipping_fee, 'pay_money' => bcadd($pay_money, $shipping_fee, 2)];
  332. } catch (Exception $e) {
  333. throw new Exception($e->getMessage());
  334. }
  335. }
  336. /**
  337. * 获取价差
  338. * 购买时判断当前等级礼包与所选购礼包的金额价差,满足则可下单成功升级
  339. * ②若当前等级无设置礼包则往上找最近有设置礼包的等级取差价
  340. * ④若是普通用户不是代理商等级则取选购的礼包金额
  341. * @param $level
  342. * @param $package_price
  343. * @return string
  344. */
  345. public function priceDiff($level, $package_price)
  346. {
  347. $price_diff = $package_price;
  348. if ($level == 0) {
  349. return $price_diff;
  350. }
  351. $package_current = CloudStockPriceDifferenceGiftPackage::find()->where([
  352. 'mall_id' => $this->mall_id,
  353. 'status' => StatusEnum::ENABLED,
  354. ])->andWhere(['>=', 'level', $level])->orderBy('level asc')->one();
  355. if (!empty($package_current)) {
  356. $price_diff = bcsub($price_diff, $package_current['price'], 2);
  357. }
  358. return $price_diff;
  359. }
  360. public function orderCreate($params)
  361. {
  362. $t = Yii::$app->db->beginTransaction();
  363. try {
  364. //传入的插件名和识别value
  365. if (empty($params['goods_ids'])) {
  366. throw new \Exception('请选择商品');
  367. }
  368. $cart_list = $this->getCartAll($params['price_difference_gift_package_id']);
  369. if (empty($cart_list)) {
  370. throw new \Exception('购物车为空');
  371. }
  372. $package = CloudStockPriceDifferenceGiftPackage::find()->where(['id' => $params['price_difference_gift_package_id']])->one();
  373. if (empty($package)) {
  374. throw new \Exception('礼包不存在');
  375. }
  376. $cloud_stock_agent = CloudStockAgent::findOne(['mall_id' => $this->mall_id, 'user_id' => $this->user_id, 'status' => StatusEnum::ENABLED]);
  377. $goods_ids = array_keys($cart_list);
  378. $goods_ids = array_intersect($goods_ids, $params['goods_ids']);
  379. $main_goods_list = Goods::lists(['where' => [['id' => $goods_ids]], 'with' => ['attr'], 'index' => 'id', 'select' => 'id,goods_name,cover_pic,price']);
  380. $obj = new CloudStockPriceDifferenceGiftPackageService(['user_id' => $this->user_id, 'mall_id' => $this->mall_id]);
  381. $list = [];
  382. $pay_money = 0;
  383. $freight_attr = [];
  384. foreach ($main_goods_list as $item) {
  385. $price = $item['price'];
  386. $self_pickup_num = $cloud_warehouse_num = 0;
  387. $obj->getPrice($item['id'], $goods_ids, $price, $package['level']);
  388. if (isset($cart_list[$item['id']])) {
  389. $self_pickup_num = $cart_list[$item['id']][self::$self_pickup] ?? 0;
  390. $cloud_warehouse_num = $cart_list[$item['id']][self::$cloud_warehouse] ?? 0;
  391. }
  392. if ($self_pickup_num > 0) {
  393. $freight_attr[] = [
  394. 'attr_id' => $item['attr'][0]['id'],
  395. 'num' => $self_pickup_num,
  396. ];
  397. }
  398. $goods_price = $price * ($self_pickup_num + $cloud_warehouse_num);
  399. $list[] = [
  400. 'goods_id' => $item['id'],
  401. 'goods_name' => $item['goods_name'],
  402. 'price' => $price,
  403. 'goods_price' => $goods_price,
  404. 'cover_pic' => $item['cover_pic'],
  405. 'self_pickup_num' => $self_pickup_num,
  406. 'cloud_warehouse_num' => $cloud_warehouse_num,
  407. ];
  408. $pay_money += $goods_price;
  409. }
  410. $cloud_stock_agent_level = 0;
  411. if (!empty($cloud_stock_agent)) {
  412. $cloud_stock_agent_level = $cloud_stock_agent['level'];
  413. }
  414. $this->check($cloud_stock_agent_level, $package, $pay_money);
  415. if (!empty($params['address_id'])) {
  416. $user_address = UserAddress::findOne(['id' => $params['address_id'], 'user_id' => $this->user_id]);
  417. if (empty($user_address)) {
  418. throw new \Exception('地址不存在');
  419. }
  420. $params['address'] = $user_address['province'] . $user_address['city'] . $user_address['district'] . $user_address['town'] . $user_address['detail'];
  421. }
  422. $shipping_money = 0;
  423. if (!empty($freight_attr)) {
  424. $form = $this->getShippingFee($params, $freight_attr);//获取运费
  425. $shipping_money = $form['marketing']['deduct']['shipping_fee']['money'] ?? 0;
  426. }
  427. $pay_money = bcadd($pay_money, $shipping_money, 2);
  428. if ($pay_money == 0) {
  429. throw new \Exception('订单金额不能为0');
  430. }
  431. $params['shipping_money'] = $shipping_money;
  432. $params['pay_money'] = $pay_money;
  433. if (empty($params['address_id'])) {
  434. $params['address_id'] = 0;
  435. }
  436. if (empty($params['remark'])) {
  437. $params['remark'] = '';
  438. } else {
  439. $params['remark'] = (string)$params['remark'];
  440. }
  441. $params['receiver_mobile'] = (string)$params['receiver_mobile'];
  442. $order = $this->createOrder($params);
  443. $goods_name = '';
  444. foreach ($list as $k => $item) {
  445. if ($k == 0) {
  446. $goods_name = $item['goods_name'];
  447. }
  448. $add['price_difference_order_id'] = $order['id'];
  449. $add['goods_id'] = $item['goods_id'];
  450. $add['goods_price'] = $item['goods_price'];
  451. $add['self_pickup_num'] = $item['self_pickup_num'];
  452. $add['cloud_warehouse_num'] = $item['cloud_warehouse_num'];
  453. $this->createOrderDetail($add);
  454. }
  455. $order_trade_info[] = [
  456. 'order_id' => $order->id,
  457. 'order_type' => 'price_diff_order',
  458. 'order_no' => $order->order_no,
  459. 'amount' => $pay_money,
  460. 'title' => $goods_name,
  461. 'notify_class' => 'addons\CloudStock\common\logic\notify\CloudStockPriceDifferenceGiftPackageNotify',
  462. ];
  463. $res = \Yii::$app->services->pay->createTrade($this->mall_id, $this->user_id, $order_trade_info);
  464. if ($res == false) throw new \Exception('生成支付流水失败');
  465. $arr['transaction'] = $res;
  466. $t->commit();
  467. return $arr;
  468. } catch (Exception $e) {
  469. $t->rollBack();
  470. throw new \Exception($e->getMessage());
  471. }
  472. }
  473. public function getCartAll($price_difference_gift_package_id)
  474. {
  475. $key = $this->getCacheKey($price_difference_gift_package_id);
  476. $data = \Yii::$app->redis->hgetall($key);
  477. $list = [];
  478. foreach ($data as $item) {
  479. $item = json_decode($item, true);
  480. if (is_array($item)) {
  481. $list[$item['goods_id']][$item['type']] = $item['num'];
  482. }
  483. }
  484. return $list;
  485. }
  486. public function getCloudStockGoodsList($goods_ids)
  487. {
  488. $cloud_stock_goods_list = CloudStockGoods::lists([
  489. 'where' => [
  490. ['goods_id' => $goods_ids],
  491. ['status' => StatusEnum::ENABLED]
  492. ],
  493. 'index' => 'goods_id',
  494. 'select' => 'goods_id,agent_price'
  495. ]);
  496. foreach ($cloud_stock_goods_list as &$val) {
  497. $agent_price = json_decode($val['agent_price'], true);
  498. $val['agent_price'] = array_column($agent_price, null, 'level');
  499. }
  500. return $cloud_stock_goods_list;
  501. }
  502. public function check($cloud_stock_agent_level, $package, $pay_money)
  503. {
  504. $price_diff = $this->priceDiff($cloud_stock_agent_level, $package['price']);
  505. if ($pay_money < $price_diff) {
  506. throw new Exception('支付金额不能小于' . $price_diff);
  507. }
  508. }
  509. /**
  510. * 获取运费
  511. * @param $params
  512. * @param $freight_attr
  513. * @return bool|int|object
  514. * @throws \Exception
  515. */
  516. public function getShippingFee($params, $freight_attr)
  517. {
  518. if (empty($params['address_id'])) {
  519. return 0;
  520. }
  521. $orderFormLogic = new OrderFormLogic();
  522. $form = $orderFormLogic->getDefaultform($this->mall_id, $this->user_id);
  523. $form->attributes = [
  524. 'type' => PreviewTypeEnum::FREIGHT,
  525. 'data' => [
  526. 'shipping_type' => \common\enums\ShippingTypeEnum::LOGISTICS,
  527. 'freight_attr' => $freight_attr,
  528. 'address_id' => $params['address_id']
  529. ]
  530. ];
  531. $form['action'] = AppEnum::ACTION_CREATE;
  532. $orderInitDataLogic = new OrderInitDataLogic();
  533. $form = $orderInitDataLogic->execute($form, $form->type);
  534. if (empty($form['group_order_goods'])) {
  535. throw new \Exception('没有商品');
  536. }
  537. $group_order_goods = $form['group_order_goods'];
  538. $extra = [];
  539. foreach ($group_order_goods as &$item) {
  540. /** @var BaseMarketing $class */
  541. $item = FreeShippingMarketing::compute($item, $form, $extra);
  542. if ($item === false) throw new \Exception(FreeShippingMarketing::getStaticError());
  543. }
  544. return $form;
  545. }
  546. public function createOrder($params)
  547. {
  548. $params['user_id'] = $this->user_id;
  549. $params['mall_id'] = $this->mall_id;
  550. $model = new CloudStockPriceDifferenceOrder();
  551. $model->loadDefaultValues();
  552. $model->load($params, '');
  553. $model->is_pay = OrderStatusEnum::NOT_PAY;
  554. $model->order_no = StringHelper::generateOrderNo('pdgp');
  555. $res = $model->save();
  556. if ($res == false) {
  557. throw new \Exception($model->getErrorMessage());
  558. }
  559. return $model;
  560. }
  561. public function createOrderDetail($params)
  562. {
  563. $params['user_id'] = $this->user_id;
  564. $params['mall_id'] = $this->mall_id;
  565. $model = new CloudStockPriceDifferenceOrderDetail();
  566. $model->loadDefaultValues();
  567. $model->load($params, '');
  568. $model->save();
  569. return $model;
  570. }
  571. public function pay($order_no, $payment_type, $out_trade_no = '')
  572. {
  573. try {
  574. $model = CloudStockPriceDifferenceOrder::findOne(['order_no' => $order_no]);
  575. if (empty($model)) throw new \Exception('订单不存在或已删除');
  576. if ($model->is_pay != OrderStatusEnum::NOT_PAY) throw new Exception('订单已经被处理,无法进行支付');
  577. if ($model->is_pay == StatusEnum::ENABLED) throw new Exception('订单已支付,请不要重复支付');
  578. $model->is_pay = OrderStatusEnum::PAY;
  579. $model->payment_type = $payment_type;
  580. $model->pay_time = time();
  581. $model->trade_no = $out_trade_no ?? '';
  582. $res = $model->save();
  583. if ($res === false) throw new Exception('修改订单失败:' . $model->getErrorMessage());
  584. $event = new PriceDifferenceOrderPaidEvent($model['mall_id']);
  585. $order['id'] = $model['id'];
  586. Yii::$app->services->events->dispatch($event, $order, $event->listeners);
  587. return $model;
  588. } catch (Exception $e) {
  589. if (isset($trans)) $trans->rollback();
  590. self::$static_error = $e->getMessage();
  591. return false;
  592. }
  593. }
  594. public function createFillOrder($data)
  595. {
  596. $order_no = StringHelper::generateOrderNo('CSF');
  597. $params = [
  598. 'user_id' => $data['user_id'],
  599. 'trade_id' => $data['trade_id'],
  600. 'pay_money' => $data['goods_price'],
  601. 'order_no' => $order_no,
  602. 'trade_no' => $data['trade_no'],
  603. 'is_pay' => CloudStockEnum::FILL_STATUS_PAY,
  604. 'goods_id' => $data['goods_id'],
  605. 'price_difference_order_id' => $data['price_difference_order_id'],
  606. 'price_difference_order_detail_id' => $data['price_difference_order_detail_id'],
  607. 'num' => $data['self_pickup_num'] + $data['cloud_warehouse_num'],
  608. ];
  609. $res_fill_order = CloudStockFillOrder::setData($data['mall_id'], $params);
  610. // 触发云库存订单支付事件
  611. $event = new FillOrderPaidEvent($data['mall_id']);
  612. $data = ['id' => $res_fill_order['id']];
  613. \Yii::$app->services->events->dispatch($event, $data, $event->listeners);
  614. return $res_fill_order;
  615. }
  616. public function createOrderPick($data)
  617. {
  618. $data['order_type'] = 2;
  619. $res = CloudStockAgentOrder::pickOffline($data['mall_id'], $data);
  620. if (false === $res) {
  621. throw new \Exception('提货失败:' . CloudStockAgentOrder::getStaticError());
  622. }
  623. }
  624. /**
  625. * @param $fill_order
  626. * @param $package
  627. * @return array|true
  628. * @throws Exception推荐奖励
  629. */
  630. public function recommendReward($fill_order, $package)
  631. {
  632. if (empty($package)) {
  633. return [];
  634. }
  635. $recommend_reward_setting = json_decode($package['recommend_reward'], true);
  636. if (empty($recommend_reward_setting)) {
  637. return [];
  638. }
  639. $recommend_reward_setting = array_column($recommend_reward_setting, null, 'level');
  640. $user_id = $fill_order['user_id'];
  641. $mall_id = $fill_order['mall_id'];
  642. $parent_id_arr = UserPartitionRelationship::getParentIdArr($user_id);
  643. $parent_id_arr = array_reverse($parent_id_arr);
  644. $where = ['user_id' => $parent_id_arr, 'mall_id' => $mall_id, 'status' => StatusEnum::ENABLED];
  645. $cloud_agent_list = CloudStockAgent::find()->where($where)->indexBy('user_id')->all();
  646. $agent_list = [];
  647. foreach ($parent_id_arr as $parent_id) {
  648. if (!empty($cloud_agent_list[$parent_id])) $agent_list[] = $cloud_agent_list[$parent_id];//按照关系排序
  649. }
  650. $log_total_price = 0;
  651. $insert_wallet = [];
  652. $new_agent_list = [];
  653. $current_agent_level = 0;
  654. foreach ($agent_list as $key => $agent) {
  655. if ($agent['level'] > $current_agent_level) {
  656. $new_agent_list[$key] = $agent;
  657. $current_agent_level = $agent['level'];
  658. }
  659. }
  660. $is_range = 1;//走极差
  661. if (isset($package['is_range']) && $package['is_range'] == 0) {
  662. $is_range = 0; //不走极差,只给最近代理发放奖励
  663. }
  664. if ($is_range == 0) {
  665. $new_agent_list = $agent_list;
  666. }
  667. foreach ($new_agent_list as $k => $agent) {
  668. if ($is_range == 0 && $k > 0) {
  669. break;
  670. }
  671. if (!isset($recommend_reward_setting[$agent['level']])) {
  672. continue;
  673. }
  674. $recommend_reward = $recommend_reward_setting[$agent['level']]['reward_fee'] * $fill_order['pay_money'] / 100;
  675. if ($recommend_reward > 0) {
  676. $recommend_reward -= $log_total_price;
  677. }
  678. $log_total_price += $recommend_reward;
  679. $this->packData($mall_id, $fill_order['id'], $fill_order['order_no'], $agent['user_id'], $fill_order['user_id'], $recommend_reward, $fill_order['pay_money'], $insert_wallet);
  680. }
  681. return $insert_wallet;
  682. }
  683. public function packData($mall_id, $order_id, $order_no, $user_id, $buy_user_id, $price, $pay_money, &$insert_wallet)
  684. {
  685. if ($price > 0) {
  686. $prize_name = '推荐奖励';
  687. $desc = '用户(' . $user_id . '),获得订单(' . $order_no . ')收入,类型:' . $prize_name . ',金额:' . $price;
  688. $insert_wallet [] = ['mall_id' => $mall_id, 'user_id' => $user_id,
  689. 'is_frozen' => false,
  690. 'wallet_type' => 'commission',
  691. 'money' => $price,
  692. 'desc' => $desc,
  693. 'source_table' => CloudStockFillOrder::tableName(),
  694. 'source_table_id' => $order_id,
  695. 'from_type' => 'CloudStock',
  696. 'capital_type' => 'recommend_reward',
  697. 'order_no' => $order_no,
  698. 'contributor_name' => '',
  699. 'contributor_id' => $buy_user_id,
  700. 'contributor_money' => $pay_money,
  701. ];
  702. }
  703. }
  704. public function export(array $data)
  705. {
  706. $download_id = $data['download_id'] ?? 0;
  707. $download = Download::findOne(['id' => $download_id]);
  708. if ($download) {
  709. $this->mall_id = $data['mall_id'] ?? $download->mall_id;
  710. try {
  711. $params = json_decode($download->params, true);
  712. $filename = $download->name;
  713. $type = $download->type;
  714. $params['where'] = $this->getQueryWhere($params);
  715. $params['order'] = 'id desc';
  716. $params['select'] = 'id,user_id,trade_id,address_id,pay_money,shipping_money,payment_type,created_at,address,receiver_name,receiver_mobile';
  717. $params['with'] = [
  718. 'detail' => function ($q) {
  719. $q->select('id,price_difference_order_id,self_pickup_num,cloud_warehouse_num,goods_price');
  720. },
  721. 'fillOrder' => function ($q) {
  722. $q->select('id,price_difference_order_id,price_difference_order_detail_id,order_no,goods_id')
  723. ->with(['goods' => function ($g) {
  724. $g->select('id,goods_name,cover_pic');
  725. }]);
  726. },
  727. 'user' => function ($q) {
  728. $q->select('id,nickname');
  729. },
  730. 'paymentTrade' => function ($q) {
  731. $q->select('id,rand_fee');
  732. }
  733. ];
  734. $list = CloudStockPriceDifferenceOrder::lists($params, true);
  735. $payment_type_list = PayTypeEnum::getMap();
  736. $deduction_user_id_arr = [];
  737. $deduction_user_list = $this->getDeductionUserList(['list' => $list], $deduction_user_id_arr);
  738. $fields = $params['fields'];
  739. $fields_arr = $this->getExportFields();
  740. $have_select_field_arr = [];
  741. foreach ($fields as $value) {
  742. if (isset($fields_arr[$value])) $have_select_field_arr[] = $fields_arr[$value];
  743. }
  744. $csv = new CsvTool();
  745. $csv->filename = $filename;
  746. $csv->file_dirname = DownloadEnum::getTypeStorageDirMap($type);
  747. $csv->export_mode = CsvTool::EXPORT_MODE_ASYNC;
  748. $csv->header = $have_select_field_arr;
  749. $rows = [];
  750. foreach ($list as $order) {
  751. $detail_list = array_column($order['detail'], null, 'id');
  752. foreach ($order['fillOrder'] as $item) {
  753. $row = [];
  754. foreach ($fields as $field) {
  755. switch (true) {
  756. case ($field == 'nickname'):
  757. $row[] = $order['user'][$field] ?? '';
  758. break;
  759. case ($field == 'created_at'):
  760. $row[] = !empty($order[$field]) ? date('Y-m-d H:i:s', $order[$field]) : '';
  761. break;
  762. case ($field == 'order_no'):
  763. $row[] = $item[$field] ?? '';
  764. break;
  765. case ($field == 'rand_fee'):
  766. $row[] = $order['paymentTrade'][$field] ?? '';
  767. break;
  768. case ($field == 'goods_name'):
  769. $row[] = $item['goods']['goods_name'] ?? '';
  770. break;
  771. case ($field == 'goods_price'):
  772. $row[] = $detail_list[$item['price_difference_order_detail_id']]['goods_price'] ?? '';
  773. break;
  774. case ($field == 'total_num'):
  775. $self_pickup_num = $detail_list[$item['price_difference_order_detail_id']]['self_pickup_num'] ?? '';
  776. $cloud_warehouse_num = $detail_list[$item['price_difference_order_detail_id']]['cloud_warehouse_num'] ?? 0;
  777. $total_num = $self_pickup_num + $cloud_warehouse_num;
  778. $row[] = !empty($total_num) ? $total_num : '';
  779. break;
  780. case ($field == 'self_pickup_num'):
  781. $row[] = $detail_list[$item['price_difference_order_detail_id']]['self_pickup_num'] ?? '';
  782. break;
  783. case ($field == 'cloud_warehouse_num'):
  784. $row[] = $detail_list[$item['price_difference_order_detail_id']]['cloud_warehouse_num'] ?? '';
  785. break;
  786. case (in_array($field, ['user_id', 'shipping_money', 'pay_money', 'receiver_name', 'receiver_mobile', 'address'])):
  787. $row[] = $order[$field] ?? '';
  788. break;
  789. case ($field == 'payment_type'):
  790. $row[] = $payment_type_list[$order[$field]] ?? '';
  791. break;
  792. case ($field == 'from_user'):
  793. // 得到补货上级
  794. $fromUser = [];
  795. if (isset($deduction_user_id_arr[$item['id']])) {
  796. $deductionUserIds = array_unique($deduction_user_id_arr[$item['id']]);
  797. foreach ($deductionUserIds as $uid) {
  798. if (!isset($deduction_user_list[$uid])) {
  799. continue;
  800. }
  801. $fromUser[] = sprintf(
  802. '补货用户ID:"%s" 补货用户昵称:"%s"',
  803. $uid,
  804. $deduction_user_list[$uid]['nickname']
  805. );
  806. }
  807. }
  808. $row[] = implode(' ,', $fromUser);
  809. break;
  810. }
  811. }
  812. $rows[] = $row;
  813. }
  814. }
  815. $csv->data = $rows;
  816. $csv->export();
  817. $csv->updateDown($download, $params['mall_id']);
  818. } catch (\Exception $e) {
  819. $download->status = 3;
  820. $res = $download->save();
  821. var_dump($e->getMessage() . $e->getFile() . $e->getLine());
  822. self::setStaticError($e->getMessage());
  823. return $e->getMessage();
  824. }
  825. }
  826. }
  827. public function exportOrder(array $data)
  828. {
  829. $this->export($data);
  830. }
  831. }