Order.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. <?php
  2. namespace app\admin\controller\shop;
  3. use addons\shop\model\TemplateMsg;
  4. use app\common\controller\Backend;
  5. use app\admin\model\shop\OrderGoods;
  6. use app\admin\model\shop\OrderAftersales;
  7. use app\admin\model\shop\OrderAction;
  8. use app\admin\model\shop\OrderElectronics;
  9. /**
  10. * 订单管理
  11. *
  12. * @icon fa fa-circle-o
  13. */
  14. class Order extends Backend
  15. {
  16. /**
  17. * Order模型对象
  18. * @var \app\admin\model\shop\Order
  19. */
  20. protected $model = null;
  21. protected $relationSearch = true;
  22. protected $searchFields = 'id,order_sn';
  23. public function _initialize()
  24. {
  25. parent::_initialize();
  26. $this->model = new \app\admin\model\shop\Order;
  27. $this->view->assign("orderstateList", $this->model->getOrderstateList());
  28. $this->view->assign("shippingstateList", $this->model->getShippingstateList());
  29. $this->view->assign("paystateList", $this->model->getPaystateList());
  30. $this->view->assign("statusList", $this->model->getStatusList());
  31. }
  32. /**
  33. * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
  34. * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
  35. * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
  36. */
  37. /**
  38. * 查看
  39. */
  40. public function index()
  41. {
  42. //设置过滤方法
  43. $this->request->filter(['strip_tags', 'trim']);
  44. if ($this->request->isAjax()) {
  45. //如果发送的来源是Selectpage,则转发到Selectpage
  46. if ($this->request->request('keyField')) {
  47. return $this->selectpage();
  48. }
  49. list($where, $sort, $order, $offset, $limit, , $alias) = $this->buildparams();
  50. $a = reset($alias);
  51. $list = $this->model
  52. ->field($a . '.*,oe.print_template,oe.id oe_id')
  53. ->alias($alias)
  54. ->where($where)
  55. ->join('shop_order_electronics oe', $a . '.order_sn=oe.order_sn and oe.status=0', 'LEFT')
  56. ->order($sort, $order)
  57. ->paginate($limit);
  58. $result = array("total" => $list->total(), "rows" => $list->items());
  59. return json($result);
  60. }
  61. $config = get_addon_config('shop');
  62. $this->assignconfig('shop', $config);
  63. return $this->view->fetch();
  64. }
  65. //发货单列表
  66. public function orderList()
  67. {
  68. $ids = $this->request->post('ids/a');
  69. if (empty($ids)) {
  70. $this->error('参数错误');
  71. }
  72. $orderList = $this->model->with(['User', 'OrderGoods'])->order('createtime desc')->where('id', 'IN', $ids)->select();
  73. foreach ($orderList as $index => $item) {
  74. if ($item->user) {
  75. $item->user->visible(['id', 'nickname', 'avatar']);
  76. }
  77. }
  78. $orderList = collection($orderList)->toArray();
  79. foreach ($orderList as $index => &$item) {
  80. $nums = 0;
  81. foreach ($item['order_goods'] as $key => $goods) {
  82. if ($goods['salestate'] == 4 || $goods['salestate'] == 5) {
  83. unset($item['order_goods'][$key]);
  84. }
  85. $nums += $goods['nums'];
  86. }
  87. $item['nums'] = $nums;
  88. }
  89. $this->success('获取成功', '', ['orderList' => $orderList]);
  90. }
  91. //订单详情
  92. public function detail()
  93. {
  94. $id = $this->request->param('ids');
  95. if (!$id) {
  96. $this->error('参数错误');
  97. }
  98. $row = $this->model->field('o.*,sum(s.refund) refund')->with(['User', 'OrderGoods', 'OrderAction'])
  99. ->where('o.id', $id)
  100. ->alias('o')
  101. ->join('shop_order_aftersales s', 'o.id=s.order_id and s.status=2 and s.type <> 3', 'LEFT')
  102. ->find();
  103. if (!$row) {
  104. $this->error('记录未找到');
  105. }
  106. //计算单个商品折扣后的价格
  107. $saleamount = bcsub($row['saleamount'], $row['shippingfee'], 2);
  108. $saleratio = $row['goodsprice'] > 0 ? bcdiv($saleamount, $row['goodsprice'], 10) : 1;
  109. $saleremains = $saleamount;
  110. $orderItem = $row->order_goods;
  111. foreach ($orderItem as $index => $item) {
  112. if (!isset($orderItem[$index + 1])) {
  113. $saleprice = $saleremains;
  114. } else {
  115. $saleprice = $row['discount'] == 0 ? bcmul($item['price'], $item['nums'], 2) : bcmul(bcmul($item['price'], $item['nums'], 2), $saleratio, 2);
  116. }
  117. $saleremains = bcsub($saleremains, $saleprice, 2);
  118. $item['saleprice'] = $saleprice;
  119. }
  120. $config = get_addon_config('shop');
  121. $this->assignconfig('shop', $config);
  122. $this->view->assign('row', $row);
  123. return $this->view->fetch();
  124. }
  125. //订单状态操作
  126. public function edit_status()
  127. {
  128. $orderstate = $this->request->post('orderstate');
  129. $paystate = $this->request->post('paystate');
  130. $order_id = $this->request->post('order_id');
  131. $order = $this->model->where('id', $order_id)->find();
  132. if (!$order) {
  133. $this->error('未找到订单记录');
  134. }
  135. //取消
  136. if ($orderstate == 1 && $order->orderstate == 0 && $order->paystate == 0) {
  137. $order->orderstate = 1;
  138. $order->canceltime = time();
  139. $order->save();
  140. $this->success('取消成功');
  141. }
  142. // 支付
  143. if ($paystate == 1 && $order->orderstate == 0 && $order->paystate == 0) {
  144. $order->paystate = 1;
  145. $order->paytype = 'system';
  146. $order->method = 'system';
  147. $order->payamount = $order->saleamount;
  148. $order->paytime = time();
  149. $order->save();
  150. //发送通知
  151. TemplateMsg::sendTempMsg(0, $order->order_sn);
  152. $this->success('操作成功');
  153. }
  154. //已完成
  155. if ($orderstate == 3 && $order->orderstate == 0 && $order->paystate == 1) {
  156. $order->orderstate = 3;
  157. $order->save();
  158. OrderAction::push($order->order_sn, '更改订单为已完成', '管理员');
  159. $this->success('操作成功');
  160. } elseif ($order->orderstate == 4) {
  161. $this->error("请完成售后后再进行操作");
  162. }
  163. $this->error('没有权限操作');
  164. }
  165. //同意退款(退货)
  166. public function refund()
  167. {
  168. $id = $this->request->post('order_goods_id');
  169. if (!$id) {
  170. $this->error('参数错误');
  171. }
  172. $orderGoods = OrderGoods::get($id, ['Order']);
  173. if (empty($orderGoods)) {
  174. $this->error('未找到记录');
  175. }
  176. $order = $orderGoods->order;
  177. if (empty($order)) {
  178. $this->error('订单不存在');
  179. }
  180. if ($orderGoods->salestate != 3) {
  181. $this->error('不支持的售后状态');
  182. }
  183. $aftersales = (new OrderAftersales())
  184. ->where('order_goods_id', $id)
  185. ->where('user_id', $order->user_id)
  186. ->where('status', 2)
  187. ->order('id desc')
  188. ->find();
  189. if (!$aftersales) {
  190. $this->error('售后单未找到');
  191. }
  192. if ($aftersales['type'] == 2) {
  193. //已退货退款
  194. $orderGoods->salestate = 5;
  195. $orderGoods->save();
  196. //已通过,是否同步退款
  197. $config = get_addon_config('shop');
  198. if ($config['order_refund_sync']) {
  199. //执行同步退款
  200. try {
  201. \app\admin\model\shop\Order::refund($order->order_sn, $order->paytype, $aftersales->refund);
  202. } catch (\Exception $e) {
  203. $this->error($e->getMessage());
  204. }
  205. }
  206. //记录操作
  207. OrderAction::push($order->order_sn, '确认售后商品已收到', '管理员');
  208. $count = \app\admin\model\shop\OrderGoods::where('order_sn', $order['order_sn'])->where('salestate', 'not in', [4, 5])->count();
  209. if (!$count) {
  210. $order->refundtime = time();
  211. $order->orderstate = 3;
  212. $order->save();
  213. } else {
  214. $order->orderstate = 0;
  215. $order->save();
  216. }
  217. }
  218. $this->success('确认收货成功!');
  219. }
  220. //编辑订单信息【备注等】
  221. public function edit_info()
  222. {
  223. $id = $this->request->post('id');
  224. $field = $this->request->post('field');
  225. $value = $this->request->post('value');
  226. if (!in_array($field, ['memo'])) {
  227. $this->error('没有权限编辑');
  228. }
  229. $row = $this->model->with(['User'])->where('id', $id)->find();
  230. if (!$row) {
  231. $this->error('记录未找到');
  232. }
  233. $row->$field = $value;
  234. $row->save();
  235. $this->success('保存成功');
  236. }
  237. //发货
  238. public function deliver()
  239. {
  240. $expressname = $this->request->post('expressname');
  241. $expressno = $this->request->post('expressno');
  242. $order_id = $this->request->post('order_id');
  243. $type = $this->request->post('type');
  244. $order = $this->model->where('id', $order_id)->find();
  245. if (!$order) {
  246. $this->error('未找到订单记录');
  247. }
  248. //发货 / 修改快递信息
  249. if ($order->orderstate == 0 && $order->shippingstate == 0 && $order->paystate == 1 && $type == 0) {
  250. $order->expressname = $expressname;
  251. $order->expressno = $expressno;
  252. $order->shippingstate = 1;
  253. $order->shippingtime = time();
  254. $order->save();
  255. $this->success('发货成功');
  256. } elseif ($type == 1) {
  257. $order->expressname = $expressname;
  258. $order->expressno = $expressno;
  259. $order->save();
  260. $this->success('修改成功');
  261. } elseif ($order->orderstate == 4) {
  262. $this->error("请完成售后后再进行操作");
  263. }
  264. $this->error('没有权限操作');
  265. }
  266. //电子面单【单独】
  267. public function electronics()
  268. {
  269. $order_id = $this->request->param('order_id');
  270. $row = $this->model->field('o.id,oe.print_template')
  271. ->where('o.id', $order_id)
  272. ->alias('o')
  273. ->join('shop_order_electronics oe', 'oe.order_sn=o.order_sn and oe.status=0', 'LEFT')
  274. ->find();
  275. if ($row && !empty($row['print_template'])) {
  276. $this->success('获取成功', '', ['PrintTemplate' => $row->print_template]);
  277. }
  278. $res = [];
  279. $electronics_id = $this->request->param('electronics_id');
  280. try {
  281. $res = \addons\shop\library\KdApiExpOrder::create($order_id, $electronics_id);
  282. } catch (\Exception $e) {
  283. $this->error($e->getMessage());
  284. }
  285. if (!isset($res['Success']) || !$res['Success']) {
  286. $msg = isset($res['Reason']) ? $res['Reason'] : '请求失败';
  287. $this->error($msg);
  288. }
  289. //成功
  290. $this->success('开始打印', '', $res);
  291. }
  292. //批量打印
  293. public function prints()
  294. {
  295. $ids = $this->request->param('ids');
  296. if (empty($ids)) {
  297. $this->error('打印参数错误');
  298. }
  299. $order_ids = explode('_', $ids);
  300. if ($this->request->isPost()) {
  301. $electronics_id = $this->request->post('electronics_id');
  302. $param = [];
  303. //是否已获取
  304. $list = $this->model->field('o.id,oe.print_template')
  305. ->where('o.id', 'IN', $order_ids)
  306. ->alias('o')
  307. ->join('shop_order_electronics oe', 'oe.order_sn=o.order_sn and oe.status=0', 'LEFT')
  308. ->select();
  309. $has_ids = [];
  310. //获取过的
  311. if ($list) {
  312. foreach ($list as $item) {
  313. if (!empty($item['print_template'])) {
  314. $param[] = [
  315. 'PrintTemplate' => $item['print_template'],
  316. 'Success' => true
  317. ];
  318. $has_ids[] = $item['id'];
  319. }
  320. }
  321. }
  322. //剩余未获取的
  323. try {
  324. foreach (array_diff($order_ids, $has_ids) as $order_id) {
  325. $res = \addons\shop\library\KdApiExpOrder::create($order_id, $electronics_id);
  326. if ($res) {
  327. $param[] = $res;
  328. }
  329. }
  330. } catch (\Exception $e) {
  331. $this->error($e->getMessage());
  332. }
  333. $this->success('操作成功', '', $param);
  334. }
  335. $config = get_addon_config('shop');
  336. $this->assignconfig('shop', $config);
  337. $this->assignconfig('order_ids', $order_ids);
  338. $order = $this->model->with(['OrderGoods'])->where('id', 'IN', $order_ids)->select();
  339. $this->view->assign('order', $order);
  340. return $this->view->fetch();
  341. }
  342. //取消电子面单
  343. public function cancel_electronics()
  344. {
  345. $oe_id = $this->request->param('oe_id');
  346. $row = OrderElectronics::get($oe_id);
  347. if ($row['status'] == 1) {
  348. $this->error('电子面单已取消');
  349. }
  350. $res = \addons\shop\library\KdApiExpOrder::cancel($row);
  351. if (isset($res['Success']) && $res['Success']) {
  352. $row->status = 1;
  353. $row->save();
  354. $this->success('取消成功', '', $res);
  355. }
  356. $msg = isset($res['Reason']) ? $res['Reason'] : '取消失败';
  357. $this->error($msg);
  358. }
  359. //退款查询
  360. protected function refunded($order)
  361. {
  362. $config = \addons\epay\library\Service::getConfig($order['paytype']);
  363. $response = null;
  364. try {
  365. if ($order['paytype'] == 'wechat') {
  366. $response = \Yansongda\Pay\Pay::wechat($config)->find([
  367. 'type' => in_array($order['method'], ['miniapp', 'app']) ? $order['method'] : '',
  368. 'out_trade_no' => $order['order_sn']
  369. ], 'refund');
  370. } elseif ($order['paytype'] == 'alipay') {
  371. $response = \Yansongda\Pay\Pay::alipay($config)->find([
  372. 'out_trade_no' => $order['order_sn'],
  373. 'out_request_no' => $order['order_sn']
  374. ], 'refund');
  375. }
  376. } catch (\Exception $e) {
  377. $this->assign('refunded_info', '查询退款失败,' . $e->getMessage());
  378. }
  379. if ($order['paytype'] == 'wechat') {
  380. if ($response && $response['return_msg'] == 'OK') {
  381. $this->assign('refunded_info', '已成功退款:' . $response->refund_fee / 100 . '元。');
  382. }
  383. } elseif ($order['paytype'] == 'alipay') {
  384. if ($response && $response['msg'] == 'Success') {
  385. $this->assign('refunded_info', '已成功退款:' . $response->refund_amount . '元。');
  386. }
  387. } else {
  388. $this->assign('refunded_info', "未知支付类型");
  389. }
  390. }
  391. }