ShopOrderModel.php 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936
  1. <?php
  2. namespace app\common\model;
  3. use app\common\model\ShopGoodsModel as Goods;
  4. use app\common\model\UserModel as User;
  5. use app\common\model\UserMoneyModel as UserMoney;
  6. use app\api\services\ExpressServices;
  7. use jobs\ShopOrderJob;
  8. use mysql_xdevapi\Result;
  9. use services\CacheServices;
  10. use think\db\concern\ResultOperation;
  11. use think\Exception;
  12. use think\facade\Db;
  13. use think\Model;
  14. use app\common\model\ShopOrderGoodsModel as OrderGoods;
  15. use app\common\model\ShopOrderShippingModel as OrderShipping;
  16. use jobs\ShopBonusJob;
  17. use utils\Json;
  18. use utils\Queue;
  19. class ShopOrderModel extends Model
  20. {
  21. protected $name = 'shop_order';
  22. const waitPay = 0; //待支付
  23. const waitDelivery = 1; //待发货
  24. const doneDelivery = 2; //已发货
  25. const doneOrder = 3; //交易完成
  26. const cancelOrder = 4; //已取消
  27. /**
  28. * @return \think\model\relation\HasMany
  29. * 关联订单商品
  30. */
  31. public function withOrderGoods ()
  32. {
  33. return self::hasMany(OrderGoods::class, 'order_id', 'order_id')->field('goods_name,goods_id,goods_img,num,price,total_fee,spec_text,goods_spec_id');
  34. }
  35. /**
  36. * @return \think\model\relation\HasOne
  37. * 关联订单配送
  38. */
  39. public function withOrderShipping ()
  40. {
  41. return self::hasOne(OrderShipping::class, 'order_id', 'order_id')->field('sp_name,sp_mobile,sp_province,sp_city,sp_county,sp_remark,sp_mergename');
  42. }
  43. /**
  44. * 订单列表
  45. */
  46. public static function list (array $map = [], array $paginate = [], $userId, ?string $field = '*')
  47. {
  48. $map['user_id'] = $userId;
  49. $field = 'order_id,status,order_sn,order_type,coupon_number,created_time,order_remark,payment,ship_postfee,rebate_score,ship_name,ship_code,ship_number,expires_time,rebate_lock_score';
  50. foreach ($map as $k => $v) {
  51. if (empty($v) && $v != '0') {
  52. unset($map[$k]);
  53. }
  54. }
  55. if (isset($map['status'])) {
  56. if ($map['status'] == -1) {
  57. $map['status'] = ['0','1','2', '4', '5', '6'];
  58. }
  59. }
  60. // if (isset($map['order_type'])) {
  61. // if ($map['order_type'] == -1) {
  62. // $map['order_type'] = ['1','2','3', '4', '5'];
  63. // }
  64. // }
  65. $data = self::where($map)->where('status', '<>', 3)->relation(['withOrderGoods'])->field($field)->order('order_id desc')->paginate($paginate['limit'])->toArray();
  66. foreach ($data['data'] as $k=>&$v){
  67. foreach ($v['withOrderGoods'] as $key=>$val){
  68. $goods_sn = Db::name('shop_goods')->where('goods_id', $val['goods_id'])->value('goods_sn');
  69. // sr_log($goods_sn);
  70. // $val['goods_sn'] = $goods_sn;
  71. $data['data'][$k]['withOrderGoods'][$key]['goods_sn'] = $goods_sn;
  72. // $data['data'][$k]['withOrderGoods'][$key]['goods_name'] = '云德商品购买';
  73. }
  74. $v['withOrderShipping'] = Db::name('shop_order_shipping')->where('order_id', $v['order_id'])->find();
  75. }
  76. $cur_xzmoney = Db::name('system_config')->where('name', 'xz_cur_money')->where('group', 'xzconfig')->value('value');
  77. foreach ($data['data'] as $k => &$v) {
  78. $v['withOrderExpress'] = [];
  79. // if (in_array($v['status'], [1, 2])) {
  80. $v['withOrderExpress'] = ExpressServices::instance()->orderId($v['order_id'])->code($v['ship_code'])->number($v['ship_number'])->find() ?: [];
  81. if (intval($v['status']) == 2){
  82. $v['express_url'] = "https://m.kuaidi100.com/result.jsp?nu=".$v['ship_number'];
  83. }else{
  84. $v['express_url'] = "";
  85. }
  86. // }
  87. if ($v['status'] == 1){
  88. if ($v['order_type'] == 1){
  89. $v['can_hg'] = 1;
  90. }
  91. }else{
  92. $v['can_hg'] = 2;
  93. }
  94. // if ($v['status'] == 4){
  95. // $v['yg_goodsid'] = Db::name('yg_order')->where('order_sn', $v['order_sn'])->max('id');
  96. // }else{
  97. // $v['yg_goodsid'] = 0;
  98. //
  99. // }
  100. switch ($v['status']){
  101. case 0:
  102. $v['status_title'] = '待付款';
  103. break;
  104. case 1:
  105. $v['status_title'] = '待发货';
  106. break;
  107. case 2:
  108. $v['status_title'] = '已发货';
  109. break;
  110. case 3:
  111. $v['status_title'] = '已过期';
  112. break;
  113. case 4:
  114. $v['status_title'] = '已完成';
  115. break;
  116. case 5:
  117. $v['status_title'] = '已完成';
  118. break;
  119. case 6:
  120. $v['status_title'] = '已完成';
  121. break;
  122. }
  123. // if ($v['expires_time']){
  124. // $v['expires_time']=strtotime($v['expires_time']);
  125. // }
  126. // 建议竞拍价格
  127. // $back_redscore = number_format($v['rebate_lock_score']*env('app.YP_APPLY_HUIGOU_SCALE')/100, '2', '.', '');
  128. // $cur_xzmoney = Db::name('system_config')->where('name', 'xz_cur_money')->where('group', 'xzconfig')->value('value');
  129. // $xz_price = getXzPirceWithPrice($cur_xzmoney, $back_redscore);
  130. // $v['jy_buyprice'] = number_format($xz_price + 1, '0', '.', '');
  131. // if ($xz_price < 1){
  132. // $v['jy_jpprice'] = 0.1;
  133. // }
  134. //
  135. // if ($xz_price > 1){
  136. // $v['jy_jpprice'] = 1;
  137. // }
  138. //
  139. // if ($xz_price > 4){
  140. // $v['jy_jpprice'] = number_format($xz_price-2, '0', '.', '');
  141. // }
  142. // if ($xz_price > 5){
  143. // $v['jy_jpprice'] = number_format($xz_price-3, '0', '.', '');
  144. // }
  145. // if ($v['order_type'] == 5){
  146. // foreach ($v['withOrderGoods'] as $k1=>&$v1){
  147. // $v1['price'] = getXzPirceWithPrice($cur_xzmoney ,$v1['price']);
  148. // }
  149. //
  150. // $v['payment'] = getXzPirceWithPrice($cur_xzmoney, $v['payment']);
  151. // }
  152. }
  153. return $data['data'];
  154. }
  155. /**
  156. * 订单详情
  157. */
  158. public static function details (array $map, $userId, ?string $field = '*'): array
  159. {
  160. $field = 'order_type,order_id,status,order_sn,created_time,coupon_number,order_remark,total_price,ship_postfee,payment,rebate_score,ship_code,ship_name,ship_number,expires_time,rebate_lock_score';
  161. $cur_xzmoney = Db::name('system_config')->where('name', 'xz_cur_money')->where('group', 'xzconfig')->value('value');
  162. $map['user_id'] = $userId;
  163. $details = self::where($map)->relation(['withOrderGoods', 'withOrderShipping'])->field($field)->findOrEmpty()->toArray();
  164. if (empty($details))
  165. throw new Exception('订单不存在');
  166. $details['withOrderExpress'] = [];
  167. if (in_array($details['status'], [1, 2])) {
  168. $details['withOrderExpress'] = ExpressServices::instance()->orderId($details['order_id'])->code($details['ship_code'])->number($details['ship_number'])->find() ?: [];
  169. if (intval($details['status']) == 2){
  170. $details['express_url'] = "https://m.kuaidi100.com/result.jsp?nu=".$details['ship_number'];
  171. }else{
  172. $details['express_url'] = "";
  173. }
  174. }
  175. if ($details['order_type'] == 5){
  176. $details['total_price'] = getXzPirceWithPrice($cur_xzmoney, $details['total_price']);
  177. }
  178. switch ($details['status']){
  179. case 0:
  180. $details['status_title'] = '待付款';
  181. break;
  182. case 1:
  183. $details['status_title'] = '待发货';
  184. break;
  185. case 2:
  186. $details['status_title'] = '已发货';
  187. break;
  188. case 3:
  189. $details['status_title'] = '取消订单';
  190. break;
  191. case 4:
  192. $details['status_title'] = '待发货(正在竞拍)';
  193. break;
  194. case 5:
  195. $details['status_title'] = '待发货(竞拍完成)';
  196. break;
  197. case 6:
  198. $details['status_title'] = '已发货(竞拍已发货)';
  199. break;
  200. }
  201. // if ($details['expires_time']){
  202. // $details['expires_time']=strtotime($details['expires_time']);
  203. // }
  204. // foreach ($details['data'] as $k=>$v){
  205. foreach ($details['withOrderGoods'] as $key=>$val){
  206. $goods_sn = Db::name('shop_goods')->where('goods_id', $val['goods_id'])->value('goods_sn');
  207. // sr_log($goods_sn);
  208. // $val['goods_sn'] = $goods_sn;
  209. //
  210. $details['withOrderGoods'][$key]['goods_sn'] = $goods_sn;
  211. // $details['withOrderGoods'][$key]['goods_name'] = '云德商品购买';
  212. $details['withOrderGoods'][$key]['price'] = getXzPirceWithPrice($cur_xzmoney, $details['withOrderGoods'][$key]['price']);
  213. }
  214. // }
  215. return $details;
  216. }
  217. /**
  218. * 下单详情,获取商品信息
  219. */
  220. public static function buyDetails (array $data, array $address = [])
  221. {
  222. $result = [];
  223. foreach ($data as $key => $value) {
  224. $result[$value['goods_sn'] . '_' . $value['spec_id']][] = $value;
  225. }
  226. $details = [];
  227. try {
  228. array_walk($result, function ($value, $key) use (&$details, &$flag) {
  229. $key_arrkass = explode('_', $key);
  230. $goodsBase = Db::name('shop_goods')->where(['goods_sn' => $key_arrkass[0]])->find();
  231. $num = array_sum(array_column($value, 'num'));
  232. $goodsSpec = Db::name('shop_goods_spec')->where(['goods_id' => $goodsBase['goods_id'], 'spec_ids' => $value[0]['spec_id']])->find();
  233. if (empty($goodsSpec) || empty($goodsBase)) {
  234. throw new Exception('操作失败,所选商品含有失效商品');
  235. }
  236. $superlizer = Db::name('shop_supplier')->where('id', $goodsBase['supplier'])->find();
  237. $details[] = [
  238. 'goods_sn' => $goodsBase['goods_sn'],
  239. 'goods_id' => $goodsBase['goods_id'],
  240. 'goods_type' => $goodsBase['goods_type'],
  241. 'goods_name' => $goodsBase['goods_name'],
  242. 'picture' => $goodsSpec['picture'] ?: $goodsBase['goods_img'],
  243. 'num' => $num, //数量
  244. 'price' => $goodsSpec['price'],//单价
  245. 'weight' => $goodsSpec['weight'], //重量
  246. 'total_fee' => bcmul($num, $goodsSpec['price'], 2), //总价
  247. 'rebate_score' => $goodsSpec['rebate_score'],//单个返利积分
  248. // 'rebate_score_most' => bcmul($num, $goodsBase['rebate_score_most'], 2),//返回积分 马上
  249. // 'rebate_score_lock' => bcmul($num, $goodsBase['rebate_score_lock'], 2),//返回积分 锁定
  250. 'total_items_rebate_score' => bcmul($num, $goodsSpec['rebate_score'], 2),//总返利积分
  251. 'spec_ids' => $goodsSpec['spec_ids'],
  252. 'spec_text' => $goodsSpec['spec_text'],
  253. // 'coupon_num' => $goodsBase['coupon_num'],
  254. 'post_template_id' => $goodsBase['post_template_id'], //是否包邮,否就是运费模板ID
  255. 'stock' => $goodsSpec['stock'],
  256. 'supplier_name'=>$superlizer['name']
  257. ];
  258. });
  259. //组合数据
  260. $details_arr = [];
  261. foreach ($details as $k => $v) {
  262. $details_arr[$v['goods_sn']]['goods'][] = $v;
  263. $total_rebate_score = multi_array_sum($details_arr[$v['goods_sn']]['goods'], 'total_items_rebate_score');
  264. // $total_rebate_most_score = multi_array_sum($details_arr[$v['goods_sn']]['goods'], 'rebate_score_most');
  265. // $total_rebate_lock_score = multi_array_sum($details_arr[$v['goods_sn']]['goods'], 'rebate_score_lock');
  266. $total_num = multi_array_sum($details_arr[$v['goods_sn']]['goods'], 'num');
  267. $total_weight = multi_array_sum($details_arr[$v['goods_sn']]['goods'], 'weight');
  268. $total_price = multi_array_sum($details_arr[$v['goods_sn']]['goods'], 'total_fee');
  269. // $total_coupon_num = multi_array_sum($details_arr[$v['goods_sn']]['goods'], 'coupon_num');
  270. $details_arr[$v['goods_sn']]['total_rebate_score'] = $total_rebate_score; //总返利积分
  271. // $details_arr[$v['goods_sn']]['total_rebate_most_score'] = $total_rebate_most_score; // 返利积分马上到账
  272. // $details_arr[$v['goods_sn']]['total_rebate_lock_score'] = $total_rebate_lock_score; //总返利积分
  273. $details_arr[$v['goods_sn']]['total_num'] = $total_num; //总数量
  274. $details_arr[$v['goods_sn']]['total_price'] = $total_price; //总金额
  275. $details_arr[$v['goods_sn']]['total_weight'] = $total_weight; //总重量
  276. // $details_arr[$v['goods_sn']]['total_coupon_num'] = $total_coupon_num * $total_num; //总抢购值
  277. //获取运费
  278. // if ($address) {
  279. // $details_arr[$v['goods_sn']]['post_fee'] = self::postFee(
  280. // $address['city'],
  281. // [
  282. // 'goods_sn' => $v['goods_sn'],
  283. // 'num' => $total_num,
  284. // 'total_price' => $total_price,
  285. // 'total_weight' => $details_arr
  286. // ],
  287. // $v['post_template_id']
  288. // );
  289. // } else {
  290. // $details_arr[$v['goods_sn']]['post_fee'] = '0.00';
  291. // }
  292. $details_arr[$v['goods_sn']]['post_fee'] = '0.00';
  293. $details_arr[$v['goods_sn']]['payment'] = bcadd($details_arr[$v['goods_sn']]['total_price'], $details_arr[$v['goods_sn']]['post_fee'], 2);
  294. $details_arr[$v['goods_sn']]['supplier_name'] = $details[$key]['supplier_name'];
  295. }
  296. $total = [
  297. 'count_payment' => sprintf("%.2f", multi_array_sum($details_arr, 'payment')),
  298. 'count_rebate_score' => (string)multi_array_sum($details_arr, 'total_rebate_score'),
  299. // 'count_rebate_most_score' => (string)multi_array_sum($details_arr, 'total_rebate_most_score'),
  300. // 'count_rebate_lock_score' => (string)multi_array_sum($details_arr, 'total_rebate_lock_score'),
  301. 'count_num' => multi_array_sum($details_arr, 'total_num'),
  302. // 'total_coupon_num' => multi_array_sum($details_arr, 'total_coupon_num')
  303. ];
  304. $details_arr = array_values($details_arr);
  305. return ['details' => $details_arr, 'total' => $total];
  306. } catch (\Exception $e) {
  307. throw new Exception($e->getMessage());
  308. }
  309. }
  310. /**
  311. * 生成订单
  312. */
  313. public static function createOrder (array $data, int $userId, $user, $buyData, $cart_id)
  314. {
  315. Db::startTrans();
  316. try {
  317. //-----组装商品数据,不同商品将拆分------
  318. $result = $data['order'];
  319. $results = [];
  320. $specStock = [];
  321. // $m_id = createdMachineID();
  322. // if ($data['order_type'] == 3){
  323. // // 生成矿机兑换券
  324. // $m_machine->insertGetId([
  325. // 'number'=>$m_id,
  326. // 'create_time'=>sr_getcurtime(time())
  327. // ]);
  328. // }
  329. array_walk($result, function ($value, $key) use (&$results, &$specStock) {
  330. $key_arrkass = explode('_', $key);
  331. $goodsBase = Db::name('shop_goods')->where(['goods_sn' => $key_arrkass[0]])->find();
  332. $results[$key_arrkass[0]]['goods'] = $goodsBase;
  333. $goodsSpec = Db::name('shop_goods_spec')->where(['goods_id' => $goodsBase['goods_id'], 'spec_ids' => $value[0]['spec_id']])->find();
  334. $num = array_sum(array_column($value, 'num'));
  335. $results[$key_arrkass[0]]['spec'][$key_arrkass[1]] = $specStock[] = [
  336. 'num' => $num, //数量
  337. 'total_fee' => bcmul($num, $goodsSpec['price'], 3), //总价
  338. 'total_weight' => bcmul($num, $goodsSpec['weight'], 3), //总重量
  339. 'spec_id' => $value[0]['spec_id'], //规格ids
  340. 'spec_data' => $goodsSpec, //规格数据
  341. 'total_rebate_score' => bcmul($num, $goodsBase['rebate_score'], 3),//总返积分
  342. // 'total_rebate_lock_score' => bcmul($num, $goodsBase['rebate_score_lock'], 3)//返利积分锁定
  343. ];
  344. });
  345. //------减库存--------
  346. $num = 0;
  347. foreach ($specStock as $k => $v) {
  348. Db::name('shop_goods_spec')->where(['goods_spec_id' => $v['spec_data']['goods_spec_id']])->dec('stock', $v['num'])->update();
  349. $spec_info = Db::name('shop_goods_spec')->where(['goods_spec_id' => $v['spec_data']['goods_spec_id']])->find();
  350. Db::name('shop_goods')->where(['goods_id' => $spec_info['goods_id']])->dec('inventory', $v['num'])->update();
  351. // CacheServices::clear(md5('goodsDetail_' . $v['goods_sn']));
  352. CacheServices::set(md5('goodsDetail_' . $spec_info['goods_sn']), false);
  353. }
  354. //-------生成订单商品,返回订单号--------
  355. $createOrder = [];
  356. $i = -1;
  357. $total_rebate_score = 0;
  358. // $total_rebate_lock_score = 0;
  359. array_walk($results, function ($value, $key) use ($userId, $data, &$createOrder, &$i, &$total_rebate_score) {
  360. $nowTime = date('Y-m-d H:i:s', time());
  361. $nums = multi_array_sum($value['spec'], 'num');
  362. $total_price = multi_array_sum($value['spec'], 'total_fee');
  363. $total_weight = multi_array_sum($value['spec'], 'total_weight');
  364. $total_rebate_score = multi_array_sum($value['spec'], 'total_rebate_score');
  365. // $total_rebate_score = $value['goods']['rebate_score_most']*
  366. // $total_rebate_lock_score = multi_array_sum($value['spec'], 'total_rebate_lock_score');
  367. //运费
  368. $post_fee = self::postFee(
  369. $data['address']['city'],
  370. [
  371. 'goods_sn' => $value['goods']['goods_sn'],
  372. 'num' => $nums,
  373. 'total_price' => $total_price,
  374. 'total_weight' => $total_weight
  375. ],
  376. $value['goods']['post_template_id']
  377. );
  378. $post_fee = 0;
  379. $give_vip = 0;
  380. if ($data['cls'] == 1 && $value['goods']['give_vip']) {
  381. $give_vip = $value['goods']['give_vip'];
  382. }
  383. $i++;
  384. // //写入订单
  385. $status = 0;
  386. $payment = bcadd($total_price, $post_fee, 3);
  387. $order = self::create([
  388. 'order_sn' => createdOrderSn(),
  389. 'total_price' => $total_price,
  390. 'payment' => $payment,
  391. 'user_id' => $userId,
  392. 'num' => $nums,
  393. 'status'=>$status,
  394. 'ship_postfee' => $post_fee,
  395. 'rebate_score' => $total_rebate_score, //总返利积分
  396. 'created_time' => $nowTime, 'updated_time' => $nowTime,
  397. 'give_vip' => $give_vip,
  398. 'order_remark' => isset($data['order_remark']) ? $data['order_remark'] : '',
  399. 'pay_type'=>$data['pay_type'],
  400. 'order_type'=>$data['order_type'],
  401. 'coupon_number'=>'',
  402. 'expires_time'=>sr_getcurtime(time()+intval(env('common.ORDER_EXPIRES_TIME'))),
  403. 'supplier_name'=>$data['supplier_name']
  404. ]);
  405. // sr_log('ccccc'.$data['order_type']);
  406. //写入订单商品详情
  407. $orderGoods = [];
  408. foreach ($value['spec'] as $specKey => $specValue) {
  409. $orderGoods[] = [
  410. 'order_id' => $order->id, 'goods_id' => $value['goods']['goods_id'],
  411. 'goods_name' => $value['goods']['goods_name'], 'goods_category' => $value['goods']['category'],
  412. 'goods_img' => $specValue['spec_data']['picture'] ?: $value['goods']['goods_img'],
  413. 'num' => $specValue['num'],
  414. 'price' => $specValue['spec_data']['price'],
  415. 'total_fee' => $specValue['total_fee'],
  416. 'goods_spec_id' => $specValue['spec_data']['goods_spec_id'],
  417. 'spec_ids' => $specValue['spec_data']['spec_ids'],
  418. 'spec_text' => $specValue['spec_data']['spec_text'],
  419. 'rebate_score' => $specValue['spec_data']['rebate_score'],
  420. 'total_rebate_score' => $specValue['total_rebate_score'],
  421. 'order_type'=>$data['order_type'],
  422. 'uid'=>$userId
  423. ];
  424. }
  425. (new OrderGoods())->saveAll($orderGoods);
  426. //写入订单配送
  427. OrderShipping::create(OrderShipping::packageAddressShipPing($data['address'], $order->id));
  428. $createOrder[] = ['order_sn' => $order->order_sn, 'order_data' => $value['spec']];
  429. });
  430. if ($data['cart_ids']) {
  431. Db::name('shop_cart')->where('id', 'in', $data['cart_ids'])->where(['user_id' => $userId])->delete();
  432. }
  433. // 购买商品
  434. if (in_array($data['order_type'], [1, 3])){
  435. $ex_time = intval(env('common.ORDER_EXPIRES_TIME', 60*60));
  436. $order_sn = $createOrder[0]['order_sn'];
  437. Queue::instance()->log('订单过期执行成功')->job(ShopOrderJob::class)->do('ShopOrderExpired')->secs($ex_time)->push([$order_sn]);
  438. }
  439. // 增加销量
  440. if (in_array($data['order_type'], [2,4,5])){
  441. foreach ($createOrder as $key=>$val){
  442. $order_id = Db::name('shop_order')->where('order_sn', $val['order_sn'])->value('order_id');
  443. $orderGoods = OrderGoods::where(['order_id' => $order_id])->select()->toArray();
  444. foreach ($orderGoods as $k => $v) {
  445. ShopGoodsModel::where(['goods_id' => $v['goods_id']])->inc('sales_volume', $v['num'])->inc('real_sales_volume', $v['num'])->update();
  446. }
  447. }
  448. }
  449. if (intval($cart_id) > 0){
  450. Db::name('shop_cart')->where('id', $cart_id)->delete();
  451. }
  452. Db::commit();
  453. return ['flag' => 200, 'data' => array_column($createOrder, 'order_sn')];
  454. } catch (\Exception $e) {
  455. Db::rollback();
  456. if (strpos($e->getMessage(), 'SQLSTATE[22003]') !== false) {
  457. throw new Exception('所选商品含有库存不足');
  458. }
  459. throw new Exception($e->getMessage());
  460. }
  461. }
  462. /**
  463. * 校验库存
  464. */
  465. public static function checkStock (array $data)
  466. {
  467. $results = [];
  468. array_walk($data, function ($value, $key) use (&$results) {
  469. $num = array_sum(array_column($value, 'num'));
  470. $results[] = ['spec_id' => $value[0]['spec_id'], 'goods_sn' => $value[0]['goods_sn'], 'num' => $num];
  471. });
  472. foreach ($results as $k => $v) {
  473. $stock = Db::name('shop_goods_spec')->where(['goods_sn' => $v['goods_sn'], 'spec_ids' => $v['spec_id']])->value('stock') ?: 0;
  474. sr_log($stock);
  475. if ($v['num'] > $stock) {
  476. return false;
  477. }
  478. }
  479. return true;
  480. }
  481. /**
  482. * 支付前校验订单
  483. */
  484. public static function checkingOrder ($order_sn, $userPayMoney, $userId)
  485. {
  486. $order = self::where(['order_sn' => explode(',', $order_sn)])->select()->toArray();
  487. if (empty($order)) {
  488. return ['flag' => 110, 'msg' => '校验订单失败'];
  489. }
  490. $orderPayment = multi_array_sum($order, 'payment');
  491. // if ($orderPayment != $userPayMoney) {
  492. // return ['flag' => 111, 'msg' => '金额错误'];
  493. // }
  494. foreach ($order as $k => $v) {
  495. if ($v['user_id'] != $userId) {
  496. return ['flag' => 112, 'msg' => '校验订单失败'];
  497. }
  498. }
  499. return ['flag' => 200, 'msg' => '成功', 'orderPayment' => $orderPayment, 'order' => $order];
  500. }
  501. /**
  502. * 支付订单回调
  503. */
  504. public static function payDoneOrderCallback ($order, $payType, $userId)
  505. {
  506. $nowTime = date('Y-m-d H:i:s', time());
  507. self::where(['order_sn' => array_column($order, 'order_sn')])
  508. ->update(['pay_type' => $payType, 'status' => self::waitDelivery, 'updated_time' => $nowTime]);
  509. //根据订单商品 生成分红
  510. $orderId = array_column($order, 'order_id');
  511. $orderGoods = OrderGoods::where(['order_id' => $orderId])->select()->toArray();
  512. foreach ($orderGoods as $k => $v) {
  513. ShopGoodsModel::where(['goods_id' => $v['goods_id']])->inc('sales_volume', $v['num'])->inc('real_sales_volume', $v['num'])->update();
  514. }
  515. //赠送送会员
  516. if ($order[0]['give_vip']) {
  517. $vip = $order[0]['give_vip'] == 2 ? 'year_card' : 'monthly_card';
  518. $user = Db::name('user')->where('id', $userId)->field('vip,vip_expire_time')->find();
  519. $vip_config = get_vip_config($vip);
  520. $date = new \DateTime($user['vip_expire_time']);
  521. $date->add(new \DateInterval(get_vip_datetime_string($vip_config['type'])['time']));
  522. $vip_expire_time = $date->format('Y-m-d H:i:s'); // vip到期时间
  523. //更新用户vip信息
  524. Db::name('User')->where('id', $userId)->update(['vip' => get_vip_datetime_string($vip_config['type'])['vip_type'], 'vip_expire_time' => $vip_expire_time]);
  525. Db::name('vip_log')->insert(['uid' => $userId, 'type' => 2, 'pay_price' => 0, 'vip_expire_time' => $vip_expire_time, 'vip_type' => $vip]);
  526. }
  527. Queue::instance()->log('执行成功')->job(ShopBonusJob::class)->do('shopBonusJob')->push([$userId, $orderGoods]);
  528. }
  529. /**
  530. * 取消订单
  531. */
  532. public static function cancelOrder ($data, $userId)
  533. {
  534. $nowTime = date('Y-m-d H:i:s', time());
  535. $data = self::where(['order_sn' => $data['order_sn'], 'user_id' => $userId])->relation(['withOrderGoods'])->findOrEmpty()->toArray();
  536. if (empty($data)) {
  537. throw new Exception('参数错误');
  538. }
  539. if ($data['status'] != 0) {
  540. throw new Exception('订单状态错误');
  541. }
  542. self::where(['order_sn' => $data['order_sn']])->save(['status' => 3, 'updated_time' => $nowTime]);
  543. foreach ($data['withOrderGoods'] as $kk => $vv) {
  544. Db::name('shop_goods_spec')->where(['goods_spec_id' => $vv['goods_spec_id']])->inc('stock', $vv['num'])->update();
  545. }
  546. }
  547. /**
  548. * 确定订单
  549. */
  550. public static function receiveOrder ($data, $userId)
  551. {
  552. $nowTime = date('Y-m-d H:i:s', time());
  553. $data = self::where(['order_sn' => $data['order_sn'], 'user_id' => $userId])->relation(['withOrderGoods'])->findOrEmpty()->toArray();
  554. if (empty($data)) {
  555. throw new Exception('参数错误');
  556. }
  557. if ($data['status'] != 2) {
  558. throw new Exception('订单状态错误');
  559. }
  560. self::where(['order_sn' => $data['order_sn']])->save(['status' => 4, 'updated_time' => $nowTime]);
  561. }
  562. /**
  563. * @param $address 用户地址
  564. * @param $data 商品数据
  565. * @param $express_template_id 模板ID
  566. * 获取运费
  567. */
  568. public static function postFee ($address, $data, $express_template_id)
  569. {
  570. //获取运费模板
  571. $expressDelivery = Db::name('express_delivery')->where(['id' => $express_template_id])->findOrEmpty();
  572. //获取运费模板列表
  573. $expressDeliveryItems = Db::name('express_shipping_method')->where(['template_id' => $expressDelivery['id']])->select()->toArray();
  574. $price_method_field = '';
  575. switch ($expressDelivery['price_method']) {
  576. case 1:
  577. $price_method_field = $data['total_price']; //按金额
  578. break;
  579. case 2:
  580. $price_method_field = $data['num']; //按件数
  581. break;
  582. case 3:
  583. $price_method_field = $data['total_weight']; //按重量
  584. break;
  585. default:
  586. break;
  587. }
  588. if ($expressDelivery['price_method'] == 1) {
  589. //计算默认运费 【配送区域、免运费金额、达标时运费、未达标时运费;】
  590. if ($price_method_field < $expressDelivery['default_free_price']) {
  591. $default_postfee = $expressDelivery['default_fastandard_price'];
  592. } else {
  593. //达标时运费
  594. $default_postfee = $expressDelivery['default_price'];
  595. }
  596. if (empty($expressDeliveryItems)) {
  597. return $default_postfee;
  598. }
  599. //按指定地区计算邮费
  600. foreach ($expressDeliveryItems as $k => $node) {
  601. if (in_array($address, explode(',', $node['address_items_ids']))) {
  602. //未达标运费
  603. if ($price_method_field < $node['free_price']) {
  604. return $node['fastandard_price'];
  605. } else {
  606. //达标时运费
  607. return $node['price'];
  608. }
  609. } else {
  610. return $default_postfee;
  611. }
  612. }
  613. } else {
  614. //按件数 重量计费 【配送区域、首件、达标时运费、续件、未达标时运费】
  615. //计算默认运费
  616. if ($price_method_field <= $expressDelivery['default_pieces']) {
  617. $default_postfee = $expressDelivery['default_price'];
  618. } else {
  619. //达到续件条件时的运费
  620. if ($expressDelivery['add_pieces']) {
  621. //配置过续件费用
  622. //续件数 = (下单件数 - 首件) /续件数
  623. //总运费 = 首件运费 + (续件数 * 续件费用)
  624. $add_pieces = bcdiv(($price_method_field - $expressDelivery['default_pieces']), $expressDelivery['add_pieces'], 2);
  625. $default_postfee = bcadd($expressDelivery['default_price'], bcmul($add_pieces, $expressDelivery['add_price'], 2), 2);
  626. } else {
  627. //未配置过续件,按首件价格
  628. $default_postfee = $expressDelivery['default_price'];
  629. }
  630. }
  631. if (empty($expressDeliveryItems)) {
  632. return $default_postfee;
  633. }
  634. //按指定地区计算邮费
  635. foreach ($expressDeliveryItems as $k => $node) {
  636. if (in_array($address, explode(',', $node['address_items_ids']))) {
  637. //未达到续件条件时的运费
  638. if ($price_method_field <= $node['pieces']) {
  639. return $node['price'];
  640. } else {
  641. //达到续件条件时的运费
  642. if ($node['add_pieces']) {
  643. //配置过续件费用
  644. //续件数 = (下单件数 - 首件) /续件数
  645. //总运费 = 首件运费 + (续件数 * 续件费用)
  646. $add_pieces = bcdiv(($price_method_field - $node['pieces']), $node['add_pieces'], 2);
  647. return bcadd($node['price'], bcmul($add_pieces, $node['add_price'], 2), 2);
  648. } else {
  649. //未配置过续件,按首件价格
  650. return $node['price'];
  651. }
  652. }
  653. } else {
  654. return $default_postfee;
  655. }
  656. }
  657. }
  658. }
  659. public function boxGoodsSurePost($uid, $params){
  660. $hand_ids = $params['hand_ids'];
  661. $address_id = $params['address_id'];
  662. $total_ids = explode(',', $hand_ids);
  663. $model_hands = new BoxHandleModel();
  664. $list = $model_hands->where('id', 'in', $hand_ids)->where('status', 1)->where('uid', $uid)->select();
  665. if (count($list) != count($total_ids)){
  666. sr_throw('参数错误');
  667. }
  668. $address_info = Db::name('user_address')->where('id', $address_id)->where('uid', $uid)->find();
  669. if (!$address_info){
  670. sr_throw('地址错误');
  671. }
  672. $cur_time = sr_getcurtime(time());
  673. foreach ($total_ids as $key=>$val){
  674. $hand_info = Db::name('box_handle')->where('id', $val)->find();
  675. $goods_info = Db::name('shop_goods')->where('goods_id', $hand_info['goods_id'])->find();
  676. $supplier_info = Db::name('shop_supplier')->where('id', $goods_info['supplier'])->find();
  677. $order_id = Db::name('shop_order')->insertGetId([
  678. 'order_sn'=>createdFDOrderSn(),
  679. 'payment'=>0,
  680. 'ship_postfee'=>0,
  681. 'user_id'=>$uid,
  682. 'status'=>1,
  683. 'num'=>1,
  684. 'order_type'=>5,
  685. 'supplier_name'=>$supplier_info['name'],
  686. 'total_price'=>0,
  687. 'created_time'=>$cur_time,
  688. 'rebate_score'=>0,
  689. ]);
  690. Db::name('shop_order_goods')->insertGetId([
  691. 'order_id'=>$order_id,
  692. 'goods_id'=>$goods_info['goods_id'],
  693. 'goods_name'=>$goods_info['goods_name'],
  694. 'goods_category'=>$goods_info['category'],
  695. 'goods_img'=>$goods_info['goods_img'],
  696. 'num'=>1,
  697. 'price'=>$goods_info['price'],
  698. 'total_fee'=>$goods_info['price'],
  699. 'spec_ids'=>1,
  700. 'spec_text'=>$goods_info['spec_name'],
  701. 'uid'=>$uid,
  702. 'rebate_score'=>0,
  703. 'total_rebate_score'=>0
  704. ]);
  705. $pname = Db::name('area')->where('id', $address_info['province'])->value('name');
  706. $cname = Db::name('area')->where('id', $address_info['city'])->value('name');
  707. $countyname = Db::name('area')->where('id', $address_info['county'])->value('name');
  708. Db::name('shop_order_shipping')->insert([
  709. 'order_id'=>$order_id,
  710. 'sp_name'=>$address_info['name'],
  711. 'sp_mobile'=>$address_info['mobile'],
  712. 'sp_province'=>$pname,
  713. 'sp_city'=>$cname,
  714. 'sp_county'=>$countyname,
  715. 'sp_remark'=>$address_info['remark'],
  716. 'sp_mergename'=> $pname.' '.$cname.' '.$countyname.' '.$address_info['remark'],
  717. 'created_time'=>$cur_time
  718. ]);
  719. Db::name('box_handle')->where('id', $val)->save([
  720. 'status'=>2,
  721. 'handle_type'=>1
  722. ]);
  723. }
  724. }
  725. // 一件回收
  726. public function boxGoodsReBuy($uid, $params, $user_info){
  727. $hand_ids = $params['hand_ids'];
  728. $total_ids = explode(',', $hand_ids);
  729. $model_hands = new BoxHandleModel();
  730. $total_goodsnum = count($total_ids);
  731. $list = $model_hands->where('id', 'in', $total_ids)->where('status', 1)->where('uid', $uid)->select();
  732. if (count($list) != $total_goodsnum){
  733. sr_throw('参数或状态错误');
  734. }
  735. if ($model_hands->where('box_type', 10)->where('id', 'in', $hand_ids)->find()){
  736. sr_throw('普通商品只能发货,不能回收');
  737. }
  738. $cur_time = sr_getcurtime(time());
  739. // 待处理的总金额
  740. $total_money = Db::name('box_handle')->where('id', 'in', $hand_ids)->sum('goods_price');
  741. // 最终金额 总共商品金额减去 每个商品 10快
  742. $end_money = $total_money - $total_goodsnum* env('boxsetting.RECYCLE_ONBOX_PRICE');
  743. if ($end_money < 0){
  744. sr_throw('错误,请联系客服');
  745. }
  746. if ($params['action'] == 'apply'){
  747. return [
  748. 'total_count'=>count($list),
  749. 'end_money'=>$end_money,
  750. 'total_money'=>$total_money
  751. ];
  752. }
  753. if ($params['action'] == 'surerecycle'){
  754. $user_info = Db::name('user')->where(['id'=> $uid])->field('id,score,money,recycle_count')->find();
  755. // 回收卡扣除
  756. if ($user_info['recycle_count'] < $total_goodsnum){
  757. sr_throw('回收卡不足'.$total_goodsnum.'个');
  758. }
  759. // 扣除回收卡
  760. edit_user_recyclecard(3, $uid, $total_goodsnum, 0, $hand_ids);
  761. // 288的原价
  762. $oring_price = count($total_ids) * env('boxsetting.ONE_BOX_PRICE');
  763. edit_user_money(2, $uid, $oring_price);
  764. // 备注利润是否可以为负 by wes
  765. if ($total_money > $end_money){
  766. // 待结算利润
  767. Db::name('user')->where('id', $uid)->inc('profit_money',max(0,$end_money-$oring_price))->update();
  768. // 添加用户利润记录
  769. Db::name('user_unmoney')->insert([
  770. 'uid'=>$uid,
  771. 'money'=>$end_money-$oring_price,
  772. 'ids'=>$hand_ids,
  773. 'create_time'=>sr_getcurtime(time())
  774. ]);
  775. }
  776. // 改变用户处理状态
  777. Db::name('box_handle')->where('id', 'in', $hand_ids)->save([
  778. 'status'=>2,
  779. 'handle_type'=>2
  780. ]);
  781. }
  782. }
  783. }