OrderSubmitForm.php 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\alliance\models\pt\order;
  8. use app\constants\OptionSetting;
  9. use app\models\Address;
  10. use app\models\Cart;
  11. use app\models\common\CommonOrder;
  12. use app\models\DeliveryInfo;
  13. use app\models\FoodCart;
  14. use app\models\FoodFlag;
  15. use app\models\Goods;
  16. use app\models\GoodsBook;
  17. use app\models\Level;
  18. use app\models\LevelOrder;
  19. use app\models\LocalDeliveryFreight;
  20. use app\models\Md;
  21. use app\models\MdProfit;
  22. use app\models\OfferPrice;
  23. use app\models\Order;
  24. use app\models\OrderDetail;
  25. use app\models\PtActivity;
  26. use app\models\PtActivityOrder;
  27. use app\models\PtActivityOrderDetail;
  28. use app\models\SeckillActivity;
  29. use app\models\SeckillActivityGoods;
  30. use app\models\SeckillActivityOrderLog;
  31. use app\models\Store;
  32. use app\models\User;
  33. use app\models\UserCoupon;
  34. use app\models\Option;
  35. use app\models\AccountLog;
  36. use app\models\VerifyCardSale;
  37. use app\models\VideoGoodsList;
  38. use app\models\VideoGoodsSetting;
  39. use app\models\VideoGoodsShare;
  40. use app\modules\admin\models\maiyatian\MaiyatianForm;
  41. use app\modules\admin\models\keloop\KeloopForm;
  42. use app\plugins\adopt\models\AdoptGoods;
  43. use app\plugins\adopt\models\AdoptOrderInfo;
  44. use app\utils\CloudPrint;
  45. use app\utils\Delivery\Delivery;
  46. use app\utils\Delivery\Alipay\ADelivery;
  47. use app\utils\Delivery\WechatNewDelivery;
  48. use app\utils\Notice\NoticeSend;
  49. use app\utils\OrderNo;
  50. use app\utils\PrintOrder;
  51. use app\utils\Tools;
  52. use yii\helpers\ArrayHelper;
  53. use yii\helpers\Json;
  54. class OrderSubmitForm extends OrderForm
  55. {
  56. public $user;
  57. public $payment;
  58. public $use_integral;
  59. public $buy_level_id;
  60. public $adopt_name;
  61. public $adopt_mobile;
  62. public $order_no;
  63. public function rules()
  64. {
  65. $rules = [
  66. [['payment', 'use_integral', 'buy_level_id'], 'integer'],
  67. [['adopt_name', 'adopt_mobile', 'order_no'], 'string']
  68. ];
  69. return array_merge(parent::rules(), $rules);
  70. }
  71. public function preOrder() {
  72. if (!$this->validate()) {
  73. return [
  74. 'code' => 1,
  75. 'msg' => $this->getErrorSummary(false)[0],
  76. ];
  77. }
  78. try {
  79. $mch_list = $this->getStoreListData(true);
  80. $goods_list = [];
  81. foreach ($mch_list as $mch) {
  82. foreach ($mch['goods_list'] as $goods) {
  83. $goods_list[] = [
  84. 'name' => $goods['goods_name'],
  85. 'price' => $goods['price'],
  86. 'pic' => $goods['goods_pic'],
  87. 'num' => $goods['num'],
  88. ];
  89. }
  90. $delivery_time = $mch['delivery_time'];//送出时间
  91. }
  92. if($this->order_no){
  93. $existOrder = Order::findOne(['order_no' => $this->order_no]);
  94. if($existOrder){
  95. return [
  96. 'code' => 1,
  97. 'msg' => '单号错误0,请后退到商品页重新下单',
  98. ];
  99. }
  100. $order_no = $this->order_no;
  101. }else{
  102. $order_no = cache()->get('delivery_order_no_' . get_saas_user_id());
  103. }
  104. $local_type = Option::get(OptionSetting::STORE_LOCAL_TYPE, $this->store_id, 'store')['value'];
  105. $local_type = Option::get(OptionSetting::STORE_LOCAL_TYPE, $this->store_id, 'pay', $local_type);
  106. if($local_type['value'] == 'keloop') {
  107. if(KeloopForm::isSaasOpen()){
  108. $preAddOrder = KeloopForm::preAddOrder($this->store_id, $order_no, $this->address['longitude'], $this->address['latitude']);
  109. if ($preAddOrder['code']) {
  110. return $preAddOrder;
  111. }
  112. return [
  113. 'code' => 0,
  114. 'msg' => 'ok',
  115. 'data' => [
  116. "resultcode" => 0,
  117. 'fee' => (float)$preAddOrder['data']['fee'],
  118. 'fee_data' => $preAddOrder['data']['fee_data'],
  119. ],
  120. 'order_no' => $order_no,
  121. ];
  122. }
  123. return [
  124. 'code' => 1,
  125. 'msg' => '快跑者配送没有配置',
  126. ];
  127. }
  128. if($local_type['value'] == 'maiyatian') {//麦芽田
  129. if(MaiyatianForm::isopen($this->store_id)){
  130. $getFreight = LocalDeliveryFreight::getFreight($this->store_id, $this->address, $delivery_time, LocalDeliveryFreight::TYPE_MAIYATIAN, $goods_list);
  131. if($getFreight['code'] != 0){
  132. return $getFreight;
  133. }
  134. $freight = $getFreight['data'];
  135. $preAddOrder = MaiyatianForm::preAddOrder($this->store_id, $order_no, $freight);
  136. return [
  137. 'code' => 0,
  138. 'msg' => 'ok',
  139. 'data' => [
  140. "resultcode" => 0,
  141. // 'fee' => (float)MaiyatianForm::getConf($this->store_id, 'cyy_delivery_fee'),
  142. 'fee' => (float)$freight,
  143. ],
  144. 'order_no' => $order_no,
  145. ];
  146. return $preAddOrder;
  147. }
  148. return [
  149. 'code' => 1,
  150. 'msg' => '麦芽田没有配置',
  151. ];
  152. } elseif($local_type['value'] == 'aggregate') {//聚合配送
  153. if(is_alipay_platform()){
  154. $this->address_id || $this->address_id = 220;
  155. $res = ADelivery::createOrder(1, $this->store_id, get_mini_id(), get_saas_user()->ali_user_id, $goods_list, $order_no, $this->address_id);;
  156. return array_merge($res, ['order_no' => $order_no]);
  157. }
  158. $store = Store::findOne($this->store_id);
  159. if (intval($store->wechat_delivery_type) === 0) {
  160. return array_merge(Delivery::preAddOrder($goods_list, $order_no), ['order_no' => $order_no]);
  161. } else {
  162. $form = new WechatNewDelivery();
  163. $result = $form->preAddOrder([
  164. 'address' => ArrayHelper::toArray($this->address),
  165. 'goods_list' => $goods_list,
  166. 'store_id' => $this->store_id,
  167. 'md_id' => get_md_id()
  168. ]);
  169. if ($result['code'] === 0) {
  170. DeliveryInfo::deleteAll(['order_no' => $order_no, 'store_id' => get_store_id(), 'status' => 0]);
  171. // 存预下单表
  172. $delivery_info = new DeliveryInfo();
  173. $delivery_info->store_id = get_store_id();
  174. $delivery_info->order_no = $order_no;
  175. $delivery_info->fee = bcdiv($result['data']['fee'], 100, 2);
  176. $delivery_info->delivery_type = 0;
  177. $delivery_info->created_at = time();
  178. $delivery_info->is_local = DeliveryInfo::IS_LOCAL_NO;
  179. $serial_num = DeliveryInfo::find()->where(['>','created_at',strtotime(date('Y-m-d'))])->orderBy('serial_num desc')->asArray()->one()['serial_num'];
  180. $delivery_info->serial_num = $serial_num > 0 ? $serial_num + 1 : 1;
  181. $delivery_info->md_id = get_md_id();
  182. $delivery_info->wechat_delivery_type = 1;
  183. $delivery_info->save();
  184. return array_merge($result, ['order_no' => $order_no]);
  185. } else {
  186. return $result;
  187. }
  188. // return array_merge($form->preAddOrder([
  189. // 'address' => ArrayHelper::toArray($this->address),
  190. // 'goods_list' => $goods_list,
  191. // 'store_id' => $this->store_id,
  192. // 'md_id' => 0
  193. // ]), ['order_no' => $order_no]);
  194. }
  195. } elseif(in_array($local_type['value'], ['self', 'self_store'])) {//平台自配
  196. $type = LocalDeliveryFreight::TYPE_LOCAL;
  197. if ($local_type['value'] === 'self_store') {
  198. $type = LocalDeliveryFreight::TYPE_STORE_LOCAL;
  199. }
  200. $getFreight = LocalDeliveryFreight::getFreight($this->store_id, $this->address, $delivery_time, $type, $goods_list);
  201. if($getFreight['code'] != 0){
  202. return $getFreight;
  203. }
  204. $freight = $getFreight['data'];
  205. DeliveryInfo::deleteAll(['order_no' => $order_no, 'store_id' => get_store_id(), 'status' => 0]);
  206. // 存预下单表
  207. $delivery_info = new DeliveryInfo();
  208. $delivery_info->store_id = get_store_id();
  209. $delivery_info->order_no = $order_no;
  210. $delivery_info->fee = $freight;
  211. $delivery_info->delivery_type = 0;
  212. $delivery_info->created_at = time();
  213. $delivery_info->is_local = DeliveryInfo::IS_LOCAL_YSE;
  214. $delivery_info->is_store_delivery_type = intval($local_type['value'] === 'self_store');
  215. $serial_num = DeliveryInfo::find()->where(['>','created_at',strtotime(date('Y-m-d'))])->orderBy('serial_num desc')->asArray()->one()['serial_num'];
  216. $delivery_info->serial_num = $serial_num > 0 ? $serial_num + 1 : 1;
  217. $delivery_info->save();
  218. return [
  219. 'code' => 0,
  220. 'msg' => 'success',
  221. 'order_no' => $order_no,
  222. 'data' => $getFreight['info'],
  223. ];
  224. /* end */
  225. // return [
  226. // 'code' => 0,
  227. // 'data' => [
  228. // 'goods_list' => $goods_list,
  229. // 'order_no' => $order_no,
  230. // 'test' => [
  231. // 'address' => $address,
  232. // 'store' => $store,
  233. // 'distance' => $distance,
  234. // 'delivery_time' => $delivery_time,
  235. // 'delivery_time_stamp' => $delivery_time_stamp,
  236. // 'LocalDeliveryFreight' => $data,
  237. // 'freight_detail' => $freight_detail,
  238. // 'freight' => $freight,
  239. // ]
  240. // ],
  241. // 'msg' => '平台自配'
  242. // ];
  243. }
  244. } catch (\Exception $e) {
  245. return [
  246. 'code' => 1,
  247. 'msg' => $e->getMessage()
  248. ];
  249. }
  250. }
  251. public function save()
  252. {
  253. if (!$this->validate())
  254. return [
  255. 'code' => 1,
  256. 'msg' => $this->getErrorSummary(false)[0],
  257. ];
  258. try {
  259. $mchListData = $this->getStoreListData(true);
  260. } catch (\Exception $e) {
  261. return [
  262. 'code' => 1,
  263. 'msg' => $e->getMessage()
  264. ];
  265. }
  266. $order_id_list = [];
  267. $md_select = 0;
  268. /**
  269. * @var $address Address
  270. */
  271. $saas_user = get_saas_user();
  272. $this->user = User::findOne(['binding' => $saas_user->mobile,'store_id' => get_store_id(),'is_delete'=>0]);
  273. $address = (object)($this->address);
  274. $t = \Yii::$app->db->beginTransaction();
  275. foreach ($mchListData as &$mch) {
  276. $mch_goods = $mch['goods_list'];
  277. if ($mch_goods) {
  278. $checkMchData = $this->checkMchData($mch);
  279. if ($checkMchData['code'] == 1) {
  280. $t->rollBack();
  281. return $checkMchData;
  282. }
  283. $level_price = 0;
  284. $total_price = 0;
  285. $is_have_express = false;
  286. $is_have_shop = false;
  287. $is_have_delivery = 0;
  288. if ($mch['send'] == 'express') {
  289. $is_have_express = true;
  290. }
  291. if ($mch['send'] == 'shop') {// || get_md_id()
  292. $is_have_shop = true;
  293. if (!empty($mch['shop']) && !empty($mch['shop']['id'])) {
  294. $md_select = $mch['shop']['id'];
  295. }
  296. }
  297. $is_delivery = OfferPrice::findOne([
  298. 'store_id' => get_store_id(),
  299. 'is_delete' => 0
  300. ]);
  301. $store_data = Store::findOne(get_store_id());
  302. if ($mch['send'] == 'delivery') {
  303. $local_type = Option::get(OptionSetting::STORE_LOCAL_TYPE, get_store_id(), 'store')['value'];
  304. $local_type = Option::get(OptionSetting::STORE_LOCAL_TYPE, get_store_id(), 'pay', $local_type);
  305. $is_have_express = true;
  306. $delivery_rules = json_decode($is_delivery->delivery_rules, true);
  307. if ($is_delivery->delivery_type == 1 && !empty($delivery_rules)) {
  308. $conf = [
  309. 'shop_tag' => $store_data->coordinate,
  310. 'deliveryRules' => $delivery_rules
  311. ];
  312. $deliveryRules = $this->canDeliver($address, $conf);
  313. if (!$deliveryRules['can_deliver']) {
  314. return [
  315. 'code' => 1,
  316. 'msg' => '当前订单超出配送距离'
  317. ];
  318. }
  319. }
  320. if ($local_type['value'] == 'keloop') { //快跑者配送
  321. if (!KeloopForm::isSaasOpen()) {
  322. $t->rollBack();
  323. return [
  324. 'code' => 1,
  325. 'msg' => '商城未设置有效配送方式'
  326. ];
  327. }
  328. }
  329. if($local_type['value'] == 'maiyatian') {//麦芽田
  330. $maiyatian = MaiyatianForm::isopen($this->store_id);
  331. if (!$maiyatian) {
  332. $t->rollBack();
  333. return [
  334. 'code' => 1,
  335. 'msg' => '商城未设置有效配送方式'
  336. ];
  337. }
  338. } elseif($local_type['value'] == 'aggregate') {//聚合配送
  339. $store = Store::findOne($this->store_id);
  340. if (intval($store->wechat_delivery_type) === 0) {
  341. if ($store->delivery_type == 0) {
  342. $t->rollBack();
  343. return [
  344. 'code' => 1,
  345. 'msg' => '商城未设置有效配送方式'
  346. ];
  347. }
  348. $res = Delivery::getBindAccount();
  349. // 下单时判断是否可以同城配送
  350. if (empty($res['data']['shop_list'])) {
  351. $t->rollBack();
  352. return [
  353. 'code' => 1,
  354. 'msg' => '当前未绑定运力账号,暂不能保存选择同城配送方式'
  355. ];
  356. }
  357. $shop_list = $res['data']['shop_list'];
  358. $delivery_arr = array_column($shop_list, 'delivery_id');
  359. $delivery_arr[] = 'TEST';
  360. $delivery_arr_id = array_column($shop_list, null, 'delivery_id');
  361. if (!in_array(Delivery::$deliveryIdArr[$store->delivery_type], $delivery_arr) || $delivery_arr_id[Delivery::$deliveryIdArr[$store->delivery_type]]['audit_result'] != 0) {
  362. $t->rollBack();
  363. return [
  364. 'code' => 1,
  365. 'msg' => '当前账号未在微信后台绑定或者并未审核通过'
  366. ];
  367. }
  368. }
  369. } elseif(in_array($local_type['value'], ['self', 'self_store'])) {//平台自配
  370. if(empty($mch['delivery_time'])){
  371. $store_id = $local_type['value'] === 'self_store' ? $this->store_id : 0;
  372. $setting = json_decode(Option::get(OptionSetting::LOCAL_DELIVERY_SETTING, $store_id, '', '{}')['value'], true);
  373. $mch['delivery_time'] = date('Y-m-d H:i:s', time() + 90 * 60);
  374. if(!empty($setting['default_time']) && !empty($setting['default_time']['value'])){
  375. $mch['delivery_time'] = date('Y-m-d H:i:s', time() + ($setting['default_time']['value'] * 60));
  376. }
  377. }
  378. }
  379. $is_have_delivery = true;
  380. }
  381. // if (!in_array($mch['send'], ['express', 'shop'])) {
  382. // return [
  383. // 'code' => 1,
  384. // 'msg' => '请选择快递或到店自提'
  385. // ];
  386. // }
  387. foreach ($mch_goods as $v) {
  388. $level_price += $v['level_price'];
  389. $total_price += isset($v['total_price']) ? $v['total_price'] : $v['price'];
  390. }
  391. $mch['level_price'] = $level_price;
  392. $mch['total_price'] = $total_price;
  393. // $mch['total_integral'] = $total_integral; //积分兑换
  394. $payPrice = $this->getPayPrice($mch);
  395. $order = new PtActivityOrder();
  396. $order->is_platform = 1;
  397. // 订单来源
  398. if (is_h5()) {
  399. $order->order_origin = Order::ORDER_SOURCE_WEB;
  400. }
  401. $order->store_id = get_store_id();
  402. $user = User::findOne(['binding' => get_saas_user()->mobile, 'is_delete' => 0, 'store_id' => get_store_id()]);
  403. $order->user_id = $this->user_id ?: $user->id;
  404. $order->saas_id = get_saas_user_id();
  405. if ($is_have_delivery) {
  406. if($this->order_no){
  407. $order->order_no = $this->order_no;
  408. }else{
  409. $order->order_no = cache()->get('delivery_order_no_' . get_saas_user_id());
  410. }
  411. $existOrder = Order::findOne(['order_no' => $order->order_no]);
  412. if($existOrder){
  413. $t->rollBack();
  414. return [
  415. 'code' => 1,
  416. 'msg' => '单号错误1,请后退到商品页重新下单',
  417. ];
  418. }
  419. } else {
  420. $order->order_no = OrderNo::getOrderNo(OrderNo::ORDER_PT);
  421. }
  422. $order->pay_price = $payPrice;
  423. $order->pt_number = $mch['pt_number'];
  424. if ($this->head_integral > 0) {
  425. if ($this->head_integral > get_user()->integral) {
  426. return [
  427. 'code' => 1,
  428. 'msg' => '开团积分不足'
  429. ];
  430. }
  431. $order->head_integral = $this->head_integral;
  432. }
  433. // 订单类型
  434. // 是否是平台小程序订单
  435. if (get_md_id()) {
  436. $order->md_id = get_md_id();
  437. }
  438. if($md_select > 0){
  439. $order->md_id = $md_select;
  440. }
  441. if($this->send_price){
  442. $order->send_price = $this->send_price;
  443. }
  444. if($this->take_price){
  445. $order->take_price = $this->take_price;
  446. }
  447. $order->created_at = time();
  448. $order->content = $mch['content'] ?? '';
  449. $order->is_offline = $is_have_shop ? 1 : 0;
  450. $order->remark = $mch['remark'];
  451. if ($this->payment == 2) {
  452. $order->pay_type = 2;
  453. $order->is_pay = 0;
  454. }
  455. if ($this->payment == 3) {
  456. $order->pay_type = 3;
  457. $order->is_pay = 0;
  458. }
  459. // 线下支付
  460. if ($this->payment == 6) {
  461. $order->pay_type = 6;
  462. $order->is_pay = 0;
  463. }
  464. if ($is_have_express || get_md_id()) {
  465. $order->address = $address->province . $address->city . $address->district . $address->detail;
  466. $order->mobile = $address->mobile;
  467. $order->name = $address->name;
  468. $order->province_id = $address->province_id;
  469. $order->city_id = $address->city_id;
  470. $order->district_id = $address->district_id;
  471. $order->address_data = json_encode([
  472. 'province' => trim($address->province),
  473. 'city' => trim($address->city),
  474. 'district' => trim($address->district),
  475. 'detail' => trim($address->detail),
  476. 'latitude' => $address->latitude,
  477. 'longitude' => $address->longitude,
  478. ], JSON_UNESCAPED_UNICODE);
  479. $order->express_price = $mch['express_price'];
  480. $order->total_price = $mch['total_price'] + $mch['express_price'];
  481. }
  482. //获取代理配置信息
  483. $store = Store::findOne($this->store_id);
  484. //支付金额 * 店铺让利比例 * 代理商分润比例
  485. // $admin_profit = Option::get('admin_profit', 0, 'saas', 0)['value'];
  486. if (!empty($store->transfer_profit)) {
  487. $order->ag_rebate = $payPrice * ($store->transfer_profit / 100);
  488. }
  489. if ($is_have_delivery) {
  490. $cacheK = 'is_have_delivery_' . $order->order_no;
  491. $cacheV = cache()->get($cacheK);
  492. $deliveryInfo = DeliveryInfo::find()->where(['order_no' => $order->order_no])->one();
  493. if(!$deliveryInfo){
  494. $t->rollBack();
  495. if($cacheV){
  496. return [
  497. 'code' => 1,
  498. 'msg' => '配送单不存在,请返回商品详情页重新下单。' . $cacheV . $cacheK
  499. ];
  500. }
  501. cache()->set($cacheK, 1, 180);
  502. $this->order_no = '';
  503. $preOrder = $this->preOrder();
  504. if($preOrder['code'] != 0){
  505. return $preOrder;
  506. }else{
  507. $this->order_no = '';
  508. return $this->save();
  509. }
  510. } else {
  511. if (intval($deliveryInfo->wechat_delivery_type) === 1) {
  512. $goods_list = [];
  513. //foreach ($mch as $mch_item) {
  514. foreach ($mch['goods_list'] as $goods) {
  515. $goods_list[] = [
  516. 'name' => $goods['goods_name'],
  517. 'price' => $goods['price'],
  518. 'pic' => $goods['goods_pic'],
  519. 'num' => $goods['num'],
  520. 'weight' => $goods['weight'],
  521. ];
  522. }
  523. //}
  524. $form = new WechatNewDelivery();
  525. $result = $form->preAddOrder([
  526. 'address' => ArrayHelper::toArray($this->address),
  527. 'goods_list' => $goods_list,
  528. 'store_id' => $this->store_id,
  529. 'md_id' => get_md_id()
  530. ]);
  531. // $result = $form->addOrder([
  532. // 'address' => ArrayHelper::toArray($this->address),
  533. // 'goods_list' => $goods_list,
  534. // 'store_id' => $order->store_id,
  535. // 'md_id' => $order->md_id ?: 0,
  536. // 'order_no' => $order->order_no,
  537. // 'store_user' => ArrayHelper::toArray(get_user()),
  538. // 'order_seq' => $deliveryInfo->serial_num,
  539. // 'order_detail_path' => '/order/order-detail/order-detail?id=' . $order->id,
  540. // ]);
  541. if ($result['code'] === 0) {
  542. $deliveryInfo = DeliveryInfo::findOne(['order_no' => $order->order_no]);
  543. if (floatval($deliveryInfo->fee) !== floatval(bcdiv($result['data']['fee'], 100, 2))) {
  544. $t->rollBack();
  545. return [
  546. 'code' => 1,
  547. 'msg' => '配送费错误,请重新下单'
  548. ];
  549. }
  550. } else {
  551. $t->rollBack();
  552. return $result;
  553. }
  554. }
  555. }
  556. $order->total_price += $deliveryInfo->fee;
  557. $order->pay_price += $deliveryInfo->fee;
  558. }
  559. if ($order->save()) {
  560. // 绑定上下级
  561. $user = User::findOne($this->user_id);
  562. if ($user && $user->parent_user_id) {
  563. CommonOrder::saveParentId($user->parent_user_id);
  564. }
  565. // 处理订单生成之后其他相关数据
  566. $orderRes = $this->insertData($mch, $order);
  567. if ($orderRes['code'] == 1) {
  568. $t->rollBack();
  569. return $orderRes;
  570. }
  571. $printer_order = new PrintOrder($order->store_id, $order->id, 'order', 0, 0, 0, $order['mch_id']);
  572. $printer_order->print_order();
  573. // 订单提交完成发送消息
  574. NoticeSend::OrderSubmit($this->user_id, $order->mobile, $order->order_no, $order->pay_price, $mch_goods[0]['goods_name'], 0, $order->store_id);
  575. $order_id_list[] = $order->id;
  576. } else {
  577. $t->rollBack();
  578. return [
  579. 'code' => 0,
  580. 'msg' => implode(';', array_values($order->firstErrors))
  581. ];
  582. }
  583. }
  584. }
  585. if (count($order_id_list) > 0) {
  586. $t->commit();
  587. $store = Store::findOne($this->store_id);
  588. $order_id = $order_id_list[0];
  589. if($order->take_price > 0){
  590. if (($order->pay_price - $order->take_price) >= 0) {
  591. $order->pay_price -= $order->take_price;
  592. $order->total_price -= $order->take_price;
  593. } else {
  594. $order->take_price -= $order->pay_price;
  595. $order->total_price = $order->pay_price = 0;
  596. }
  597. $order->save();
  598. }
  599. CloudPrint::doPrint($order_id, 0, $this->store_id);
  600. return [
  601. 'code' => 0,
  602. 'msg' => '订单提交成功',
  603. 'data' => (object)[
  604. 'order_id' => $order_id_list[0],
  605. 'add_time' => $order->created_at,
  606. 'order_price'=> $order->pay_price,
  607. 'douyin_url' => $store->douyin_url,
  608. ],
  609. ];
  610. } else {
  611. $t->rollBack();
  612. return [
  613. 'order_list' => $order_id_list,
  614. 'order_price'=> $order->pay_price
  615. ];
  616. }
  617. }
  618. private function reduceIntegral($order) {
  619. $integral = Json::decode($order->integral);
  620. // 减去当前用户账户积分
  621. if ($integral['forehead_integral'] > 0) {
  622. $user = User::findOne($order->user_id);
  623. $before = $user->integral;
  624. $user->integral -= $integral['forehead_integral'];
  625. if ($user->save()) {
  626. $log = new AccountLog();
  627. $log->store_id = $order->store_id;
  628. $log->user_id = $user->id;
  629. $log->type = AccountLog::TYPE_INTEGRAL;
  630. $log->log_type = AccountLog::LOG_TYPE_EXPEND;
  631. $log->amount = $integral['forehead_integral'];
  632. $log->desc = "订单积分抵扣支付,订单号为:{$order->order_no}。";
  633. $log->before = $before;
  634. $log->after = $user->integral;
  635. $log->operator = '';
  636. $log->operator_id = 0;
  637. $log->operator_type = AccountLog::TYPE_OPERATOR_NORMAL;
  638. $log->created_at = time();
  639. $log->order_id = $order->id;
  640. $log->order_type = AccountLog::TYPE_PLATFORM_ORDER;
  641. $log->save();
  642. }
  643. }
  644. }
  645. /**
  646. * 判断是否可以配送并计算费用
  647. */
  648. private function canDeliver($address, $conf)
  649. {
  650. // 解析商家地址的经纬度
  651. list($shopLon, $shopLat) = explode(',', $conf['shop_tag']);
  652. // 计算距离
  653. $distance = Tools::getDistance((float)$shopLat, (float)$shopLon, $address->latitude ?: $address['latitude'], $address->longitude ?: $address['longitude']);
  654. if (strpos($distance, 'km') !== false) {
  655. $distance = floatval(explode('km', $distance)[0]);
  656. } elseif (strpos($distance, 'm') !== false) {
  657. $distance = floatval(explode('m', $distance)[0]) / 1000;
  658. }
  659. foreach ($conf['deliveryRules'] as $rule) {
  660. if ($rule['start'] <= $distance && $distance <= $rule['end']) {
  661. return [
  662. 'can_deliver' => true,
  663. 'distance' => $distance,
  664. 'delivery_price' => $rule['price'],
  665. 'delivery_range' => [$rule['start'], $rule['end']]
  666. ];
  667. }
  668. }
  669. return ['can_deliver' => false, 'distance' => $distance, 'delivery_price' => null, 'delivery_range' => null];
  670. }
  671. public function getNo($attrStr,$searchAttrIds){
  672. $attr = json_decode($attrStr,true);
  673. foreach ($attr as $item){
  674. $attrIds = array_column($item['attr_list'],'attr_id');
  675. if ($attrIds == $searchAttrIds){
  676. return $item['no'];
  677. }
  678. }
  679. }
  680. // 获得实际支付金额
  681. private function getPayPrice($mch)
  682. {
  683. $goods_list = $mch['goods_list'];
  684. $payPrice = $mch['level_price'];
  685. if (isset($mch['use_integral']) && $mch['use_integral']) {
  686. $payPrice -= $mch['integral']['forehead'];
  687. }
  688. if (isset($mch['picker_coupon'])) {
  689. $pickerCoupon = $mch['picker_coupon'];
  690. if ($pickerCoupon['sub_price'] > 0) {
  691. $coupon_price = 0;
  692. if ($pickerCoupon['appoint_type'] == 1 && $pickerCoupon['cat_id_list'] != null) {
  693. foreach ($goods_list as $goods) {
  694. foreach ($goods['cat_id'] as $v1) {
  695. if (in_array($v1, $pickerCoupon['cat_id_list'])) {
  696. $coupon_price += floatval($goods['level_price']);
  697. break;
  698. };
  699. };
  700. }
  701. } else if ($pickerCoupon['appoint_type'] == 2 && $pickerCoupon['goods_id_list'] != null) {
  702. foreach ($goods_list as $goods) {
  703. if (in_array($goods['goods_id'], $pickerCoupon['goods_id_list'])) {
  704. $coupon_price += floatval($goods['level_price']);
  705. };
  706. }
  707. };
  708. if ($pickerCoupon['sub_price'] > $coupon_price && $coupon_price > 0) {
  709. $payPrice -= $coupon_price;
  710. } else {
  711. $payPrice -= $pickerCoupon['sub_price'];
  712. }
  713. }
  714. }
  715. // Todo 此处有待确认算法是否正确 by Syan
  716. // $payPrice = $payPrice > 0 ? $payPrice : 0.01;
  717. if ($mch['express_price'] > 0) {
  718. if (isset($mch['send']) && $mch['send'] == 'express') {
  719. $payPrice += $mch['express_price'];
  720. } else {
  721. foreach ($goods_list as $goods) {
  722. if (isset($goods['send']) && $goods['send'] == 'express') {
  723. $payPrice += $mch['express_price'];
  724. break;
  725. }
  726. }
  727. }
  728. }
  729. if ($this->buy_level_id) {
  730. $level = Level::findOne($this->buy_level_id);
  731. $payPrice += ($level->price * 1);
  732. }
  733. return $payPrice > 0 ? $payPrice : 0;
  734. }
  735. // 检查数据
  736. private function checkMchData($mch)
  737. {
  738. if (empty($mch['goods_list'])) {
  739. return [
  740. 'code' => 1,
  741. 'msg' => '商品不存在或已删除'
  742. ];
  743. }
  744. $checkFormData = $this->checkFormData($mch);
  745. if ($checkFormData['code'] == 1) {
  746. return $checkFormData;
  747. }
  748. $checkSendType = $this->checkSendType($mch);
  749. if ($checkSendType['code'] == 1) {
  750. return $checkSendType;
  751. }
  752. // $checkCoupon = $this->checkCoupon($mch);
  753. // if ($checkCoupon['code'] == 1) {
  754. // return $checkCoupon;
  755. // }
  756. // $checkGoods = $this->checkGoods($mch);
  757. // if ($checkGoods['code'] == 1) {
  758. // return $checkGoods;
  759. // }
  760. return ['code' => 0, 'msg' => 'success'];
  761. }
  762. // 检测优惠券是否可使用
  763. private function checkCoupon($mch)
  764. {
  765. if (empty($mch['picker_coupon'])) {
  766. return [
  767. 'code' => 0,
  768. 'msg' => ''
  769. ];
  770. }
  771. $ok = false;
  772. foreach ($mch['coupon_list'] as $item) {
  773. if ($item['user_coupon_id'] == $mch['picker_coupon']['user_coupon_id']) {
  774. $ok = true;
  775. }
  776. }
  777. if (!$ok) {
  778. return [
  779. 'code' => 1,
  780. 'msg' => '该优惠券已过期'
  781. ];
  782. } else {
  783. return [
  784. 'code' => 0,
  785. 'msg' => ''
  786. ];
  787. }
  788. }
  789. // 检测发货方式
  790. private function checkSendType($mch)
  791. {
  792. if ($mch['mch_id'] == 0) {
  793. if (!$this->address) {
  794. return [
  795. 'coe' => 1,
  796. 'msg' => '收货地址不存在'
  797. ];
  798. }
  799. if ($mch['offer_rule'] && $mch['offer_rule']['is_allowed'] == 1) {
  800. return [
  801. 'code' => 1,
  802. 'msg' => $mch['offer_rule']['msg']
  803. ];
  804. }
  805. if ($mch['is_area'] == 1 && $mch['send'] == 'express') {
  806. return [
  807. 'code' => 1,
  808. 'msg' => '所选地区自营商品暂时无货'
  809. ];
  810. }
  811. }
  812. return ['code' => 0, 'msg' => ''];
  813. }
  814. // 检测自定义表单
  815. private function checkFormData($mch)
  816. {
  817. foreach ($mch['goods_list'] as $goods) {
  818. if (isset($goods['form']['code'])) {
  819. return $goods['form'];
  820. }
  821. if (!isset($goods['form'])) {
  822. continue;
  823. }
  824. $form = $goods['form'];
  825. if ($form['is_form'] == 1) {
  826. $form_list = $form['list'];
  827. foreach ($form_list as $index => $value) {
  828. if ($value['required'] == 1) {
  829. if (in_array($value['type'], ['radio', 'checkbox'])) {
  830. $is_true = false;
  831. foreach ($value['default_list'] as $k => $v) {
  832. if ($v['checked'] == true) {
  833. $is_true = true;
  834. }
  835. }
  836. if (!$is_true) {
  837. return [
  838. 'code' => 1,
  839. 'msg' => '请填写' . $form['name'] . ',加“*”为必填项',
  840. 'name' => $value['name']
  841. ];
  842. }
  843. } else {
  844. if (empty($value['default']) && strlen($value['default']) == 0) {
  845. return [
  846. 'code' => 1,
  847. 'msg' => '请填写' . $form['name'] . ',加“*”为必填项',
  848. 'name' => $value['name']
  849. ];
  850. }
  851. }
  852. }
  853. }
  854. }
  855. }
  856. return [
  857. 'code' => 0,
  858. 'msg' => ''
  859. ];
  860. }
  861. // 检测商品相关
  862. private function checkGoods($mch)
  863. {
  864. \Yii::warning($mch);
  865. foreach ($mch['goods_list'] as $goods) {
  866. $attr_id_list = [];
  867. foreach ($goods['attr_list'] as $item) {
  868. array_push($attr_id_list, $item['attr_id']);
  869. }
  870. $_goods = Goods::find()->where('id = ' . $goods['goods_id'] . ' for update')->one();
  871. $is_install = $this->goodsIsInstall($goods['goods_id']);
  872. if ($is_install !== 2) {
  873. $store = Store::findOne(get_store_id());
  874. $store_address = [
  875. 'province_id' => $store->province_id,
  876. 'city_id' => $store->city_id,
  877. 'district_id' => $store->district_id,
  878. ];
  879. $address = $is_install === 1 ? $this->address : $store_address;
  880. $result = $this->goodsIsGoodsAgent($address, $goods['goods_id']);
  881. if ($result['code'] !== 0) {
  882. return $result;
  883. }
  884. }
  885. }
  886. return ['code' => 0, 'msg' => ''];
  887. }
  888. public function getOrderNo()
  889. {
  890. $order_no = null;
  891. while (true) {
  892. $order_no = date('YmdHis') . mt_rand(100000, 999999);
  893. $exist_order_no = Order::find()->where(['order_no' => $order_no])->exists();
  894. if (!$exist_order_no) {
  895. break;
  896. }
  897. }
  898. return $order_no;
  899. }
  900. // 优惠券可优惠的商品总额计算
  901. private function pickerGoods(&$mch)
  902. {
  903. $totalPrice = 0;
  904. $pickerCoupon = $mch['picker_coupon'];
  905. if (empty($pickerCoupon)) {
  906. return;
  907. }
  908. foreach ($mch['goods_list'] as $item) {
  909. if ($pickerCoupon['appoint_type'] == 1) {
  910. if ($pickerCoupon['cat_id_list'] !== null) {
  911. $catIdList = $pickerCoupon['cat_id_list'];
  912. if (array_intersect($item['cat_id'], $catIdList)) {
  913. $totalPrice += $item['price'];
  914. $mch['picker_coupon']['goods_id'][] = $item['goods_id'];
  915. }
  916. } else {
  917. $totalPrice += $item['price'];
  918. $mch['picker_coupon']['goods_id'][] = $item['goods_id'];
  919. }
  920. } else if ($pickerCoupon['appoint_type'] == 2) {
  921. if ($pickerCoupon['goods_id_list'] !== null) {
  922. $goodsIdList = $pickerCoupon['goods_id_list'];
  923. if (in_array($item['goods_id'], $goodsIdList)) {
  924. $totalPrice += $item['price'];
  925. $mch['picker_coupon']['goods_id'][] = $item['goods_id'];
  926. }
  927. } else {
  928. $totalPrice += $item['price'];
  929. $mch['picker_coupon']['goods_id'][] = $item['goods_id'];
  930. }
  931. } else {
  932. $totalPrice += $item['price'];
  933. $mch['picker_coupon']['goods_id'][] = $item['goods_id'];
  934. }
  935. }
  936. $mch['picker_coupon']['total_price'] = $totalPrice;
  937. }
  938. /**
  939. * @param $mch
  940. * @param $order PtActivityOrder
  941. * @return array
  942. */
  943. private function insertData($mch, $order)
  944. {
  945. // 计算商品相关
  946. $goods_list = $mch['goods_list'];
  947. $goodsPrice = 0;
  948. // 计算商品分润
  949. $goods_profit = 0;
  950. foreach ($goods_list as $goods) {
  951. // if ($goods['product_type'] == Goods::GOODS_TYPE_ADOPT) {
  952. // $adopt_order_info = new AdoptOrderInfo();
  953. // $adopt_order_info->name = $this->adopt_name;
  954. // $adopt_order_info->mobile = $this->adopt_mobile;
  955. // $adopt_order_info->order_id = $order->id;
  956. // $adopt_order_info->store_id = $this->store_id;
  957. // $adopt_goods = AdoptGoods::find()->where(['goods_id' => $goods['id']])->one();
  958. // $adopt_order_info->mature_time = time() + $adopt_goods->growth_cycle * 86400;
  959. //
  960. // if (!$adopt_order_info->save()) {
  961. // return [
  962. // 'code' => 1,
  963. // 'msg' => '订单提交失败,请稍后再重试',
  964. // 'error' => $adopt_order_info->errors
  965. // ];
  966. // }
  967. // }
  968. // 存入下单表单
  969. if ($goods['form'] && $goods['form']['is_form'] == 1) {
  970. foreach ($goods['form']['list'] as $index => $value) {
  971. $order_form = new \app\models\OrderForm();
  972. $order_form->store_id = $this->store_id;
  973. $order_form->order_id = $order->id;
  974. $order_form->goods_id = $goods['id'];
  975. $order_form->key = $value['name'];
  976. $order_form->value = $value['default'];
  977. $order_form->type = $value['type'];
  978. $order_form->is_delete = 0;
  979. $order_form->save();
  980. }
  981. }
  982. // 删除购物车
  983. if (isset($goods['cart_id'])) {
  984. Cart::updateAll(['is_delete' => 1], ['id' => $goods['cart_id']]);
  985. }
  986. $order_detail = new PtActivityOrderDetail();
  987. $order_detail->order_id = $order->id;
  988. $order_detail->goods_id = $goods['goods_id'];
  989. $order_detail->num = $goods['num'];
  990. $order_detail->is_level = 0;
  991. $order_detail->activity_id = $this->pt_activity_id;
  992. $payPrice = $goods['level_price'];
  993. $payPrice = $payPrice >= 0 ? sprintf('%.2f', $payPrice) : 0;
  994. $goodsPrice += $payPrice;
  995. $orderPrice = floatval($order->pay_price) - floatval($order->express_price);
  996. if ($goodsPrice > $orderPrice) {
  997. $payPrice = $payPrice - ($goodsPrice - $orderPrice);
  998. $goodsPrice = $orderPrice;
  999. }
  1000. $order_detail->total_price = $payPrice;
  1001. // 计算单个商品可分红金额
  1002. $profit = $goods['rate_type'] == 0 ? floatval($payPrice * $goods['rate'] / 100) : floatval($goods['rate']) * $goods['num'];
  1003. $goods_profit += $profit;
  1004. $order_detail->profit = $profit;
  1005. $order_detail->is_delete = 0;
  1006. $order_detail->attr = json_encode($goods['attr_list'], JSON_UNESCAPED_UNICODE);
  1007. $goods_info = Goods::findOne($goods['goods_id']);
  1008. $order_detail->pic = $goods['goods_pic'] ? $goods['goods_pic'] : $goods_info->cover_pic;
  1009. $order_detail->goods_name = $goods_info ? $goods_info->name : $goods['goods_name'];
  1010. $order_detail->goods_info = $goods_info ? Json::encode($goods_info->toArray()) : json::encode([]);
  1011. $order_detail->delivery_type = $mch['send'] == 'express' ? OrderDetail::GOODS_DELIVERY_EXPRESS : OrderDetail::GOODS_DELIVERY_SHOP;
  1012. $attr_id_list = [];
  1013. foreach ($goods['attr_list'] as $item) {
  1014. array_push($attr_id_list, $item['attr_id']);
  1015. }
  1016. if (!$order_detail->save()) {
  1017. return [
  1018. 'code' => 1,
  1019. 'msg' => '订单提交失败,请稍后再重试',
  1020. 'error' => $order_detail->errors[0]
  1021. ];
  1022. }
  1023. }
  1024. // goods_profit 计算之后存入订单表中
  1025. $order->profit = $goods_profit;
  1026. $order->save();
  1027. // 计算门店收益
  1028. if ($order->is_offline) {
  1029. // MdProfit::handleProfit($order->id, $order->total_price, $order->total_price, $order->md_id);
  1030. }
  1031. return [
  1032. 'code' => 0,
  1033. 'msg' => ''
  1034. ];
  1035. }
  1036. }