Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 
 

828 righe
30 KiB

  1. <?php
  2. namespace app\admin\controller\unishop;
  3. use addons\nzf\PayService;
  4. use addons\unishop\extend\Hashids;
  5. use addons\unishop\extend\Redis;
  6. use app\admin\model\unishop\Area;
  7. use app\admin\model\unishop\OrderProduct;
  8. use app\admin\model\unishop\OrderRefund;
  9. use app\common\controller\Backend;
  10. use think\Db;
  11. use think\Exception;
  12. use think\exception\PDOException;
  13. use think\exception\ValidateException;
  14. use think\Hook;
  15. /**
  16. * 订单管理
  17. *
  18. * @icon fa fa-circle-o
  19. */
  20. class Order extends Backend
  21. {
  22. /**
  23. * 是否是关联查询
  24. */
  25. protected $relationSearch = true;
  26. protected $noNeedLogin=["export","finish","doRefund","carry","resetOrder"];
  27. /**
  28. * Order模型对象
  29. * @var \app\admin\model\unishop\Order
  30. */
  31. protected $model = null;
  32. public function _initialize()
  33. {
  34. parent::_initialize();
  35. $this->model = new \app\admin\model\unishop\Order;
  36. $this->view->assign("payTypeList", $this->model->getPayTypeList());
  37. $this->view->assign("statusList", $this->model->getStatusList());
  38. $this->view->assign("refundStatusList", $this->model->getRefundStatusList());
  39. }
  40. /**
  41. * 查看
  42. */
  43. public function index()
  44. {
  45. //设置过滤方法
  46. $this->request->filter(['strip_tags']);
  47. if ($this->request->isAjax()) {
  48. //如果发送的来源是Selectpage,则转发到Selectpage
  49. if ($this->request->request('keyField')) {
  50. return $this->selectpage();
  51. }
  52. list($where, $sort, $order, $offset, $limit) = $this->buildparams();
  53. $total = $this->model
  54. ->alias('order')
  55. ->join('user', 'user.id = order.user_id')
  56. ->where($where)
  57. ->count();
  58. $list = $this->model
  59. ->alias('order')
  60. ->join('user', 'user.id = order.user_id')
  61. ->where($where)
  62. ->order($sort, $order)
  63. ->limit($offset, $limit)
  64. ->field('order.*,user.username')
  65. ->select();
  66. $list = collection($list)->toArray();
  67. foreach ($list as &$item) {
  68. $item['id'] = (string)$item['id']; // 整形数字太大js会失准
  69. $item['user'] = [];
  70. $item['user']['username'] = $item['username'] ? $item['username'] : __('Tourist');
  71. $item['have_paid_status'] = $item['have_paid'];
  72. $item['have_delivered_status'] = $item['have_delivered'];
  73. $item['have_received_status'] = $item['have_received'];
  74. $item['have_commented_status'] = $item['have_commented'];
  75. $item["is_carry"]=$item["is_carry"]?"已提货":"未提货";
  76. $item['refund_fee'] = $item['refund_status']==3?$item['refund_fee']:'--';
  77. }
  78. $result = array("total" => $total, "rows" => $list);
  79. return json($result);
  80. }
  81. return $this->view->fetch();
  82. }
  83. /**
  84. * 生成查询所需要的条件,排序方式
  85. * @param mixed $searchfields 快速查询的字段
  86. * @param boolean $relationSearch 是否关联查询
  87. * @return array
  88. */
  89. protected function buildparams($searchfields = null, $relationSearch = null)
  90. {
  91. $searchfields = is_null($searchfields) ? $this->searchFields : $searchfields;
  92. $relationSearch = is_null($relationSearch) ? $this->relationSearch : $relationSearch;
  93. $search = $this->request->get("search", '');
  94. $filter = $this->request->get("filter", '');
  95. $op = $this->request->get("op", '', 'trim');
  96. $sort = $this->request->get("sort", "id");
  97. $order = $this->request->get("order", "DESC");
  98. $offset = $this->request->get("offset", 0);
  99. $limit = $this->request->get("limit", 0);
  100. $filter = (array)json_decode($filter, true);
  101. $op = (array)json_decode($op, true);
  102. $filter = $filter ? $filter : [];
  103. $where = [];
  104. $tableName = '';
  105. if ($relationSearch) {
  106. if (!empty($this->model)) {
  107. $name = \think\Loader::parseName(basename(str_replace('\\', '/', get_class($this->model))));
  108. $tableName = '' . $name . '.';
  109. }
  110. $sortArr = explode(',', $sort);
  111. foreach ($sortArr as $index => & $item) {
  112. $item = stripos($item, ".") === false ? $tableName . trim($item) : $item;
  113. }
  114. unset($item);
  115. $sort = implode(',', $sortArr);
  116. }
  117. $adminIds = $this->getDataLimitAdminIds();
  118. if (is_array($adminIds)) {
  119. $where[] = [$tableName . $this->dataLimitField, 'in', $adminIds];
  120. }
  121. if ($search) {
  122. $searcharr = is_array($searchfields) ? $searchfields : explode(',', $searchfields);
  123. foreach ($searcharr as $k => &$v) {
  124. $v = stripos($v, ".") === false ? $tableName . $v : $v;
  125. }
  126. unset($v);
  127. $where[] = [implode("|", $searcharr), "LIKE", "%{$search}%"];
  128. }
  129. foreach ($filter as $k => $v) {
  130. // 搜索订单状态
  131. if (in_array($k, ['have_paid_status', 'have_delivered_status', 'have_received_status', 'have_commented_status'])) {
  132. switch ($k) {
  133. case 'have_paid_status':
  134. $k = 'have_paid';
  135. break;
  136. case 'have_delivered_status':
  137. $k = 'have_delivered';
  138. break;
  139. case 'have_received_status':
  140. $k = 'have_received';
  141. break;
  142. case 'have_commented_status':
  143. $k = 'have_commented';
  144. break;
  145. }
  146. $v == 0 ? ($op[$k] = '=') : ($op[$k] = '>');
  147. $v = 0;
  148. }
  149. $sym = isset($op[$k]) ? $op[$k] : '=';
  150. if (stripos($k, ".") === false) {
  151. $k = $tableName . $k;
  152. }
  153. $v = !is_array($v) ? trim($v) : $v;
  154. $sym = strtoupper(isset($op[$k]) ? $op[$k] : $sym);
  155. switch ($sym) {
  156. case '=':
  157. case '<>':
  158. $where[] = [$k, $sym, (string)$v];
  159. break;
  160. case 'LIKE':
  161. case 'NOT LIKE':
  162. case 'LIKE %...%':
  163. case 'NOT LIKE %...%':
  164. $where[] = [$k, trim(str_replace('%...%', '', $sym)), "%{$v}%"];
  165. break;
  166. case '>':
  167. case '>=':
  168. case '<':
  169. case '<=':
  170. $where[] = [$k, $sym, intval($v)];
  171. break;
  172. case 'FINDIN':
  173. case 'FINDINSET':
  174. case 'FIND_IN_SET':
  175. $where[] = "FIND_IN_SET('{$v}', " . ($relationSearch ? $k : '`' . str_replace('.', '`.`', $k) . '`') . ")";
  176. break;
  177. case 'IN':
  178. case 'IN(...)':
  179. case 'NOT IN':
  180. case 'NOT IN(...)':
  181. $where[] = [$k, str_replace('(...)', '', $sym), is_array($v) ? $v : explode(',', $v)];
  182. break;
  183. case 'BETWEEN':
  184. case 'NOT BETWEEN':
  185. $arr = array_slice(explode(',', $v), 0, 2);
  186. if (stripos($v, ',') === false || !array_filter($arr)) {
  187. continue 2;
  188. }
  189. //当出现一边为空时改变操作符
  190. if ($arr[0] === '') {
  191. $sym = $sym == 'BETWEEN' ? '<=' : '>';
  192. $arr = $arr[1];
  193. } elseif ($arr[1] === '') {
  194. $sym = $sym == 'BETWEEN' ? '>=' : '<';
  195. $arr = $arr[0];
  196. }
  197. $where[] = [$k, $sym, $arr];
  198. break;
  199. case 'RANGE':
  200. case 'NOT RANGE':
  201. $v = str_replace(' - ', ',', $v);
  202. $arr = array_slice(explode(',', $v), 0, 2);
  203. if (stripos($v, ',') === false || !array_filter($arr)) {
  204. continue 2;
  205. }
  206. //当出现一边为空时改变操作符
  207. if ($arr[0] === '') {
  208. $sym = $sym == 'RANGE' ? '<=' : '>';
  209. $arr = $arr[1];
  210. } elseif ($arr[1] === '') {
  211. $sym = $sym == 'RANGE' ? '>=' : '<';
  212. $arr = $arr[0];
  213. }
  214. $where[] = [$k, str_replace('RANGE', 'BETWEEN', $sym) . ' time', $arr];
  215. break;
  216. case 'LIKE':
  217. case 'LIKE %...%':
  218. $where[] = [$k, 'LIKE', "%{$v}%"];
  219. break;
  220. case 'NULL':
  221. case 'IS NULL':
  222. case 'NOT NULL':
  223. case 'IS NOT NULL':
  224. $where[] = [$k, strtolower(str_replace('IS ', '', $sym))];
  225. break;
  226. default:
  227. break;
  228. }
  229. }
  230. $where = function ($query) use ($where) {
  231. foreach ($where as $k => $v) {
  232. if (is_array($v)) {
  233. call_user_func_array([$query, 'where'], $v);
  234. } else {
  235. $query->where($v);
  236. }
  237. }
  238. };
  239. return [$where, $sort, $order, $offset, $limit];
  240. }
  241. /**
  242. * 编辑
  243. */
  244. public function edit($ids = null)
  245. {
  246. $row = $this->model->get($ids);
  247. if (!$row) {
  248. $this->error(__('No Results were found'));
  249. }
  250. $adminIds = $this->getDataLimitAdminIds();
  251. if (is_array($adminIds)) {
  252. if (!in_array($row[$this->dataLimitField], $adminIds)) {
  253. $this->error(__('You have no permission'));
  254. }
  255. }
  256. if ($this->request->isPost()) {
  257. $params = $this->request->post("row/a");
  258. if ($params) {
  259. $params = $this->preExcludeFields($params);
  260. $result = false;
  261. Db::startTrans();
  262. try {
  263. //是否采用模型验证
  264. if ($this->modelValidate) {
  265. $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
  266. $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
  267. $row->validateFailException(true)->validate($validate);
  268. }
  269. $updatetime = $this->request->post('updatetime');
  270. // 乐观锁
  271. $result = $this->model->allowField(true)->save($params, ['id' => $ids, 'updatetime' => $updatetime]);
  272. if (!$result) {
  273. throw new Exception(__('Data had been update before saved, close windows and do it again'));
  274. }
  275. Db::commit();
  276. } catch (ValidateException $e) {
  277. Db::rollback();
  278. $this->error($e->getMessage());
  279. } catch (PDOException $e) {
  280. Db::rollback();
  281. $this->error($e->getMessage());
  282. } catch (Exception $e) {
  283. Db::rollback();
  284. $this->error($e->getMessage());
  285. }
  286. if ($result !== false) {
  287. $this->success();
  288. } else {
  289. $this->error(__('No rows were updated'));
  290. }
  291. }
  292. $this->error(__('Parameter %s can not be empty', ''));
  293. }
  294. $this->view->assign("row", $row);
  295. return $this->view->fetch();
  296. }
  297. /**
  298. * 物流管理
  299. */
  300. public function delivery($ids = null)
  301. {
  302. $row = $this->model->get($ids, ['extend']);
  303. if (!$row) {
  304. $this->error(__('No Results were found'));
  305. }
  306. $adminIds = $this->getDataLimitAdminIds();
  307. if (is_array($adminIds)) {
  308. if (!in_array($row[$this->dataLimitField], $adminIds)) {
  309. $this->error(__('You have no permission'));
  310. }
  311. }
  312. if ($this->request->isPost()) {
  313. $result = false;
  314. Db::startTrans();
  315. try {
  316. $express_number = $this->request->post('express_number');
  317. $have_delivered = $express_number ? time() : 0;
  318. $res1 = $row->allowField(true)->save(['have_delivered' => $have_delivered]);
  319. $res2 = $row->extend->allowField(true)->save(['express_number' => $express_number]);
  320. if ($res1 && $res2) {
  321. $result = true;
  322. } else {
  323. throw new Exception(__('No rows were updated'));
  324. }
  325. Db::commit();
  326. } catch (ValidateException $e) {
  327. Db::rollback();
  328. $this->error($e->getMessage());
  329. } catch (PDOException $e) {
  330. Db::rollback();
  331. $this->error($e->getMessage());
  332. } catch (Exception $e) {
  333. Db::rollback();
  334. $this->error($e->getMessage());
  335. }
  336. if ($result !== false) {
  337. $this->success();
  338. } else {
  339. $this->error(__('No rows were updated'));
  340. }
  341. $this->error(__('Parameter %s can not be empty', ''));
  342. }
  343. $address = json_decode($row->extend->address_json,true);
  344. if ($address) {
  345. $area = (new Area)->whereIn('id',[$address['province_id'],$address['city_id'],$address['area_id']])->column('name', 'id');
  346. $row['addressText'] = $area[$address['province_id']].$area[$address['city_id']].$area[$address['area_id']].' '.$address['address'];
  347. $row['address'] = $address;
  348. }
  349. $this->view->assign("row", $row);
  350. return $this->view->fetch();
  351. }
  352. /**
  353. * 商品管理
  354. */
  355. public function product($ids = null)
  356. {
  357. if ($this->request->isPost()) {
  358. $this->success();
  359. }
  360. $row = $this->model->get($ids, ['product','evaluate']);
  361. $this->view->assign('product', $row->product);
  362. $evaluate = [];
  363. foreach ($row->evaluate as $key => $item) {
  364. $evaluate[$item['product_id']] = $item;
  365. }
  366. $this->view->assign('order', $row);
  367. $this->view->assign('evaluate', $evaluate);
  368. return $this->view->fetch();
  369. }
  370. /**
  371. * 退货管理
  372. */
  373. public function refund($ids = null)
  374. {
  375. $row = $this->model->get($ids, ['refund']);
  376. if ($row['status'] != \app\admin\model\unishop\Order::STATUS_REFUND) {
  377. $this->error(__('This order is not returned'));
  378. }
  379. if ($this->request->isPost()) {
  380. $params = $this->request->post("row/a");
  381. if ($params) {
  382. $params = $this->preExcludeFields($params);
  383. $result = false;
  384. Db::startTrans();
  385. try {
  386. // 退款
  387. if($params['refund_action'] == 1) {
  388. $params['had_refund'] = time();
  389. Hook::add('order_refund', 'addons\\unishop\\behavior\\Order');
  390. }
  391. $updatetime = $this->request->post('updatetime');
  392. // 乐观锁
  393. $result = $this->model->allowField(true)->save($params, ['id' => $ids, 'updatetime' => $updatetime]);
  394. if (!$result) {
  395. throw new Exception(__('Data had been update before saved, close windows and do it again'));
  396. }
  397. Db::commit();
  398. } catch (ValidateException $e) {
  399. Db::rollback();
  400. $this->error($e->getMessage());
  401. } catch (PDOException $e) {
  402. Db::rollback();
  403. $this->error($e->getMessage());
  404. } catch (Exception $e) {
  405. Db::rollback();
  406. $this->error($e->getMessage());
  407. }
  408. if ($result !== false) {
  409. Hook::listen('order_refund', $row);
  410. $this->success();
  411. } else {
  412. $this->error(__('No rows were updated'));
  413. }
  414. }
  415. $this->error(__('Parameter %s can not be empty', ''));
  416. }
  417. $products = $row->product;
  418. $refundProducts = $row->refundProduct;
  419. foreach ($products as &$product) {
  420. $product['choose'] = 0;
  421. foreach ($refundProducts as $refundProduct) {
  422. if ($product['id'] == $refundProduct['order_product_id']) {
  423. $product['choose'] = 1;
  424. }
  425. }
  426. }
  427. if ($row->refund) {
  428. $refund = $row->refund->append(['receiving_status_text', 'service_type_text'])->toArray();
  429. } else {
  430. $refund = [
  431. 'service_type' => 0,
  432. 'express_number' => -1,
  433. 'receiving_status_text' => -1,
  434. 'receiving_status' => -1,
  435. 'service_type_text' => -1,
  436. 'amount' => -1,
  437. 'reason_type' => -1,
  438. 'refund_explain' => -1,
  439. ];
  440. }
  441. $this->view->assign('row', $row);
  442. $this->view->assign('product', $products);
  443. $this->view->assign('refund', $refund);
  444. return $this->view->fetch();
  445. }
  446. /**
  447. * 回收站
  448. */
  449. public function recyclebin()
  450. {
  451. //设置过滤方法
  452. $this->request->filter(['strip_tags']);
  453. if ($this->request->isAjax()) {
  454. list($where, $sort, $order, $offset, $limit) = $this->buildparams();
  455. $total = $this->model
  456. ->onlyTrashed()
  457. ->alias('order')
  458. ->join('user', 'user.id = order.user_id')
  459. ->where($where)
  460. ->count();
  461. $list = $this->model
  462. ->onlyTrashed()
  463. ->alias('order')
  464. ->join('user', 'user.id = order.user_id')
  465. ->where($where)
  466. ->field('order.*,user.username')
  467. ->order($sort, $order)
  468. ->limit($offset, $limit)
  469. ->select();
  470. $list = collection($list)->toArray();
  471. foreach ($list as &$item) {
  472. $item['id'] = (string)$item['id'];
  473. $item['user'] = [];
  474. $item['user']['username'] = $item['username'] ? $item['username'] : __('Tourist');
  475. $item['have_paid_status'] = $item['have_paid'];
  476. $item['have_delivered_status'] = $item['have_delivered'];
  477. $item['have_received_status'] = $item['have_received'];
  478. $item['have_commented_status'] = $item['have_commented'];
  479. }
  480. $result = array("total" => $total, "rows" => $list);
  481. return json($result);
  482. }
  483. return $this->view->fetch();
  484. }
  485. public function export(){
  486. $order_model=New \app\admin\model\unishop\Order();
  487. $list = $order_model
  488. ->alias('o')
  489. ->join('user', 'user.id = o.user_id')
  490. ->join('unishop_order_product', 'unishop_order_product.order_id = o.id')
  491. ->where([
  492. 'o.status'=>["<>",0]
  493. ])
  494. ->field('
  495. out_trade_no,
  496. user.username,
  497. user.nickname,
  498. user.floor,
  499. user.email,
  500. unishop_order_product.title,
  501. unishop_order_product.number as number,
  502. unishop_order_product.price,
  503. FROM_UNIXTIME(o.createtime,\'%Y-%m-%d %H:%i:%S\'),
  504. if(o.is_carry=1,\'已提货\',\'未提货\'),
  505. o.total_price,
  506. ifnull(o.refund_fee,0),
  507. if(o.status=1,\'正常\',\'退款\'),
  508. o.remark')
  509. ->group("unishop_order_product.id")
  510. ->order("o.createtime","desc")
  511. ->select();
  512. $list = collection($list)->toArray();
  513. $title = ['订单号','工号','姓名','楼层','邮箱','商品','购买数量','金额','下单时间','是否提货','订单总金额','退款金额','状态','备注'];
  514. // Create new Spreadsheet object
  515. $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
  516. $sheet = $spreadsheet->getActiveSheet();
  517. $sheet->setTitle("订单信息");
  518. // 方法一,使用 setCellValueByColumnAndRow
  519. //表头
  520. //设置单元格内容
  521. foreach ($title as $key => $value) {
  522. // 单元格内容写入
  523. $sheet->setCellValueByColumnAndRow($key + 1, 1, $value);
  524. }
  525. $row = 2; // 从第二行开始
  526. foreach ($list as $item) {
  527. $column = 1;
  528. foreach ($item as $value) {
  529. // 单元格内容写入
  530. $sheet->setCellValueByColumnAndRow($column, $row, $value);
  531. $column++;
  532. }
  533. $row++;
  534. }
  535. $sheet_two = $spreadsheet->createSheet(2)->setTitle('商品信息');
  536. $title1=["商品名称","件数","单价","总价"];
  537. $product=new \app\admin\model\unishop\OrderProduct();
  538. $product_list = $product->alias("p")
  539. ->join("unishop_order","p.order_id = unishop_order.id")
  540. ->where([
  541. 'unishop_order.have_received'=>0,
  542. 'unishop_order.status'=>1
  543. ])
  544. ->field('
  545. p.title,
  546. SUM(p.number) num,
  547. p.price,
  548. SUM(p.number)*p.price as total,
  549. p.product_id')
  550. ->group("p.id")
  551. ->select();
  552. $product_list = collection($product_list)->toArray();
  553. $product_arr=[];
  554. foreach ($product_list as $tmp_product){
  555. if (isset($product_arr[$tmp_product['product_id']])){
  556. $product_arr[$tmp_product['product_id']]["num"]+=$tmp_product['num'];
  557. $product_arr[$tmp_product['product_id']]["total"]+=$tmp_product['total'];
  558. }else{
  559. $product_arr[$tmp_product['product_id']]=$tmp_product;
  560. }
  561. }
  562. foreach ($title1 as $key => $value) {
  563. // 单元格内容写入
  564. $sheet_two->setCellValueByColumnAndRow($key + 1, 1, $value);
  565. }
  566. $row=2;
  567. foreach ($product_arr as $item) {
  568. unset($item['product_id']);
  569. $column = 1;
  570. foreach ($item as $value) {
  571. // 单元格内容写入
  572. $sheet_two->setCellValueByColumnAndRow($column, $row, $value);
  573. $column++;
  574. }
  575. $row++;
  576. }
  577. $title2=["商品名称","总库存","剩余库存"];
  578. $sheet_three= $spreadsheet->createSheet(3)->setTitle('库存信息');
  579. foreach ($title2 as $key => $value) {
  580. // 单元格内容写入
  581. $sheet_three->setCellValueByColumnAndRow($key + 1, 1, $value);
  582. }
  583. $product1=new \addons\unishop\model\Product();
  584. $product_list1 = $product1
  585. ->field('
  586. id,
  587. title,
  588. (stock+real_sales),
  589. stock')
  590. ->select();
  591. $product_list1 = collection($product_list1)->toArray();
  592. $row=2;
  593. foreach ($product_list1 as $tmp_product){
  594. unset($tmp_product["product_id"]);
  595. $column = 1;
  596. foreach ($tmp_product as $value) {
  597. // 单元格内容写入
  598. $sheet_three->setCellValueByColumnAndRow($column, $row, $value);
  599. $column++;
  600. }
  601. $row++;
  602. }
  603. $file_name="导出订单.xlsx";
  604. // Redirect output to a client’s web browser (Xlsx)
  605. header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  606. header('Content-Disposition: attachment;filename='.$file_name);
  607. header('Cache-Control: max-age=0');
  608. // If you're serving to IE 9, then the following may be needed
  609. header('Cache-Control: max-age=1');
  610. // If you're serving to IE over SSL, then the following may be needed
  611. header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
  612. header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified
  613. header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
  614. header('Pragma: public'); // HTTP/1.0
  615. $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
  616. $writer->save('php://output');
  617. exit;
  618. }
  619. public function finish(){
  620. $this->model->save(
  621. ['have_received'=>time(),
  622. "have_delivered"=>time()],
  623. ['have_received'=>0,
  624. 'status'=>1]
  625. );
  626. $this->success("提交成功", null);
  627. }
  628. public function doRefund(){
  629. $order_id = $this->request->get('id');
  630. $refund_fee = $this->request->get("refund_fee",0);
  631. if (!$this->isAmount($refund_fee)) {
  632. $this->error("退款金额格式错误");
  633. }
  634. $order = $this->model->where([
  635. 'id' => $order_id,
  636. 'status'=>1,//订单状态正常
  637. // 'have_paid'=>[">",0],//已支付
  638. // 'had_refund'=>0
  639. ])->find();
  640. if (!$order){
  641. $this->error("订单已取消,请勿重复操作");
  642. }
  643. if ($order->have_paid>0){
  644. if ($order['total_price']<$refund_fee) {
  645. $this->error("退款金额不能高于订单总金额");
  646. }
  647. //已支付
  648. self::refundOrder($order,$refund_fee);
  649. }else{
  650. $order->status = \addons\unishop\model\Order::STATUS_CANCEL;
  651. $order->save();
  652. }
  653. //回退库存
  654. $this->refundProduct($order->id);
  655. $this->success("提交成功", null);
  656. }
  657. /**
  658. * 金额校验函数
  659. * @param $value
  660. * @param bool $isZero
  661. * @param bool $negative
  662. * @return bool
  663. */
  664. function isAmount($value){
  665. // 必须是整数或浮点数,且允许为负
  666. if (!preg_match("/^[-]?\d+(.\d{1,2})?$/", $value)){
  667. return false;
  668. }
  669. // 不为负数
  670. if ((int)($value * 100) < 0){
  671. return false;
  672. }
  673. return true;
  674. }
  675. static function refundOrder($order,$refund_fee){
  676. if ($refund_fee == 0) {//如果未传入金额,则使用总金额
  677. $refund_fee = $order['total_price'];
  678. }
  679. $order->status = \addons\unishop\model\Order::STATUS_REFUND;
  680. $order->refund_status = \addons\unishop\model\Order::REFUND_STATUS_AGREE;
  681. $order->refund_fee = $refund_fee;
  682. $result = $order->save();
  683. if ($result !== false){
  684. //order_id:订单ID name:订单名称 total_fee:总金额-元 refund_fee退款金额
  685. $param = [
  686. "order_id"=>$order['out_trade_no'],
  687. "total_fee"=>$order['total_price'],
  688. "refund_fee"=>$refund_fee,
  689. "memo"=>'订单退款',
  690. ];
  691. PayService::cancel($param,$order["pay_type"]);
  692. return;
  693. }
  694. }
  695. public function refundProduct($order_id){
  696. $model=new OrderProduct();
  697. $order =$model->where([
  698. 'order_id' => $order_id,
  699. ])->select();
  700. if (!$order){
  701. return;
  702. }
  703. $list = collection($order)->toArray();
  704. $product = new \app\admin\model\unishop\Product();
  705. foreach ($list as $val){
  706. try {
  707. $product->where(["id" => $val['product_id']])->setInc("stock", $val["number"]);
  708. $product->where(["id" => $val['product_id']])->setInc("real_sales", -$val["number"]);
  709. } catch (Exception $e) {
  710. }
  711. }
  712. }
  713. public function carry($ids = null)
  714. {
  715. $this->model->save(
  716. ['is_carry'=>1],
  717. ['id'=>["in",$ids]]
  718. );
  719. $this->success("确认成功", null);
  720. }
  721. public function refundShow(){
  722. $id = $this->request->get("id");
  723. $refund_fee = $this->request->get("refund_fee");
  724. $this->view->assign('id', $id);
  725. $this->view->assign('refund_fee', $refund_fee);
  726. return $this->view->fetch();
  727. }
  728. public function resetOrder(){
  729. $out_trade_no = $this->request->get("out_trade_no");;
  730. $prod_id = $this->request->get("prod_id");;
  731. $order = $this->model->where([
  732. 'out_trade_no' => $out_trade_no])->find();
  733. if (!$order){
  734. return "查询主订单失败";
  735. }
  736. //库存回滚
  737. $model=new OrderProduct();
  738. $sborder =$model->where([
  739. 'order_id' => $order['id'],
  740. 'product_id'=>$prod_id
  741. ])->find();
  742. if (!$sborder){
  743. return "查询子订单失败";
  744. }
  745. try {
  746. //退款金额
  747. $refund_fee = $sborder->price*$sborder->number;
  748. //修改退款金额
  749. $orderModel = new \app\admin\model\unishop\Order();
  750. $orderModel->where(["id"=>$order['id']])->setInc("refund_fee",$refund_fee);
  751. //退款
  752. $param = [
  753. "order_id"=>$order['out_trade_no'],
  754. "total_fee"=>$order['total_price'],
  755. "refund_fee"=>$refund_fee,
  756. "memo"=>'订单退款',
  757. ];
  758. $result = PayService::cancel($param,$order["pay_type"]);
  759. if (!$result['flag']) {
  760. return "退款失败".$result['msg'];
  761. }
  762. //修改库存
  763. $product = new \app\admin\model\unishop\Product();
  764. $product->where(["id" => $prod_id])->setInc("stock", $sborder["number"]);
  765. $product->where(["id" => $prod_id])->setInc("real_sales", -$sborder["number"]);
  766. //删除表数据
  767. $modelde=new OrderProduct();
  768. $modelde->where([
  769. 'order_id' => $order['id'],
  770. 'product_id'=>$prod_id
  771. ])->delete();
  772. return "完成";
  773. } catch (Exception $e) {
  774. return "失败".$e->getMessage();
  775. }
  776. }
  777. }