You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

777 lines
28 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"];
  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. refund_fee,
  506. if(o.status=1,\'正常\',\'退款\'),
  507. o.remark')
  508. ->group("unishop_order_product.id")
  509. ->order("o.createtime","desc")
  510. ->select();
  511. $list = collection($list)->toArray();
  512. $title = ['订单号','工号','姓名','楼层','邮箱','商品','购买数量','总金额','下单时间','是否提货','退款金额','状态','备注'];
  513. // Create new Spreadsheet object
  514. $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
  515. $sheet = $spreadsheet->getActiveSheet();
  516. $sheet->setTitle("订单信息");
  517. // 方法一,使用 setCellValueByColumnAndRow
  518. //表头
  519. //设置单元格内容
  520. foreach ($title as $key => $value) {
  521. // 单元格内容写入
  522. $sheet->setCellValueByColumnAndRow($key + 1, 1, $value);
  523. }
  524. $row = 2; // 从第二行开始
  525. foreach ($list as $item) {
  526. $column = 1;
  527. foreach ($item as $value) {
  528. // 单元格内容写入
  529. $sheet->setCellValueByColumnAndRow($column, $row, $value);
  530. $column++;
  531. }
  532. $row++;
  533. }
  534. $sheet_two = $spreadsheet->createSheet(2)->setTitle('商品信息');
  535. $title1=["商品名称","件数","单价","总价"];
  536. $product=new \app\admin\model\unishop\OrderProduct();
  537. $product_list = $product->alias("p")
  538. ->join("unishop_order","p.order_id = unishop_order.id")
  539. ->where([
  540. 'unishop_order.have_received'=>0,
  541. 'unishop_order.status'=>1
  542. ])
  543. ->field('
  544. p.title,
  545. SUM(p.number) num,
  546. p.price,
  547. SUM(p.number)*p.price as total,
  548. p.product_id')
  549. ->group("p.id")
  550. ->select();
  551. $product_list = collection($product_list)->toArray();
  552. $product_arr=[];
  553. foreach ($product_list as $tmp_product){
  554. if (isset($product_arr[$tmp_product['product_id']])){
  555. $product_arr[$tmp_product['product_id']]["num"]+=$tmp_product['num'];
  556. $product_arr[$tmp_product['product_id']]["total"]+=$tmp_product['total'];
  557. }else{
  558. $product_arr[$tmp_product['product_id']]=$tmp_product;
  559. }
  560. }
  561. foreach ($title1 as $key => $value) {
  562. // 单元格内容写入
  563. $sheet_two->setCellValueByColumnAndRow($key + 1, 1, $value);
  564. }
  565. $row=2;
  566. foreach ($product_arr as $item) {
  567. unset($item['product_id']);
  568. $column = 1;
  569. foreach ($item as $value) {
  570. // 单元格内容写入
  571. $sheet_two->setCellValueByColumnAndRow($column, $row, $value);
  572. $column++;
  573. }
  574. $row++;
  575. }
  576. $title2=["商品名称","总库存","剩余库存"];
  577. $sheet_three= $spreadsheet->createSheet(3)->setTitle('库存信息');
  578. foreach ($title2 as $key => $value) {
  579. // 单元格内容写入
  580. $sheet_three->setCellValueByColumnAndRow($key + 1, 1, $value);
  581. }
  582. $product1=new \addons\unishop\model\Product();
  583. $product_list1 = $product1
  584. ->field('
  585. id,
  586. title,
  587. (stock+real_sales),
  588. stock')
  589. ->select();
  590. $product_list1 = collection($product_list1)->toArray();
  591. $row=2;
  592. foreach ($product_list1 as $tmp_product){
  593. unset($tmp_product["product_id"]);
  594. $column = 1;
  595. foreach ($tmp_product as $value) {
  596. // 单元格内容写入
  597. $sheet_three->setCellValueByColumnAndRow($column, $row, $value);
  598. $column++;
  599. }
  600. $row++;
  601. }
  602. $file_name="导出订单.xlsx";
  603. // Redirect output to a client’s web browser (Xlsx)
  604. header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  605. header('Content-Disposition: attachment;filename='.$file_name);
  606. header('Cache-Control: max-age=0');
  607. // If you're serving to IE 9, then the following may be needed
  608. header('Cache-Control: max-age=1');
  609. // If you're serving to IE over SSL, then the following may be needed
  610. header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
  611. header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified
  612. header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
  613. header('Pragma: public'); // HTTP/1.0
  614. $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
  615. $writer->save('php://output');
  616. exit;
  617. }
  618. public function finish(){
  619. $this->model->save(
  620. ['have_received'=>time(),
  621. "have_delivered"=>time()],
  622. ['have_received'=>0,
  623. 'status'=>1]
  624. );
  625. $this->success("提交成功", null);
  626. }
  627. public function doRefund(){
  628. $order_id = $this->request->get('id');
  629. $refund_fee = $this->request->get("refund_fee",0);
  630. if (!$this->isAmount($refund_fee)) {
  631. $this->error("退款金额格式错误");
  632. }
  633. $order = $this->model->where([
  634. 'id' => $order_id,
  635. 'status'=>1,//订单状态正常
  636. // 'have_paid'=>[">",0],//已支付
  637. // 'had_refund'=>0
  638. ])->find();
  639. if (!$order){
  640. $this->error("订单已取消,请勿重复操作");
  641. }
  642. if ($order->have_paid>0){
  643. if ($order['total_price']<$refund_fee) {
  644. $this->error("退款金额不能高于订单总金额");
  645. }
  646. //已支付
  647. self::refundOrder($order,$refund_fee);
  648. }else{
  649. $order->status = \addons\unishop\model\Order::STATUS_CANCEL;
  650. $order->save();
  651. }
  652. //回退库存
  653. $this->refundProduct($order->id);
  654. $this->success("提交成功", null);
  655. }
  656. /**
  657. * 金额校验函数
  658. * @param $value
  659. * @param bool $isZero
  660. * @param bool $negative
  661. * @return bool
  662. */
  663. function isAmount($value){
  664. // 必须是整数或浮点数,且允许为负
  665. if (!preg_match("/^[-]?\d+(.\d{1,2})?$/", $value)){
  666. return false;
  667. }
  668. // 不为负数
  669. if ((int)($value * 100) < 0){
  670. return false;
  671. }
  672. return true;
  673. }
  674. static function refundOrder($order,$refund_fee){
  675. if ($refund_fee == 0) {//如果未传入金额,则使用总金额
  676. $refund_fee = $order['total_price'];
  677. }
  678. $order->status = \addons\unishop\model\Order::STATUS_REFUND;
  679. $order->refund_status = \addons\unishop\model\Order::REFUND_STATUS_AGREE;
  680. $order->refund_fee = $refund_fee;
  681. $result = $order->save();
  682. if ($result !== false){
  683. //order_id:订单ID name:订单名称 total_fee:总金额-元 refund_fee退款金额
  684. $param = [
  685. "order_id"=>$order['out_trade_no'],
  686. "total_fee"=>$order['total_price'],
  687. "refund_fee"=>$refund_fee,
  688. "memo"=>'订单退款',
  689. ];
  690. PayService::cancel($param,$order["pay_type"]);
  691. return;
  692. }
  693. }
  694. public function refundProduct($order_id){
  695. $model=new OrderProduct();
  696. $order =$model->where([
  697. 'order_id' => $order_id,
  698. ])->select();
  699. if (!$order){
  700. return;
  701. }
  702. $list = collection($order)->toArray();
  703. $product = new \app\admin\model\unishop\Product();
  704. foreach ($list as $val){
  705. try {
  706. $product->where(["id" => $val['product_id']])->setInc("stock", $val["number"]);
  707. $product->where(["id" => $val['product_id']])->setInc("real_sales", -$val["number"]);
  708. } catch (Exception $e) {
  709. }
  710. }
  711. }
  712. public function carry($ids = null)
  713. {
  714. $this->model->save(
  715. ['is_carry'=>1],
  716. ['id'=>["in",$ids]]
  717. );
  718. $this->success("确认成功", null);
  719. }
  720. public function refundShow(){
  721. $id = $this->request->get("id");
  722. $refund_fee = $this->request->get("refund_fee");
  723. $this->view->assign('id', $id);
  724. $this->view->assign('refund_fee', $refund_fee);
  725. return $this->view->fetch();
  726. }
  727. }