OrderLogic.php 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | likeshop开源商城系统
  4. // +----------------------------------------------------------------------
  5. // | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
  6. // | gitee下载:https://gitee.com/likeshop_gitee
  7. // | github下载:https://github.com/likeshop-github
  8. // | 访问官网:https://www.likeshop.cn
  9. // | 访问社区:https://home.likeshop.cn
  10. // | 访问手册:http://doc.likeshop.cn
  11. // | 微信公众号:likeshop技术社区
  12. // | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用,未经许可不能去除前后端官方版权标识
  13. // | likeshop系列产品收费版本务必购买商业授权,购买去版权授权后,方可去除前后端官方版权标识
  14. // | 禁止对系统程序代码以任何目的,任何形式的再发布
  15. // | likeshop团队版权所有并拥有最终解释权
  16. // +----------------------------------------------------------------------
  17. // | author: likeshop.cn.team
  18. // +----------------------------------------------------------------------
  19. namespace app\shop\logic\order;
  20. use app\admin\logic\distribution\DistributionLevelLogic;
  21. use app\api\logic\PayLogic;
  22. use app\common\basics\Logic;
  23. use app\common\enum\NoticeEnum;
  24. use app\common\enum\OrderEnum;
  25. use app\common\enum\OrderLogEnum;
  26. use app\common\enum\PayEnum;
  27. use app\common\enum\TeamEnum;
  28. use app\common\enum\VerificationEnum;
  29. use app\common\logic\GoodsVirtualLogic;
  30. use app\common\logic\OrderLogLogic;
  31. use app\common\logic\OrderRefundLogic;
  32. use app\common\logic\PayNotifyLogic;
  33. use app\common\model\Delivery;
  34. use app\common\model\Express;
  35. use app\common\model\goods\Goods;
  36. use app\common\model\order\Order;
  37. use app\common\model\DevRegion;
  38. use app\common\model\order\OrderGoods;
  39. use app\common\model\printer\Printer;
  40. use app\common\model\printer\PrinterConfig;
  41. use app\common\model\team\Team;
  42. use app\common\model\team\TeamFound;
  43. use app\common\model\team\TeamJoin;
  44. use app\common\model\user\User;
  45. use app\common\model\user\UserLevel;
  46. use app\common\model\order\Verification;
  47. use app\common\server\ConfigServer;
  48. use app\common\server\ExportExcelServer;
  49. use app\common\server\UrlServer;
  50. use app\common\server\YlyPrinter;
  51. use app\shop\logic\printer\PrinterLogic;
  52. use think\facade\Cache;
  53. use expressage\Kd100;
  54. use expressage\Kdniao;
  55. use think\facade\Db;
  56. use think\Exception;
  57. use think\facade\Validate;
  58. use think\Model;
  59. /**
  60. * 订单管理-逻辑
  61. * Class GoodsLogic
  62. * @package app\shop\logic\goods
  63. */
  64. class OrderLogic extends Logic
  65. {
  66. /**
  67. * @notes 订单统计
  68. * @param array $get
  69. * @param int $shop_id
  70. * @return array
  71. * @throws \think\db\exception\DataNotFoundException
  72. * @throws \think\db\exception\DbException
  73. * @throws \think\db\exception\ModelNotFoundException
  74. * @author suny
  75. * @date 2021/7/14 10:23 上午
  76. */
  77. public static function statistics(array $get = [], int $shop_id = 0, $is_export = false)
  78. {
  79. $order = new Order();
  80. $where = static::getWhere($get);
  81. $page = $get['page'] ?? 1;
  82. $limit = $get['limit'] ?? 10;
  83. $where[] = ['o.delete', '=', 0];
  84. $where[] = ['o.del', '=', 0];
  85. $where[] = ['o.shop_id', '=', $shop_id];
  86. if (Validate::must($get['page'] ?? '')) {
  87. $page = $get['page'];
  88. }
  89. if (Validate::must($get['limit'] ?? '')) {
  90. $limit = $get['limit'];
  91. }
  92. // 导出excel
  93. if (true === $is_export) {
  94. return self::export($where);
  95. }
  96. $field = 'o.*,s.name as shop_name,u.level';
  97. $count = $order
  98. ->alias('o')
  99. ->Join('shop s', 's.id = o.shop_id')
  100. ->Join('user u', 'u.id = o.user_id')
  101. ->Join('order_goods g', 'g.order_id = o.id')
  102. ->where($where)
  103. ->group('o.id')
  104. ->count();
  105. $lists = $order
  106. ->alias('o')
  107. ->field($field)
  108. ->Join('shop s', 's.id = o.shop_id')
  109. ->Join('user u', 'u.id = o.user_id')
  110. ->Join('order_goods g', 'g.order_id = o.id')
  111. ->with(['order_goods', 'user'])
  112. ->where($where)
  113. ->append([
  114. 'delivery_address', 'pay_status_text', 'order_source_text',
  115. 'order_status_text', 'delivery_type_text','order_type_text',
  116. 'pay_way_text', 'is_team_success', 'to_ship_btn', 'to_verification_btn', 'edit_address_btn',
  117. ])
  118. ->page($page, $limit)
  119. ->order('o.id desc')
  120. ->group('o.id')
  121. ->select()->toArray();
  122. $user_level = UserLevel::where(['del'=>0])->column('name','id');
  123. foreach ($lists as &$list) {
  124. $list['pay_time'] = $list['pay_time'] == '0' ? '未支付' : date('Y-m-d H:i:s', $list['pay_time']);
  125. $list['user']['avatar'] = UrlServer::getFileUrl($list['user']['avatar']);
  126. foreach ($list['order_goods'] as $order_good) {
  127. $order_good['image'] = UrlServer::getFileUrl($order_good['image']);
  128. }
  129. // 订单核销按钮 & 发货按钮 & 修改地址
  130. $list['verification_btn'] = $list['to_verification_btn'];
  131. $list['send_btn'] = $list['to_ship_btn'];
  132. $list['change_address_btn'] = $list['edit_address_btn'];
  133. // 会员等级
  134. $list['user_level'] = '暂无等级';
  135. if(isset($user_level[$list['level']])) {
  136. $list['user_level'] = $user_level[$list['level']];
  137. }
  138. //会员优惠
  139. $list['member_amount'] = $list['member_amount'] ?? 0.00;
  140. }
  141. return ['count' => $count, 'lists' => $lists];
  142. }
  143. static function getWhere($data)
  144. {
  145. $where = [];
  146. $where[] = [ 'o.del', '=', 0 ];
  147. $where[] = [ 'o.delete', '=', 0 ];
  148. //订单状态选项卡
  149. if (Validate::must($data['type'] ?? '')) {
  150. $where[] = [ 'order_status', '=', $data['type'] ];
  151. }
  152. //订单搜素
  153. if (! empty($data['search_key']) && ! empty($data['keyword'])) {
  154. $keyword = $data['keyword'];
  155. switch ($data['search_key']) {
  156. case 'order_sn':
  157. $where[] = ['o.order_sn', '=', $keyword];
  158. break;
  159. case 'user_sn':
  160. $where[] = ['u.sn', '=', $keyword];
  161. break;
  162. case 'shop_name':
  163. $where[] = ['s.name', 'like', '%' . $keyword . '%'];
  164. break;
  165. case 'goods_name':
  166. $where[] = ['g.goods_name', 'like', '%' . $keyword . '%'];
  167. break;
  168. case 'user_id':
  169. $where[] = ['o.user_id', '=', $keyword];
  170. break;
  171. case 'nickname':
  172. $where[] = ['u.nickname', 'like', '%' . $keyword . '%'];
  173. break;
  174. case 'user_mobile':
  175. $where[] = ['u.mobile', '=', $keyword];
  176. break;
  177. case 'consignee':
  178. $where[] = ['consignee', '=', $keyword];
  179. break;
  180. case 'consignee_mobile':
  181. $where[] = ['o.mobile', '=', $keyword];
  182. break;
  183. }
  184. }
  185. //商品名称
  186. if (Validate::must($data['goods_name'] ?? '')) {
  187. $where[] = ['g.goods_name', 'like', '%' . $data['goods_name'] . '%'];
  188. }
  189. //配送方式
  190. if (Validate::must($data['delivery_type'] ?? '')) {
  191. $where[] = ['o.delivery_type', '=', $data['delivery_type']];
  192. }
  193. //订单状态
  194. if (Validate::must($data['order_status'] ?? '')) {
  195. $where[] = [ 'o.order_status', '=', $data['order_status'] ];
  196. }
  197. //订单类型
  198. if (Validate::must($data['order_type'] ?? '')) {
  199. $where[] = [ 'o.order_type', '=', $data['order_type'] ];
  200. }
  201. //付款方式
  202. if (Validate::must($data['pay_way'] ?? '')) {
  203. $where[] = [ 'o.pay_way', '=', $data['pay_way'] ];
  204. }
  205. //订单来源
  206. if (Validate::must($data['order_source'] ?? '')) {
  207. $where[] = ['o.order_source', '=', $data['order_source']];
  208. }
  209. //下单时间
  210. if (Validate::must($data['start_time'] ?? '')) {
  211. $where[] = ['o.create_time', '>=', strtotime($data['start_time'])];
  212. }
  213. if (Validate::must($data['end_time'] ?? '')) {
  214. $where[] = ['o.create_time', '<=', strtotime($data['end_time'])];
  215. }
  216. return $where;
  217. }
  218. public static function totalCount($shopId)
  219. {
  220. $all = Order::where(['shop_id' => $shopId, 'del' => 0, 'delete' => 0])->count();
  221. $waitPay = Order::where(['shop_id' => $shopId, 'order_status' => 0 , 'del' => 0, 'delete' => 0])->count();
  222. $waitDelivery = Order::where(['shop_id' => $shopId, 'order_status' => 1 , 'del' => 0, 'delete' => 0])->count();
  223. $waitReceipt = Order::where(['shop_id' => $shopId, 'order_status' => 2 , 'del' => 0, 'delete' => 0])->count();
  224. $waitComplete = Order::where(['shop_id' => $shopId, 'order_status' => 3 , 'del' => 0, 'delete' => 0])->count();
  225. $waitClose = Order::where(['shop_id' => $shopId, 'order_status' => 4 , 'del' => 0, 'delete' => 0])->count();
  226. return [
  227. 'all' => $all,
  228. 'wait_pay' => $waitPay,
  229. 'wait_delivery' => $waitDelivery,
  230. 'wait_receipt' => $waitReceipt,
  231. 'wait_complete' => $waitComplete,
  232. 'wait_close' => $waitClose,
  233. ];
  234. }
  235. /**
  236. * @notes 订单详情
  237. * @param $id
  238. * @return array|Model|null
  239. * @throws \think\db\exception\DataNotFoundException
  240. * @throws \think\db\exception\DbException
  241. * @throws \think\db\exception\ModelNotFoundException
  242. * @author suny
  243. * @date 2021/7/14 10:23 上午
  244. */
  245. public static function getDetail($id)
  246. {
  247. $order = new Order();
  248. $result = $order
  249. ->with(['user', 'order_goods', 'invoice'])
  250. ->where('id', $id)
  251. ->append(['delivery_address', 'pay_status_text', 'order_status_text', 'pay_way_text', 'order_type_text', 'verification_status_text', 'can_change_invoice_no','to_ship_btn','to_verification_btn' ])
  252. ->find();
  253. $result['send_btn'] = $result['to_ship_btn'];
  254. $result['verification_btn'] = $result['to_verification_btn'];
  255. $result['pay_time'] = $result['pay_time'] == 0 ? '未支付' : date('Y-m-d H:i:s', $result['pay_time']);
  256. $user = $result['user'];
  257. $user['avatar'] = UrlServer::getFileUrl($user['avatar']);
  258. $result['user'] = $user;
  259. foreach ($result['order_goods'] as &$order_goods) {
  260. $order_goods['goods_image'] = empty($order_goods['spec_image']) ?
  261. UrlServer::getFileUrl($order_goods['image']) : UrlServer::getFileUrl($order_goods['spec_image']);
  262. }
  263. if ($result['order_type'] == OrderEnum::TEAM_ORDER) {
  264. $team = TeamJoin::field('TJ.status,TF.status as found_status')->alias('TJ')
  265. ->where(['TJ.order_id'=>$result['id']])
  266. ->join('team_found TF', 'TF.id = TJ.team_id')
  267. ->findOrEmpty()->toArray();
  268. $result['is_team_success'] = false;
  269. if ($team) {
  270. $result['is_team_success'] = $team['found_status'] == 1 ? true : false;
  271. }
  272. }
  273. // 自提提货时间
  274. if ($result['delivery_type'] == OrderEnum::DELIVERY_TYPE_SELF && $result['verification_status']) {
  275. $result['confirm_take_time'] = date('Y-m-d H:i:s', $result['confirm_take_time']);
  276. } else {
  277. $result['confirm_take_time'] = '';
  278. }
  279. //会员优惠
  280. $result['member_amount'] = $result['member_amount'] ?? 0.00;
  281. return $result;
  282. }
  283. /**
  284. * @notes 物流信息
  285. * @param $order_id
  286. * @return array|\PDOStatement|string|Model|null
  287. * @throws \think\db\exception\DataNotFoundException
  288. * @throws \think\db\exception\ModelNotFoundException
  289. * @throws \think\exception\DbException
  290. * @author suny
  291. * @date 2021/7/14 10:24 上午
  292. */
  293. public static function shippingInfo($order_id)
  294. {
  295. $shipping = Db::name('delivery')->where('order_id', $order_id)->find();
  296. $shipping['traces'] = [];
  297. if ($shipping) {
  298. $shipping['create_time_text'] = date('Y-m-d H:i:s', $shipping['create_time']);
  299. if ($shipping['send_type'] == 1) {
  300. $shipping['traces'] = self::getShipping($order_id);
  301. }
  302. }
  303. return $shipping;
  304. }
  305. /**
  306. * @notes 物流轨迹
  307. * @param $order_id
  308. * @return bool|string[]
  309. * @throws \think\db\exception\DataNotFoundException
  310. * @throws \think\db\exception\DbException
  311. * @throws \think\db\exception\ModelNotFoundException
  312. * @author suny
  313. * @date 2021/7/14 10:24 上午
  314. */
  315. public static function getShipping($order_id)
  316. {
  317. $orderModel = new Order();
  318. $order = $orderModel->alias('o')
  319. ->field('invoice_no,shipping_name,shipping_id,o.shipping_status,o.mobile')
  320. ->join('delivery d', 'd.order_id = o.id')
  321. ->where(['o.id' => $order_id])
  322. ->find();
  323. $express = ConfigServer::get('express', 'way', '', '');
  324. $key = ConfigServer::get($express, 'appkey');
  325. $app = ConfigServer::get($express, 'appsecret');
  326. if (empty($express) || $order['shipping_status'] != 1 || empty($app) || empty($key)) {
  327. return $traces[] = ['暂无物流信息'];
  328. }
  329. //快递配置设置为快递鸟时
  330. if ($express === 'kdniao') {
  331. $expressage = (new Kdniao($app, $key, true));
  332. $shipping_field = 'codebird';
  333. } else {
  334. $expressage = (new Kd100($app, $key, true));
  335. $shipping_field = 'code100';
  336. }
  337. //快递编码
  338. $shipping_code = Db::name('express')
  339. ->where(['id' => $order['shipping_id']])
  340. ->value($shipping_field);
  341. //获取物流轨迹
  342. if (in_array(strtolower($shipping_code ), [ 'sf', 'shunfeng' ])) {
  343. if ($express === 'kdniao') {
  344. $expressage->logistics($shipping_code, $order['invoice_no'], substr($order['mobile'], -4));
  345. } else {
  346. $expressage->logistics($shipping_code, $order['invoice_no'], $order['mobile']);
  347. }
  348. }else {
  349. $expressage->logistics($shipping_code, $order['invoice_no']);
  350. }
  351. $traces = $expressage->logisticsFormat();
  352. if ($traces == false) {
  353. $traces[] = [$expressage->getError()];
  354. } else {
  355. foreach ($traces as &$item) {
  356. $item = array_values(array_unique($item));
  357. }
  358. }
  359. return $traces;
  360. }
  361. /**
  362. * @notes 获取物流
  363. * @return \think\Collection
  364. * @throws \think\db\exception\DataNotFoundException
  365. * @throws \think\db\exception\DbException
  366. * @throws \think\db\exception\ModelNotFoundException
  367. * @author suny
  368. * @date 2021/7/14 10:24 上午
  369. */
  370. public static function express()
  371. {
  372. return Express::where('del', 0)->select();
  373. }
  374. static function change_invoice_no($post)
  375. {
  376. $id = $post['order_id'];
  377. $order = Order::where(['id' => $id])->find();
  378. if (!$order) {
  379. return '订单失效';
  380. }
  381. if ($order['del'] == 1) {
  382. return '订单已删除';
  383. }
  384. if (! $order->getAttr('can_change_invoice_no')) {
  385. return '已不能修改物流单号';
  386. }
  387. //
  388. if ($post['send_type'] == 1 && empty($post['invoice_no'])) {
  389. return '请输入快递单号';
  390. }
  391. $delivery_data = [
  392. 'invoice_no' => $post['invoice_no'] ?? '',
  393. ];
  394. $shipping = Db::name('express')->where('id', $post['shipping_id'])->find();
  395. if ($post['send_type'] == 1) {
  396. $delivery_data['shipping_id'] = $post['shipping_id'];
  397. $delivery_data['shipping_name'] = $shipping['name'] ?? '';
  398. }
  399. Delivery::update($delivery_data, [ [ 'order_id', '=', $post['order_id'] ] ]);
  400. return true;
  401. }
  402. /**
  403. * @notes 发货操作
  404. * @param $data
  405. * @param $admin_id
  406. * @return bool
  407. * @throws \think\db\exception\DataNotFoundException
  408. * @throws \think\db\exception\DbException
  409. * @throws \think\db\exception\ModelNotFoundException
  410. * @throws \think\exception\DbException
  411. * @author suny
  412. * @date 2021/7/14 10:24 上午
  413. */
  414. public static function deliveryHandle($data, $admin_id)
  415. {
  416. $order_id = $data['order_id'];
  417. $order = Order::where(['del' => 0, 'id' => $order_id])->find();
  418. if ($order['shipping_status'] == 1) {
  419. return true;
  420. }
  421. $shipping = Db::name('express')->where('id', $data['shipping_id'])->find();
  422. //添加发货单
  423. $delivery_data = [
  424. 'order_id' => $order_id,
  425. 'order_sn' => $order['order_sn'],
  426. 'user_id' => $order['user_id'],
  427. 'admin_id' => $admin_id,
  428. 'consignee' => $order['consignee'],
  429. 'mobile' => $order['mobile'],
  430. 'province' => $order['province'],
  431. 'city' => $order['city'],
  432. 'district' => $order['district'],
  433. 'address' => $order['address'],
  434. 'invoice_no' => $data['invoice_no'],
  435. 'send_type' => $data['send_type'],
  436. 'create_time' => time(),
  437. ];
  438. //配送方式->快递配送
  439. if ($data['send_type'] == 1) {
  440. $delivery_data['shipping_id'] = $data['shipping_id'];
  441. $delivery_data['shipping_name'] = $shipping['name'];
  442. $delivery_data['shipping_status'] = 1;
  443. }
  444. $delivery_id = Db::name('delivery')->insertGetId($delivery_data);
  445. //更新订单下商品的发货状态
  446. $order->update_time = time();
  447. $order->shipping_time = time();
  448. $order->shipping_status = 1;
  449. $order->order_status = Order::STATUS_WAIT_RECEIVE;
  450. $order->delivery_id = $delivery_id;
  451. $order->save();
  452. //订单日志
  453. OrderLogLogic::record(
  454. OrderLogEnum::TYPE_SHOP,
  455. OrderLogEnum::SHOP_DELIVERY_ORDER,
  456. $order_id,
  457. $admin_id,
  458. OrderLogEnum::SHOP_DELIVERY_ORDER
  459. );
  460. //通知用户发货
  461. if (!empty($order['mobile'])) {
  462. event('Notice', [
  463. 'scene' => NoticeEnum::ORDER_DELIVERY_NOTICE,
  464. 'mobile' => $order['mobile'],
  465. 'params' => [
  466. 'order_id' => $order['id'],
  467. 'user_id' => $order['user_id'],
  468. 'shipping_name' => $delivery_data['shipping_name'] ?? '无需快递',
  469. 'invoice_no' => $data['invoice_no'] ? : '-',
  470. ]
  471. ]);
  472. }
  473. }
  474. /**
  475. * @notes 判断是否可以发货
  476. * @param $post
  477. * @return bool|string
  478. * @throws \think\db\exception\DataNotFoundException
  479. * @throws \think\db\exception\DbException
  480. * @throws \think\db\exception\ModelNotFoundException
  481. * @author suny
  482. * @date 2021/7/14 10:24 上午
  483. */
  484. public static function checkDelivery($post)
  485. {
  486. $id = $post['order_id'];
  487. $order = Order::where(['id' => $id])->find();
  488. if (!$order) {
  489. return '订单失效';
  490. }
  491. if ($order['del'] == 1) {
  492. return '订单已删除';
  493. }
  494. if ($order['shipping_status'] == 1) {
  495. return '此订单已发货';
  496. }
  497. //
  498. if ($post['send_type'] == 1 && empty($post['invoice_no'])) {
  499. return '请输入快递单号';
  500. }
  501. if ($order['order_type'] == OrderEnum::TEAM_ORDER) {
  502. $join = TeamJoin::where(['order_id' => $order['id']])->findOrEmpty();
  503. if ($join['status'] != Team::STATUS_SUCCESS) {
  504. return '已支付的拼团订单需要等待拼团成功后才能发货';
  505. }
  506. }
  507. return true;
  508. }
  509. /**
  510. * @notes 判断是否可以取消订单
  511. * @param $post
  512. * @return bool|string
  513. * @throws \think\db\exception\DataNotFoundException
  514. * @throws \think\db\exception\DbException
  515. * @throws \think\db\exception\ModelNotFoundException
  516. * @throws \think\exception\DbException
  517. * @author suny
  518. * @date 2021/7/14 10:24 上午
  519. */
  520. public static function checkCancel($post)
  521. {
  522. $id = $post['order_id'];
  523. $order = Order::where(['id' => $id, 'del' => 0])->find();
  524. if (!$order) {
  525. return '订单失效';
  526. }
  527. if ($order['order_status'] > OrderEnum::ORDER_STATUS_DELIVERY && $order['delivery_type'] != 2) {
  528. return '此订单不可取消';
  529. }
  530. if ($order['order_status'] > OrderEnum::ORDER_STATUS_GOODS && $order['delivery_type'] == 2) {
  531. return '此订单不可取消';
  532. }
  533. if ($order['order_type'] == OrderEnum::TEAM_ORDER) {
  534. $found = Db::name('team_join')->where(['order_id' => $order['id']])->find();
  535. if ($found['status'] == Team::STATUS_WAIT_SUCCESS) {
  536. return '已支付的拼团订单需要有拼团结果才可以取消';
  537. }
  538. }
  539. return true;
  540. }
  541. /**
  542. * @notes 取消订单(返回商品规格表库存)
  543. * @param $order_id
  544. * @param $admin_id
  545. * @return bool|string
  546. * @throws \think\db\exception\DataNotFoundException
  547. * @throws \think\db\exception\ModelNotFoundException
  548. * @throws \think\exception\DbException
  549. * @throws \think\exception\PDOException
  550. * @author suny
  551. * @date 2021/7/14 10:24 上午
  552. */
  553. public static function cancel($order_id, $admin_id)
  554. {
  555. Db::startTrans();
  556. try {
  557. $order = Order::where(['id' => $order_id], ['orderGoods'])->find();
  558. // 如果是拼团订单
  559. $team_join = (new TeamJoin())->where(['order_id' => $order['id'],'status'=>TeamEnum::TEAM_STATUS_CONDUCT])->findOrEmpty()->toArray();//拼团中
  560. if ($order['order_type'] == OrderEnum::TEAM_ORDER && !empty($team_join)) {
  561. $time = time();
  562. $team_id = $team_join['team_id'];
  563. $teamJoin = (new TeamJoin())->alias('TJ')
  564. ->field(['TJ.*,O.order_sn,O.order_status,O.pay_status,O.refund_status,O.order_amount'])
  565. ->where(['team_id' => $team_id])
  566. ->join('order O', 'O.id=TJ.order_id')
  567. ->select()->toArray();
  568. TeamFound::update(['status' => TeamEnum::TEAM_STATUS_FAIL, 'team_end_time' => $time], ['id' => $team_id]);
  569. foreach ($teamJoin as $item) {
  570. TeamJoin::update(['status' => TeamEnum::TEAM_STATUS_FAIL, 'update_time' => $time], ['id' => $item['id']]);
  571. OrderRefundLogic::cancelOrder($item['order_id'], OrderLogEnum::TYPE_SHOP, $admin_id); //取消订单
  572. if ($item['pay_status'] == PayEnum::ISPAID) {
  573. $order = (new Order())->findOrEmpty($item['order_id'])->toArray();
  574. OrderRefundLogic::cancelOrderRefundUpdate($order); //更新订单状态
  575. OrderRefundLogic::refund($order, $order['order_amount'], $order['order_amount']); //订单退款
  576. }
  577. }
  578. } else {
  579. //取消订单
  580. OrderRefundLogic::cancelOrder($order_id, OrderLogEnum::TYPE_SHOP, $admin_id);
  581. //已支付的订单,取消,退款
  582. if ($order['pay_status'] == PayEnum::ISPAID) {
  583. //更新订单状态
  584. OrderRefundLogic::cancelOrderRefundUpdate($order);
  585. //订单退款
  586. OrderRefundLogic::refund($order, $order['order_amount'], $order['order_amount']);
  587. }
  588. }
  589. Db::commit();
  590. return true;
  591. } catch (\Exception $e) {
  592. Db::rollback();
  593. //增加退款失败记录
  594. OrderRefundLogic::addErrorRefund($order, $e->getMessage());
  595. return $e->getMessage();
  596. }
  597. }
  598. /**
  599. * @notes 判断是否可以删除订单
  600. * @param $post
  601. * @return bool|string
  602. * @throws \think\db\exception\DataNotFoundException
  603. * @throws \think\db\exception\DbException
  604. * @throws \think\db\exception\ModelNotFoundException
  605. * @author suny
  606. * @date 2021/7/14 10:24 上午
  607. */
  608. public static function checkDel($post)
  609. {
  610. $id = $post['order_id'];
  611. $order = Order::where(['id' => $id])->find();
  612. if (!$order) {
  613. return '订单失效';
  614. }
  615. if ($order['del'] == 1) {
  616. return '订单已删除';
  617. }
  618. if ($order['order_status'] != OrderEnum::ORDER_STATUS_DOWN) {
  619. return '此订单不可删除';
  620. }
  621. return true;
  622. }
  623. /**
  624. * @notes 删除已取消的订单
  625. * @param $order_id
  626. * @param $admin_id
  627. * @throws \think\db\exception\DataNotFoundException
  628. * @throws \think\db\exception\DbException
  629. * @throws \think\db\exception\ModelNotFoundException
  630. * @author suny
  631. * @date 2021/7/14 10:24 上午
  632. */
  633. public static function del($order_id, $admin_id)
  634. {
  635. $order = Order::where(['delete' => 0, 'id' => $order_id])->find();
  636. $order->save(['delete' => 1, 'update_time' => time()]);
  637. //订单日志
  638. OrderLogLogic::record(
  639. OrderLogEnum::TYPE_SHOP,
  640. OrderLogEnum::SHOP_DEL_ORDER,
  641. $order_id,
  642. $admin_id,
  643. OrderLogEnum::SHOP_DEL_ORDER
  644. );
  645. }
  646. /**
  647. * @notes 确认收货
  648. * @param $order_id
  649. * @param $admin_id
  650. * @throws \think\db\exception\DataNotFoundException
  651. * @throws \think\db\exception\DbException
  652. * @throws \think\db\exception\ModelNotFoundException
  653. * @author suny
  654. * @date 2021/7/14 10:25 上午
  655. */
  656. public static function confirm($order_id, $admin_id)
  657. {
  658. $order = Order::where(['del' => 0, 'id' => $order_id])->find();
  659. $order->order_status = Order::STATUS_FINISH;
  660. $order->update_time = time();
  661. $order->confirm_take_time = time();
  662. $order->save();
  663. //订单日志
  664. OrderLogLogic::record(
  665. OrderLogEnum::TYPE_SHOP,
  666. OrderLogEnum::SHOP_CONFIRM_ORDER,
  667. $order_id,
  668. $admin_id,
  669. OrderLogEnum::SHOP_CONFIRM_ORDER
  670. );
  671. }
  672. /**
  673. * @notes 订单备注
  674. * @param $post
  675. * @param string $type
  676. * @return Order|array|Model
  677. * @author suny
  678. * @date 2021/7/14 10:25 上午
  679. */
  680. public static function remarks($post, $type = "get")
  681. {
  682. if ($type === 'get') {
  683. return Order::field('id,order_remarks')
  684. ->where(['id' => $post['id']])
  685. ->findOrEmpty();
  686. } else {
  687. return Order::where(['id' => $post['id']])
  688. ->update(['order_remarks' => $post['order_remarks']]);
  689. }
  690. }
  691. /**
  692. * @notes 打印订单
  693. * @param $id
  694. * @param $shop_id
  695. * @return string|void
  696. * @author 段誉
  697. * @date 2022/1/20 11:24
  698. */
  699. public static function orderPrint($id, $shop_id)
  700. {
  701. try {
  702. //打印机配置
  703. $config = PrinterConfig::where(['status' => 1, 'shop_id' => $shop_id])->findOrEmpty();
  704. //打印机列表
  705. $printers = Printer::where([
  706. 'shop_id' => $shop_id,
  707. 'config_id' => $config['id'],
  708. 'del' => 0,
  709. 'status' => 1
  710. ])->select()->toArray();
  711. if ($config->isEmpty() || empty($printers)) {
  712. throw new Exception('请先配置打印机');
  713. }
  714. // 订单信息
  715. $order = self::getPrintOrder($id);
  716. $yly_print = new YlyPrinter($config['client_id'], $config['client_secret'], $shop_id);
  717. // 模板
  718. $template = PrinterLogic::getPrinterTpl($shop_id);
  719. $yly_print->ylyPrint($printers, $order, $template);
  720. return true;
  721. } catch (\Exception $e) {
  722. $msg = json_decode($e->getMessage(), true);
  723. if ($msg && isset($msg['error'])) {
  724. return '易联云:' . $msg['error_description'];
  725. }
  726. if (18 === $e->getCode()) {
  727. Cache::rm('yly_access_token' . $shop_id);
  728. Cache::rm('yly_refresh_token' . $shop_id);
  729. }
  730. return '易联云:' . $e->getMessage();
  731. }
  732. }
  733. /**
  734. * @notes 获取打印订单
  735. * @param $id
  736. * @return array
  737. * @author 段誉
  738. * @date 2022/1/21 9:58
  739. */
  740. public static function getPrintOrder($id)
  741. {
  742. return (new Order())
  743. ->with(['user', 'order_goods'])
  744. ->where('id', $id)
  745. ->append(['delivery_address'])
  746. ->findOrEmpty()->toArray();
  747. }
  748. /**
  749. * @notes 获取地址
  750. * @param $post
  751. * @return array
  752. * @throws \think\db\exception\DataNotFoundException
  753. * @throws \think\db\exception\DbException
  754. * @throws \think\db\exception\ModelNotFoundException
  755. * @author suny
  756. * @date 2021/7/14 10:25 上午
  757. */
  758. public static function change_address($post)
  759. {
  760. $order = new Order();
  761. $info = $order->where(['id' => $post['id']])
  762. ->field(['id', 'province', 'city', 'district', 'address','consignee','mobile'])
  763. ->find()->toArray();
  764. $info = json_encode($info, JSON_UNESCAPED_UNICODE);
  765. $address_tree = json_encode(self::getAddressTree(), JSON_UNESCAPED_UNICODE);
  766. $data = [
  767. 'info' => $info,
  768. 'address_tree' => $address_tree
  769. ];
  770. return $data;
  771. }
  772. /**
  773. * @notes 获取城市信息
  774. * @return \think\Collection
  775. * @throws \think\db\exception\DataNotFoundException
  776. * @throws \think\db\exception\DbException
  777. * @throws \think\db\exception\ModelNotFoundException
  778. * @author suny
  779. * @date 2021/7/14 10:25 上午
  780. */
  781. public static function getAddressTree()
  782. {
  783. $DevRegion = new DevRegion();
  784. $lists = $DevRegion
  785. ->field(['name', 'id', 'parent_id', 'level'])
  786. ->where('level', '>', 0)
  787. ->select();
  788. return $lists;
  789. }
  790. /**
  791. * @notes 修改地址
  792. * @param $post
  793. * @author suny
  794. * @date 2021/7/14 10:27 上午
  795. */
  796. public static function change_address_post($post)
  797. {
  798. $order = new Order();
  799. $data = [
  800. 'province' => $post['province'],
  801. 'city' => $post['city'],
  802. 'district' => $post['district'],
  803. 'address' => $post['address'],
  804. 'consignee' => $post['consignee'],
  805. 'mobile' => $post['mobile'],
  806. ];
  807. $order->where(['id' => $post['order_id']])->update($data);
  808. }
  809. /**
  810. * @notes 获取各列表数量
  811. * @param $shop_id
  812. * @return int
  813. * @author suny
  814. * @date 2021/7/14 10:27 上午
  815. */
  816. public static function getAll($shop_id)
  817. {
  818. $data = input();
  819. unset($data['type']);
  820. return Order::alias('o')
  821. ->join('shop s', 's.id = o.shop_id')
  822. ->join('user u', 'u.id = o.user_id')
  823. ->join('order_goods g', 'g.order_id = o.id')
  824. ->with(['order_goods', 'user', 'shop'])
  825. ->where(static::getWhere($data))
  826. ->where('o.shop_id', $shop_id)
  827. ->where('o.del', 0)
  828. ->where('o.delete', 0)
  829. ->group('o.id')
  830. ->count();
  831. }
  832. /**
  833. * @notes 拼装统计信息
  834. * @param $order_status
  835. * @return array
  836. * @author suny
  837. * @date 2021/7/13 3:36 下午
  838. */
  839. public static function getStat($order_status, $shop_id)
  840. {
  841. $data = input();
  842. unset($data['type']);
  843. $result = [];
  844. foreach ($order_status as $status => $title) {
  845. $num = Order::alias('o')
  846. ->join('shop s', 's.id = o.shop_id')
  847. ->join('user u', 'u.id = o.user_id')
  848. ->join('order_goods g', 'g.order_id = o.id')
  849. ->with(['order_goods', 'user', 'shop'])
  850. ->where(static::getWhere($data))
  851. ->where('o.order_status', $status)
  852. ->where('o.shop_id', $shop_id)
  853. ->where('o.del', 0)
  854. ->where('o.delete', 0)
  855. ->group('o.id')
  856. ->count();
  857. $result[] = [
  858. 'title' => $title,
  859. 'status' => $status,
  860. 'count' => $num,
  861. ];
  862. }
  863. return $result;
  864. }
  865. /**
  866. * @notes 虚拟商品发货
  867. * @param $post
  868. * @param $admin_id
  869. * @return bool|void
  870. * @throws \think\db\exception\DataNotFoundException
  871. * @throws \think\db\exception\DbException
  872. * @throws \think\db\exception\ModelNotFoundException
  873. * @author 段誉
  874. * @date 2022/4/7 17:55
  875. */
  876. public static function virtualDelivery($post, $admin_id)
  877. {
  878. try {
  879. $order_id = $post['order_id'];
  880. $order = Order::with(['order_goods'])->where(['del' => 0, 'id' => $order_id])->find();
  881. // 更新发货订单信息
  882. $result = GoodsVirtualLogic::shopSelfDelivery($order_id, $post['delivery_content']);
  883. if (true !== $result) {
  884. throw new \Exception($result);
  885. }
  886. //订单日志
  887. OrderLogLogic::record(
  888. OrderLogEnum::TYPE_SHOP,
  889. OrderLogEnum::SHOP_DELIVERY_ORDER,
  890. $order_id,
  891. $admin_id,
  892. OrderLogEnum::SHOP_DELIVERY_ORDER
  893. );
  894. //通知用户发货
  895. if (!empty($order['mobile'])) {
  896. event('Notice', [
  897. 'scene' => NoticeEnum::ORDER_DELIVERY_NOTICE,
  898. 'mobile' => $order['mobile'],
  899. 'params' => [
  900. 'order_id' => $order['id'],
  901. 'user_id' => $order['user_id'],
  902. 'shipping_name' => '无需快递',
  903. 'invoice_no' => '-',
  904. ]
  905. ]);
  906. }
  907. return true;
  908. } catch (\Exception $e) {
  909. self::$error = $e->getMessage();
  910. return false;
  911. }
  912. }
  913. /**
  914. * @notes 导出Excel
  915. * @param array $condition
  916. * @return array|false
  917. * @author 段誉
  918. * @date 2022/4/24 10:10
  919. */
  920. public static function export($condition = [])
  921. {
  922. try {
  923. $field = 'o.*,order_status as order_status_text,pay_way as pay_way_text,
  924. o.delivery_type as delivery_type_text,order_type as order_type_text,
  925. u.nickname,s.name as shop_name';
  926. $lists = Order::alias('o')
  927. ->join('shop s', 's.id = o.shop_id')
  928. ->join('user u', 'u.id = o.user_id')
  929. ->join('order_goods g', 'g.order_id = o.id')
  930. ->with(['order_goods'])
  931. ->field($field)
  932. ->where($condition)
  933. ->append(['delivery_address', 'pay_status_text', 'order_source_text'])
  934. ->order('o.id desc')
  935. ->group('o.id')
  936. ->select()
  937. ->toArray();
  938. foreach ($lists as &$item) {
  939. $orderGoodsList = [];
  940. $goodsItemList = [];
  941. $goodsPriceList = [];
  942. $goodsNumList = [];
  943. foreach ($item['order_goods'] as $good) {
  944. $orderGoodsList[] = $good['goods_name'];
  945. $goodsItemList[] = $good['spec_value'];
  946. $goodsPriceList[] = $good['goods_price'];
  947. $goodsNumList[] = $good['goods_num'];
  948. }
  949. $item['order_goods_list'] = implode(';', $orderGoodsList);
  950. $item['goods_item_list'] = implode(';', $goodsItemList);
  951. $item['goods_price_list'] = implode(';', $goodsPriceList);
  952. $item['goods_num_list'] = implode(';', $goodsNumList);
  953. }
  954. $excelFields = [
  955. 'order_sn' => '订单编号',
  956. 'order_type_text' => '订单类型',
  957. 'nickname' => '用户名称',
  958. 'order_goods_list' => '商品信息',
  959. 'goods_item_list' => '规格',
  960. 'goods_price_list' => '商品价格',
  961. 'goods_num_list' => '商品数量',
  962. 'order_amount' => '实付金额',
  963. 'consignee' => '收货人',
  964. 'mobile' => '收货人手机',
  965. 'delivery_address' => '收货地址',
  966. 'pay_status_text' => '支付状态',
  967. 'order_status_text' => '订单状态',
  968. 'create_time' => '下单时间',
  969. ];
  970. $export = new ExportExcelServer();
  971. $export->setFileName('订单');
  972. $result = $export->createExcel($excelFields, $lists);
  973. return ['url' => $result];
  974. } catch (\Exception $e) {
  975. self::$error = $e->getMessage();
  976. return false;
  977. }
  978. }
  979. /**
  980. * @notes 提货核销
  981. * @param $params
  982. * @param $adminInfo
  983. * @return bool
  984. * @author 段誉
  985. * @date 2022/11/2 14:58
  986. */
  987. public static function verification($params, $adminInfo)
  988. {
  989. Db::startTrans();
  990. try {
  991. $order = Order::find($params['order_id']);
  992. //添加核销记录
  993. Verification::create([
  994. 'order_id' => $order['id'],
  995. 'shop_id' => $order['shop_id'],
  996. 'handle_id' => $adminInfo['id'],
  997. 'verification_scene' => VerificationEnum::TYPE_SHOP,
  998. 'snapshot' => json_encode([
  999. 'sn' => $adminInfo['account'],
  1000. 'name' => $adminInfo['name']
  1001. ]),
  1002. ]);
  1003. //更新订单状态
  1004. $order->order_status = OrderEnum::ORDER_STATUS_COMPLETE;
  1005. $order->verification_status = OrderEnum::WRITTEN_OFF;
  1006. $order->confirm_take_time = time();
  1007. $order->save();
  1008. //订单日志
  1009. OrderLogLogic::record(
  1010. OrderLogEnum::TYPE_SHOP,
  1011. OrderLogEnum::SHOP_VERIFICATION,
  1012. $order['id'],
  1013. $adminInfo['id'],
  1014. OrderLogEnum::SHOP_VERIFICATION
  1015. );
  1016. Db::commit();
  1017. return true;
  1018. } catch (\Exception $e) {
  1019. Db::rollback();
  1020. self::$error = $e->getMessage();
  1021. return false;
  1022. }
  1023. }
  1024. /**
  1025. * @notes 确认付款
  1026. * @param $order_id
  1027. * @param $adminInfo
  1028. * @return string|true
  1029. * @author ljj
  1030. * @date 2024/7/19 下午6:32
  1031. */
  1032. public static function confirmPay($order_id, $adminInfo)
  1033. {
  1034. Db::startTrans();
  1035. try {
  1036. $order = Order::where(['id' => $order_id])->findOrEmpty()->toArray();
  1037. $result = PayNotifyLogic::handle('order', $order['order_sn']);
  1038. if (true !== $result) {
  1039. throw new \Exception($result);
  1040. }
  1041. Db::commit();
  1042. return true;
  1043. } catch (\Exception $e) {
  1044. Db::rollback();
  1045. return $e->getMessage();
  1046. }
  1047. }
  1048. }