RefundController.php 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. <?php
  2. //退款退货
  3. namespace ghs\controllers;
  4. use bizGhs\notify\classes\NotifyClass;
  5. use bizGhs\order\classes\CheckOrderClass;
  6. use bizGhs\order\classes\RefundOrderItemClass;
  7. use bizGhs\order\services\RefundOrderService;
  8. use bizGhs\order\services\NextDayRefundService;
  9. use bizGhs\shop\classes\ShopClass;
  10. use bizHd\cg\classes\CgRefundClass;
  11. use bizHd\cg\classes\CgRefundItemClass;
  12. use bizHd\notice\classes\NoticeClass;
  13. use bizHd\purchase\classes\PurchaseClass;
  14. use common\components\dateUtil;
  15. use common\components\dict;
  16. use common\components\imgUtil;
  17. use Yii;
  18. use bizGhs\order\classes\RefundOrderClass;
  19. use common\components\util;
  20. use bizGhs\product\classes\ProductClass;
  21. use bizGhs\order\classes\OrderClass;
  22. use bizGhs\order\services\OrderService;
  23. use bizGhs\order\classes\StockWastageOrderClass;
  24. class RefundController extends BaseController
  25. {
  26. /**
  27. * 原单是否可走隔天售后(售后页预检)
  28. * GET: orderId
  29. */
  30. public function actionCheckNextDayEligible()
  31. {
  32. $orderId = Yii::$app->request->get('orderId', 0);
  33. $order = OrderClass::getById($orderId, true);
  34. if (empty($order) || intval($order->mainId) !== intval($this->mainId)) {
  35. util::fail('没有找到订单');
  36. }
  37. $check = NextDayRefundService::checkEligible($order);
  38. $check['hasPayTime'] = NextDayRefundService::hasValidPayTime($order) ? 1 : 0;
  39. $check['hasNextDay'] = bccomp((string)($order->nextDayTkPrice ?? '0'), '0', 2) > 0 ? 1 : 0;
  40. $check['nextDayTkPrice'] = $order->nextDayTkPrice ?? '0.00';
  41. $check['tkPrice'] = $order->tkPrice ?? '0.00';
  42. $check['actPrice'] = $order->actPrice ?? '0.00';
  43. $check['payWay'] = $order->payWay ?? 0;
  44. $check['onlinePay'] = $order->onlinePay ?? 0;
  45. $check['debtPrice'] = $order->debtPrice ?? '0.00';
  46. $check['remainDebtPrice'] = $order->remainDebtPrice ?? '0.00';
  47. $check['clearId'] = intval($order->clearId ?? 0);
  48. $check['payTime'] = $order->payTime ?? '';
  49. util::success($check);
  50. }
  51. //取消的订单退钱,特殊情况的操作:商家取消订单时,客户同时付款成功了,造成的流程冲突,需要退钱 ssh 20250429
  52. public function actionRefundMoney()
  53. {
  54. $get = Yii::$app->request->get();
  55. $id = $get['id'] ?? '';
  56. $order = OrderClass::getById($id, true);
  57. if (empty($order)) {
  58. util::fail('没有找到订单');
  59. }
  60. if ($order->mainId != $this->mainId) {
  61. util::fail('不是你的订单');
  62. }
  63. $addTime = $order->addTime;
  64. $addTime = strtotime($addTime);
  65. $earTime = strtotime('2025-05-01 00:00:00');
  66. if ($addTime < $earTime) {
  67. util::fail('2025.5.1号前的订单,不能退款');
  68. }
  69. $shop = $this->shop;
  70. $purchaseId = $order->purchaseId ?? 0;
  71. $cg = PurchaseClass::getById($purchaseId, true);
  72. if (empty($cg)) {
  73. util::fail('没有找到订单');
  74. }
  75. $staff = $this->shopAdmin;
  76. if ($staff->mobile != '15280215347') {
  77. util::fail('请联系管理员操作');
  78. }
  79. $respond = CgRefundClass::onlyRefundMoney($shop, $cg);
  80. $status = $respond['status'];
  81. $msg = $respond['msg'];
  82. util::success(['status' => $status], $msg);
  83. }
  84. //修改金额 ssh 20240412
  85. public function actionModifyAmount()
  86. {
  87. $get = Yii::$app->request->get();
  88. $id = $get['id'] ?? 0;
  89. $amount = $get['amount'] ?? 0;
  90. $refund = RefundOrderClass::getById($id, true);
  91. RefundOrderClass::valid($refund, $this->mainId);
  92. if (is_numeric($amount) == false) {
  93. util::fail('请填写金额');
  94. }
  95. if ($refund->status != 0) {
  96. util::fail('待审核订单才能修改');
  97. }
  98. $connection = Yii::$app->db;
  99. $transaction = $connection->beginTransaction();
  100. try {
  101. $refund->refundPrice = $amount;
  102. $refund->save();
  103. $cgRefundId = $refund->cgRefundId ?? 0;
  104. $cgRefund = CgRefundClass::getById($cgRefundId, true);
  105. if (empty($cgRefund)) {
  106. util::fail('没有找到退款信息');
  107. }
  108. $cgRefund->refundPrice = $amount;
  109. $cgRefund->save();
  110. $transaction->commit();
  111. util::complete();
  112. } catch (\Exception $e) {
  113. $transaction->rollBack();
  114. Yii::info("操作失败原因:" . $e->getMessage());
  115. util::fail('操作失败');
  116. }
  117. }
  118. //修改申请原因 ssh 20240302
  119. public function actionModifyCause()
  120. {
  121. $staff = $this->shopAdmin;
  122. if (isset($staff->finance) == false || $staff->finance == 0) {
  123. util::fail('请有财务权限的人修改');
  124. }
  125. $get = Yii::$app->request->get();
  126. $id = $get['id'] ?? 0;
  127. $cause = $get['cause'] ?? 0;
  128. $refund = RefundOrderClass::getById($id, true);
  129. RefundOrderClass::valid($refund, $this->mainId);
  130. $refund->cause = $cause;
  131. $refund->save();
  132. $orderSn = $refund->orderSn ?? '';
  133. RefundOrderItemClass::updateByCondition(['orderSn' => $orderSn], ['cause' => $cause]);
  134. $cgRefundId = $refund->cgRefundId ?? 0;
  135. $cgRefund = CgRefundClass::getById($cgRefundId, true);
  136. if (empty($cgRefund)) {
  137. util::fail('没有找到退款信息');
  138. }
  139. $cgRefund->cause = $cause;
  140. $cgRefund->save();
  141. $cgOrderSn = $cgRefund->orderSn ?? '';
  142. CgRefundItemClass::updateByCondition(['orderSn' => $cgOrderSn], ['cause' => $cause]);
  143. util::complete('修改成功');
  144. }
  145. //审核通过 ssh 20230811
  146. public function actionPass()
  147. {
  148. $shopAdmin = $this->shopAdmin;
  149. if (isset($shopAdmin->super) == false || $shopAdmin->super != 1) {
  150. util::fail('无法操作');
  151. }
  152. //多处要同步修改ghs_refund ssh 20250331
  153. if (getenv('YII_ENV') == 'production') {
  154. //小向花卉售后权限
  155. if ($this->mainId == 23390) {
  156. if (!in_array($this->adminId, [23960,77951,4])) {
  157. util::fail('你不能售后哦');
  158. }
  159. //小向花卉售后必须备注
  160. $remark = $post['remark'] ?? '';
  161. if (empty($remark)) {
  162. util::fail('请填写备注007');
  163. }
  164. }
  165. //国恋只有指定人有退款权限
  166. if ($this->mainId == 7704) {
  167. if (in_array($this->shopAdminId, [133727, 133545]) == false) {
  168. util::fail('无法操作。。');
  169. }
  170. }
  171. //小齐出车指定人可以售后
  172. if ($this->mainId == 42680) {
  173. if (!in_array($this->adminId, [40144])) {
  174. util::fail('你不能售后哦。。');
  175. }
  176. }
  177. }
  178. $get = Yii::$app->request->get();
  179. $id = $get['id'] ?? 0;
  180. $version = $get['version'] ?? 0;
  181. $confirm = $get['confirm'] ?? 0;
  182. $refund = RefundOrderClass::getById($id, true);
  183. RefundOrderClass::valid($refund, $this->mainId);
  184. $relateOrderSn = $refund->relateOrderSn ?? '';
  185. if (empty($relateOrderSn)) {
  186. util::fail('没有订单信息');
  187. }
  188. $refundList = RefundOrderClass::getAllByCondition(['relateOrderSn' => $relateOrderSn], null, '*', null, true);
  189. $has = false;
  190. if (!empty($refundList)) {
  191. foreach ($refundList as $single) {
  192. if ($single->status == 1) {
  193. $has = true;
  194. }
  195. }
  196. }
  197. if ($has == true) {
  198. if ($version == 0) {
  199. util::fail('请先升级系统');
  200. }
  201. if ($confirm == 0) {
  202. util::success(['error' => 'notFirstApply']);
  203. }
  204. }
  205. $connection = Yii::$app->db;
  206. $transaction = $connection->beginTransaction();
  207. try {
  208. RefundOrderService::passRefund($refund);
  209. $transaction->commit();
  210. $staff = $this->shopAdmin;
  211. $staffId = $staff->id;
  212. $staffName = $staff->name ?? '';
  213. $refund->shopAdminId = $staffId;
  214. $refund->shopAdminName = $staffName;
  215. $refund->save();
  216. //审核结果通知
  217. $cgRefundId = $refund->cgRefundId ?? 0;
  218. $cgRefund = CgRefundClass::getById($cgRefundId, true);
  219. $cgShopId = $cgRefund->shopId ?? 0;
  220. $cgShop = ShopClass::getById($cgShopId, true);
  221. if (!empty($cgRefund) && !empty($cgShop)) {
  222. NoticeClass::afterSaleNotice($cgShop, $cgRefund);
  223. }
  224. util::complete('操作成功');
  225. } catch (\Exception $e) {
  226. $transaction->rollBack();
  227. Yii::info("操作失败原因:" . $e->getMessage());
  228. util::fail('操作失败');
  229. }
  230. }
  231. //驳回 ssh 20230813
  232. public function actionReject()
  233. {
  234. $shopAdmin = $this->shopAdmin;
  235. if (isset($shopAdmin->super) == false || $shopAdmin->super != 1) {
  236. util::fail('无法操作');
  237. }
  238. //多处要同步修改ghs_refund ssh 20250331
  239. if (getenv('YII_ENV') == 'production') {
  240. //小向花卉售后权限
  241. if ($this->mainId == 23390) {
  242. if (!in_array($this->adminId, [23960,77951,4])) {
  243. util::fail('你不能售后哦。。');
  244. }
  245. //小向花卉售后必须备注
  246. $remark = $post['remark'] ?? '';
  247. if (empty($remark)) {
  248. util::fail('请填写备注007');
  249. }
  250. }
  251. //国恋只有指定人有退款权限
  252. if ($this->mainId == 7704) {
  253. if (in_array($this->shopAdminId, [133727, 133545]) == false) {
  254. util::fail('无法操作。。');
  255. }
  256. }
  257. //小齐出车指定人可以售后
  258. if ($this->mainId == 42680) {
  259. if (!in_array($this->adminId, [40144])) {
  260. util::fail('你不能售后哦。。。');
  261. }
  262. }
  263. }
  264. $post = Yii::$app->request->post();
  265. $id = $post['id'] ?? 0;
  266. $rejectReason = $post['rejectReason'] ?? '';
  267. $refund = RefundOrderClass::getById($id, true);
  268. RefundOrderClass::valid($refund, $this->mainId);
  269. $connection = Yii::$app->db;
  270. $transaction = $connection->beginTransaction();
  271. try {
  272. RefundOrderClass::rejectRefund($refund, $rejectReason);
  273. $transaction->commit();
  274. $staff = $this->shopAdmin;
  275. $staffId = $staff->id;
  276. $staffName = $staff->name ?? '';
  277. $refund->shopAdminId = $staffId;
  278. $refund->shopAdminName = $staffName;
  279. $refund->save();
  280. //审核结果通知
  281. $cgRefundId = $refund->cgRefundId ?? 0;
  282. $cgRefund = CgRefundClass::getById($cgRefundId, true);
  283. $cgShopId = $cgRefund->shopId ?? 0;
  284. $cgShop = ShopClass::getById($cgShopId, true);
  285. if (!empty($cgRefund) && !empty($cgShop)) {
  286. NoticeClass::afterSaleNotice($cgShop, $cgRefund);
  287. }
  288. util::complete('操作成功');
  289. } catch (\Exception $e) {
  290. $transaction->rollBack();
  291. Yii::info("操作失败原因:" . $e->getMessage());
  292. util::fail('操作失败');
  293. }
  294. }
  295. //售后之后减少库存 ssh 20250912
  296. public function actionReduceStock()
  297. {
  298. $shopAdmin = $this->shopAdmin;
  299. if (!isset($shopAdmin->super) || $shopAdmin->super != 1) {
  300. util::fail('管理员才能报损');
  301. }
  302. $post = Yii::$app->request->post();
  303. $refundItemId = $post['refundItemId'] ?? 0;
  304. $refundItem = RefundOrderItemClass::getById($refundItemId, true);
  305. if (empty($refundItem)) {
  306. util::fail('没有找到退货信息');
  307. }
  308. if ($refundItem->mainId != $this->mainId) {
  309. util::fail('不是您的退款信息');
  310. }
  311. $reduceProductId = $refundItem->productId ?? 0;
  312. $reduceNum = $post['reduceNum'] ?? 0;
  313. $productInfo = ProductClass::getById($reduceProductId, true);
  314. if (empty($productInfo)) {
  315. util::fail('没有找到花材');
  316. }
  317. if ($productInfo->mainId != $this->mainId) {
  318. util::fail('不是你的花材');
  319. }
  320. $unitType = $refundItem->xhUnitType ?? 0;
  321. if ($unitType == 1) {
  322. util::fail('小单位,无法减库存');
  323. }
  324. $refundNum = $refundItem->xhNum ?? 0;
  325. $hasReduceNum = $refundItem->xhReduceNum ?? 0;
  326. $remainNum = bcsub($refundNum, $hasReduceNum);
  327. if ($reduceNum > $remainNum) {
  328. util::fail('剩余可减数量 ' . $remainNum);
  329. }
  330. $stock = $productInfo->stock ?? 0;
  331. if ($reduceNum > $stock) {
  332. util::fail('库存不足了');
  333. }
  334. $orderSn = $refundItem->orderSn ?? '';
  335. $bigNum = bcsub($stock, $reduceNum);
  336. $refundItem->xhReduceNum = bcadd($refundItem->xhReduceNum, $reduceNum);
  337. $refundItem->save();
  338. $shop = $this->shop;
  339. $sjId = $shop->sjId ?? 0;
  340. $shopId = $shop->id ?? 0;
  341. $mainId = $shop->mainId ?? 0;
  342. $adminId = $this->adminId;
  343. $staff = $this->shopAdmin;
  344. $staffName = $staff->name ?? '';
  345. $params = [
  346. 'pdType' => '',
  347. 'itemInfo' => [['productId' => $reduceProductId, 'bigNum' => $bigNum, 'smallNum' => '']],
  348. 'remark' => '售后' . $orderSn . '直接减少库存',
  349. 'sjId' => $sjId,
  350. 'shopId' => $shopId,
  351. 'adminId' => $adminId,
  352. 'mainId' => $mainId,
  353. 'staffName' => $staffName,
  354. ];
  355. CheckOrderClass::opOrder($params);
  356. util::complete('操作成功');
  357. }
  358. //退款之后报损 ssh 20230409
  359. public function actionRefundWaste()
  360. {
  361. $shopAdmin = $this->shopAdmin;
  362. if (!isset($shopAdmin->super) || $shopAdmin->super != 1) {
  363. util::fail('管理员才能报损');
  364. }
  365. $post = Yii::$app->request->post();
  366. $refundItemId = $post['refundItemId'] ?? 0;
  367. $refundItem = RefundOrderItemClass::getById($refundItemId, true);
  368. if (empty($refundItem)) {
  369. util::fail('没有找到退货信息');
  370. }
  371. if ($refundItem->mainId != $this->mainId) {
  372. util::fail('不是您的退款信息');
  373. }
  374. $unitType = $refundItem->xhUnitType ?? 0;
  375. if ($unitType == 1) {
  376. util::fail('小单位,无法报损');
  377. }
  378. $wasteProductId = $refundItem->productId ?? 0;
  379. $wasteNum = $post['wasteNum'] ?? 0;
  380. unset($post['refundItemId']);
  381. unset($post['wasteNum']);
  382. unset($post['wasteProductId']);
  383. $productInfo = ProductClass::getById($wasteProductId, true);
  384. if (empty($productInfo)) {
  385. util::fail('没有找到花材');
  386. }
  387. $ptItemId = $productInfo->itemId ?? 0;
  388. $ratio = $productInfo->ratio ?? 20;
  389. $refundNum = $refundItem->xhNum ?? 0;
  390. $hasWasteNum = $refundItem->xhWasteNum ?? 0;
  391. $remainNum = bcsub($refundNum, $hasWasteNum);
  392. if ($wasteNum > $remainNum) {
  393. util::fail('剩余可报损数量 ' . $remainNum);
  394. }
  395. $productList = [['productId' => $wasteProductId, 'bigNum' => $wasteNum, 'smallNum' => 0, 'classId' => 0, 'itemId' => $ptItemId, 'ratio' => $ratio]];
  396. $post['shopId'] = $this->shopId;
  397. $post['sjId'] = $this->sjId;
  398. $post['mainId'] = $this->mainId;
  399. $post['shopAdminId'] = $this->shopAdminId;
  400. $adminName = $shopAdmin['name'] ?? '';
  401. $post['shopAdminName'] = $adminName;
  402. //属于售后报损
  403. $post['saleType'] = 1;
  404. $connection = Yii::$app->db;
  405. $transaction = $connection->beginTransaction();
  406. try {
  407. $refundItem->xhWasteNum = bcadd($refundItem->xhWasteNum, $wasteNum);
  408. $refundItem->save();
  409. $post['product'] = $productList;
  410. $return = StockWastageOrderClass::addOrder($post);
  411. $transaction->commit();
  412. util::success($return);
  413. } catch (\Exception $e) {
  414. $transaction->rollBack();
  415. Yii::info("报损失败原因:" . $e->getMessage());
  416. util::fail('报损失败');
  417. }
  418. }
  419. //列表
  420. public function actionList()
  421. {
  422. $get = Yii::$app->request->get();
  423. $where = [];
  424. $where['mainId'] = $this->mainId;
  425. $orderSn = $get['orderSn'] ?? '';
  426. if (!empty($orderSn)) {
  427. $where['relateOrderSn'] = $orderSn;
  428. }
  429. // 可选:只查无关联销售单
  430. $freeOnly = intval($get['freeOnly'] ?? 0);
  431. if ($freeOnly === 1) {
  432. $where['relateOrderSn'] = '';
  433. }
  434. // sameDay:-1全部 1当天售后 0隔天售后
  435. $sameDay = isset($get['sameDay']) ? intval($get['sameDay']) : -1;
  436. if ($sameDay === 0 || $sameDay === 1) {
  437. $where['sameDay'] = $sameDay;
  438. }
  439. $searchTime = $get['searchTime'] ?? '';
  440. if (!empty($searchTime)) {
  441. $startTime = $get['startTime'] ?? '';
  442. $endTime = $get['endTime'] ?? '';
  443. $period = dateUtil::formatTime($searchTime, $startTime, $endTime);
  444. $where['orderTime'] = ['between', [$period['startTime'], $period['endTime']]];
  445. }
  446. $refundSearchTime = $get['refundSearchTime'] ?? '';
  447. // 工作台退款记录:未传时间时默认近30天
  448. $useDefaultLast30 = intval($get['useDefaultLast30'] ?? 0);
  449. if ($useDefaultLast30 === 1 && empty($refundSearchTime) && empty($searchTime)) {
  450. $refundSearchTime = 'last30Days';
  451. }
  452. if (!empty($refundSearchTime)) {
  453. $startTime = $get['refundStartTime'] ?? ($get['startTime'] ?? '');
  454. $endTime = $get['refundEndTime'] ?? ($get['endTime'] ?? '');
  455. $period = dateUtil::formatTime($refundSearchTime, $startTime, $endTime);
  456. $where['addTime'] = ['between', [$period['startTime'], $period['endTime']]];
  457. }
  458. $customId = $get['customId'] ?? '';
  459. if (!empty($customId)) {
  460. $where['customId'] = $customId;
  461. }
  462. $shopAdminId = $get['shopAdminId'] ?? 0;
  463. if (!empty($shopAdminId)) {
  464. $where['shopAdminId'] = $shopAdminId;
  465. }
  466. $status = $get['status'] ?? -1;
  467. if ($status > -1) {
  468. $where['status'] = $status;
  469. }
  470. $export = $get['export'] ?? 0;
  471. if ($export == 1) {
  472. if (isset($where['orderTime']) == false && isset($where['addTime']) == false) {
  473. util::fail('请选时间');
  474. }
  475. ini_set('memory_limit', '2045M');
  476. set_time_limit(0);
  477. if (isset($where['orderTime'])) {
  478. $start = $where['orderTime'][1][0];
  479. $end = $where['orderTime'][1][1];
  480. $monthTime = bcmul(31, 86400);
  481. $startArea = strtotime($start);
  482. $endArea = strtotime($end);
  483. $diff = bcsub($endArea, $startArea);
  484. if ($diff > $monthTime) {
  485. util::fail('最长可导出一个月');
  486. }
  487. }
  488. if (isset($where['addTime'])) {
  489. $start = $where['addTime'][1][0];
  490. $end = $where['addTime'][1][1];
  491. $monthTime = bcmul(31, 86400);
  492. $startArea = strtotime($start);
  493. $endArea = strtotime($end);
  494. $diff = bcsub($endArea, $startArea);
  495. if ($diff > $monthTime) {
  496. util::fail('最长可导出一个月');
  497. }
  498. }
  499. }
  500. $respond = RefundOrderClass::getOrderList($where);
  501. if ($export == 1) {
  502. RefundOrderClass::exportRefundData($respond, $this->mainId);
  503. }
  504. util::success($respond);
  505. }
  506. //主要根据花材找退款记录 ssh 20240229
  507. public function actionGetListByItem()
  508. {
  509. $get = Yii::$app->request->get();
  510. $where = [];
  511. $where['mainId'] = $this->mainId;
  512. $status = $get['status'] ?? -1;
  513. $cause = $get['cause'] ?? -1;
  514. if ($status > -1) {
  515. $where['status'] = $status;
  516. }
  517. $string = $get['ids'];
  518. $ids = json_decode($string, true);
  519. if (!empty($ids)) {
  520. $productIds = [];
  521. $itemList = ProductClass::getAllByCondition(['mainId' => $this->mainId, 'classId' => ['in', $ids]], null, 'id', 'id');
  522. if (!empty($itemList)) {
  523. $productIds = array_keys($itemList);
  524. }
  525. if (empty($productIds)) {
  526. util::success(['list' => [], 'moreData' => 0, 'totalAmount' => 0, 'totalNum' => 0, 'totalPage' => 1]);
  527. }
  528. $where['productId'] = ['in', $productIds];
  529. }
  530. if ($cause > -1) {
  531. $where['cause'] = $cause;
  532. }
  533. $searchTime = isset($get['searchTime']) && !empty($get['searchTime']) ? $get['searchTime'] : 'today';
  534. $startTime = $get['startTime'] ?? '';
  535. $endTime = $get['endTime'] ?? '';
  536. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  537. $start = $period['startTime'];
  538. $end = $period['endTime'];
  539. $currentStartDate = date('Y-m-d', strtotime($start));
  540. $currentEndDate = date('Y-m-d', strtotime($end));
  541. $currentStartTime = $currentStartDate . ' 00:00:00';
  542. $currentEndTime = $currentEndDate . ' 23:59:59';
  543. $where['addTime'] = ['between', [$currentStartTime, $currentEndTime]];
  544. $list = RefundOrderItemClass::getRefundItemList($where);
  545. util::success($list);
  546. }
  547. public function actionDetail()
  548. {
  549. $id = Yii::$app->request->get('id', 0);
  550. $refund = RefundOrderClass::getById($id);
  551. if (empty($refund)) {
  552. util::fail('没有找到退款信息');
  553. }
  554. if (isset($refund['mainId']) == false || $refund['mainId'] != $this->mainId) {
  555. util::fail('没有权限');
  556. }
  557. $imgString = $refund['imgList'] ?? '';
  558. $relateOrderSn = $refund['relateOrderSn'] ?? '';
  559. // 无原单退款:不强制关联销售单
  560. $order = null;
  561. if ($relateOrderSn !== '' && $relateOrderSn !== null) {
  562. $order = OrderClass::getByCondition(['orderSn' => $relateOrderSn], true);
  563. }
  564. if (!empty($order)) {
  565. $refund['relateOrderId'] = $order->id;
  566. //补充原单信息,供前端判断该售后是否要走"转冲销单"(非当天单/欠款已结清),
  567. //以及转冲销单弹框里只读展示原单支付渠道。ssh 冲销单功能
  568. $refund['orderInfo'] = [
  569. 'id' => $order->id,
  570. 'payTime' => $order->payTime,
  571. 'debtPrice' => $order->debtPrice,
  572. 'remainDebtPrice' => $order->remainDebtPrice,
  573. 'actPrice' => $order->actPrice,
  574. 'forwardPrice' => $order->forwardPrice ?? 0,
  575. 'payWay' => $order->payWay,
  576. ];
  577. $refund['isFreeRefund'] = 0;
  578. } else {
  579. $refund['relateOrderId'] = 0;
  580. $refund['orderInfo'] = null;
  581. $refund['isFreeRefund'] = 1;
  582. }
  583. if (!empty($imgString)) {
  584. $imgArr = json_decode($imgString, true);
  585. $smallImgList = [];
  586. $bigImgList = [];
  587. if (!empty($imgArr)) {
  588. foreach ($imgArr as $image) {
  589. $smallImg = imgUtil::groupImg($image) . "?x-oss-process=image/resize,m_fill,h_130,w_130";
  590. $bigImg = imgUtil::groupImg($image) . "?x-oss-process=image/resize,m_fill,h_700,w_700";
  591. $smallImgList[] = $smallImg;
  592. $bigImgList[] = $bigImg;
  593. }
  594. }
  595. $refund['imgList'] = $imgArr;
  596. $refund['smallImgList'] = $smallImgList;
  597. $refund['bigImgList'] = $bigImgList;
  598. }
  599. $orderSn = $refund['orderSn'] ?? '';
  600. $itemList = RefundOrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*');
  601. $staff = $this->shopAdmin;
  602. $staffId = $this->shopAdminId;
  603. $notify = NotifyClass::getByCondition(['staffId' => $staffId, 'type' => 0, 'targetId' => $id], true);
  604. if (!empty($notify)) {
  605. if ($notify->read == 0) {
  606. $notify->read = 1;
  607. $notify->save();
  608. $notifyNum = $staff->notifyNum;
  609. if ($notifyNum > 0) {
  610. $notifyNum--;
  611. $staff->notifyNum = $notifyNum;
  612. $staff->save();
  613. }
  614. }
  615. }
  616. $itemRefundOption = dict::getDict('itemRefundOption');
  617. util::success(['info' => $refund, 'itemList' => $itemList, 'itemRefundOption' => $itemRefundOption]);
  618. }
  619. //退款 lqh 2021.6.25
  620. public function actionCreateOrder()
  621. {
  622. $post = Yii::$app->request->post();
  623. $shopAdmin = $this->shopAdmin;
  624. if (isset($shopAdmin['super']) == false || $shopAdmin['super'] != 1) {
  625. util::fail('超管才能操作退款');
  626. }
  627. //多处要同步修改ghs_refund ssh 20250331
  628. if (getenv('YII_ENV') == 'production') {
  629. //小向花卉售后权限
  630. if ($this->mainId == 23390) {
  631. if (!in_array($this->adminId, [23960,77951,4])) {
  632. util::fail('你不能售后哈。。');
  633. }
  634. //小向花卉售后必须备注
  635. $remark = $post['remark'] ?? '';
  636. if (empty($remark)) {
  637. util::fail('请填写备注007');
  638. }
  639. }
  640. //国恋只有指定人有退款权限
  641. if ($this->mainId == 7704) {
  642. if (in_array($this->shopAdminId, [133727, 133545]) == false) {
  643. util::fail('无法操作。。');
  644. }
  645. }
  646. //小齐出车指定人可以售后
  647. if ($this->mainId == 42680) {
  648. if (!in_array($this->adminId, [40144])) {
  649. util::fail('你不能售后哦。。');
  650. }
  651. }
  652. }
  653. $id = isset($post['id']) ? $post['id'] : 0;
  654. $refundType = $post['refundType'] ?? 1;
  655. //避免网络延迟,暂时重复申请
  656. $cacheKey = 'ghs_order_refund_' . $id;
  657. $has = Yii::$app->redis->executeCommand('GET', [$cacheKey]);
  658. if (!empty($has)) {
  659. util::fail('请5秒之后再提交');
  660. }
  661. Yii::$app->redis->executeCommand('SETEX', [$cacheKey, 5, 'has']);
  662. try {
  663. $respond = util::runWithDbConcurrencyRetry(function () use ($post, $id, $refundType) {
  664. $connection = Yii::$app->db;
  665. $transaction = $connection->beginTransaction();
  666. try {
  667. if ($refundType == RefundOrderClass::REFUND_TYPE_MONEY_GOOD) {
  668. //花材列表结构
  669. // [{productId:0,num:1,unitType:0,unitPrice:12,unitName:'扎'}]
  670. $productJson = $post['product'] ?? '';
  671. if (empty($productJson)) {
  672. util::fail('请选择花材');
  673. }
  674. $productList = json_decode($productJson, true);
  675. if (!is_array($productList)) {
  676. util::fail('请选择花材哦');
  677. }
  678. $post['product'] = $productList;
  679. } else {
  680. //仅退款花材直接设置为空
  681. $post['product'] = [];
  682. }
  683. $post['price'] = $post['price'] ?? 0;
  684. if ($post['price'] <= 0) {
  685. util::fail("退款金额不能小于0");
  686. }
  687. $post['shopId'] = $this->shopId;
  688. $post['sjId'] = $this->sjId;
  689. $post['shopAdminId'] = $this->shopAdminId;
  690. $post['mainId'] = $this->mainId;
  691. $shopAdmin = $this->shopAdmin;
  692. $adminName = $shopAdmin['name'] ?? '';
  693. $post['shopAdminName'] = $adminName;
  694. $respond = OrderService::refund($id, $post);
  695. $refundId = $respond->id;
  696. $refundInfo = RefundOrderClass::getById($refundId, true);
  697. RefundOrderService::passRefund($refundInfo);
  698. $transaction->commit();
  699. // 隔天售后:返回海报/结果页所需字段
  700. $refundInfo = RefundOrderClass::getById($refundId, true);
  701. $order = OrderClass::getById($id, true);
  702. $custom = null;
  703. if (!empty($order)) {
  704. $custom = \bizGhs\custom\classes\CustomClass::getById(intval($order->customId ?? 0), true);
  705. }
  706. return [
  707. 'id' => $refundId,
  708. 'orderSn' => $refundInfo->orderSn ?? '',
  709. 'sameDay' => intval($refundInfo->sameDay ?? 1),
  710. 'fundType' => intval($refundInfo->fundType ?? 0),
  711. 'onlinePay' => intval($refundInfo->onlinePay ?? 0),
  712. 'payWay' => intval($refundInfo->payWay ?? 0),
  713. 'refundPrice' => $refundInfo->refundPrice ?? 0,
  714. 'customId' => intval($order->customId ?? 0),
  715. 'customName' => $custom->name ?? ($order->customName ?? ''),
  716. 'customBalance' => bcadd((string)($custom->balance ?? '0'), '0', 2),
  717. 'orderId' => intval($id),
  718. 'nextDayTkPrice' => $order->nextDayTkPrice ?? '0.00',
  719. ];
  720. } catch (\Exception $exception) {
  721. if ($transaction->isActive) {
  722. $transaction->rollBack();
  723. }
  724. throw $exception;
  725. }
  726. });
  727. util::success($respond);
  728. } catch (\Exception $exception) {
  729. Yii::info("退款出错了,报错信息:" . $exception->getMessage());
  730. if (util::isDbConcurrencyException($exception)) {
  731. util::fail('系统繁忙中,请稍后再试');
  732. } else {
  733. // 透出业务失败原因,便于隔天售后排错
  734. util::fail($exception->getMessage() ?: '操作失败');
  735. }
  736. }
  737. }
  738. /**
  739. * 无原单退款(工作台「退款」)
  740. * POST: customId, price, product(json), fundType, refundType, remark
  741. * 立即写售后单 sameDay=0 并通过;无关联销售单/采购单。
  742. */
  743. public function actionCreateFreeRefund()
  744. {
  745. $post = Yii::$app->request->post();
  746. $shopAdmin = $this->shopAdmin;
  747. if (isset($shopAdmin['super']) == false || $shopAdmin['super'] != 1) {
  748. util::fail('超管才能操作退款');
  749. }
  750. // 与 create-order 生产环境售后权限保持一致
  751. if (getenv('YII_ENV') == 'production') {
  752. if ($this->mainId == 23390) {
  753. if (!in_array($this->adminId, [23960, 77951, 4])) {
  754. util::fail('你不能售后哈。。');
  755. }
  756. $remark = $post['remark'] ?? '';
  757. if (empty($remark)) {
  758. util::fail('请填写备注007');
  759. }
  760. }
  761. if ($this->mainId == 7704) {
  762. if (in_array($this->shopAdminId, [133727, 133545]) == false) {
  763. util::fail('无法操作。。');
  764. }
  765. }
  766. if ($this->mainId == 42680) {
  767. if (!in_array($this->adminId, [40144])) {
  768. util::fail('你不能售后哦。。');
  769. }
  770. }
  771. }
  772. $customId = intval($post['customId'] ?? 0);
  773. $cacheKey = 'ghs_free_refund_' . $this->mainId . '_' . $customId;
  774. $has = Yii::$app->redis->executeCommand('GET', [$cacheKey]);
  775. if (!empty($has)) {
  776. util::fail('请5秒之后再提交');
  777. }
  778. Yii::$app->redis->executeCommand('SETEX', [$cacheKey, 5, 'has']);
  779. try {
  780. $respond = util::runWithDbConcurrencyRetry(function () use ($post) {
  781. $connection = Yii::$app->db;
  782. $transaction = $connection->beginTransaction();
  783. try {
  784. // returnWay 优先:1库存退回要花材;0库存不退可只记金额
  785. $returnWay = intval($post['returnWay'] ?? -1);
  786. if ($returnWay === 1) {
  787. $refundType = RefundOrderClass::REFUND_TYPE_MONEY_GOOD;
  788. } elseif ($returnWay === 0) {
  789. $refundType = RefundOrderClass::REFUND_TYPE_MONEY;
  790. } else {
  791. $refundType = intval($post['refundType'] ?? RefundOrderClass::REFUND_TYPE_MONEY_GOOD);
  792. }
  793. $post['refundType'] = $refundType;
  794. if ($refundType == RefundOrderClass::REFUND_TYPE_MONEY_GOOD) {
  795. $productJson = $post['product'] ?? '';
  796. if (empty($productJson)) {
  797. util::fail('请选择花材');
  798. }
  799. $productList = is_array($productJson) ? $productJson : json_decode($productJson, true);
  800. if (!is_array($productList) || empty($productList)) {
  801. util::fail('请选择花材哦');
  802. }
  803. $post['product'] = $productList;
  804. } else {
  805. // 库存不退:金额已够,明细可选保留供对账
  806. $productJson = $post['product'] ?? '';
  807. if (!empty($productJson)) {
  808. $productList = is_array($productJson) ? $productJson : json_decode($productJson, true);
  809. $post['product'] = is_array($productList) ? $productList : [];
  810. } else {
  811. $post['product'] = [];
  812. }
  813. }
  814. $post['price'] = $post['price'] ?? 0;
  815. if ($post['price'] <= 0) {
  816. util::fail('退款金额不能小于0');
  817. }
  818. $post['shopId'] = $this->shopId;
  819. $post['sjId'] = $this->sjId;
  820. $post['shopAdminId'] = $this->shopAdminId;
  821. $post['mainId'] = $this->mainId;
  822. $shopAdmin = $this->shopAdmin;
  823. $post['shopAdminName'] = $shopAdmin['name'] ?? '';
  824. $result = RefundOrderService::createFreeRefund($post);
  825. $transaction->commit();
  826. return $result;
  827. } catch (\Exception $exception) {
  828. if ($transaction->isActive) {
  829. $transaction->rollBack();
  830. }
  831. throw $exception;
  832. }
  833. });
  834. util::success($respond);
  835. } catch (\Exception $exception) {
  836. Yii::info('无原单退款出错:' . $exception->getMessage());
  837. if (util::isDbConcurrencyException($exception)) {
  838. util::fail('系统繁忙中,请稍后再试');
  839. }
  840. util::fail($exception->getMessage() ?: '操作失败');
  841. }
  842. }
  843. //修改售后原因 ssh 20250623
  844. public function actionChangeRefundOption()
  845. {
  846. $post = Yii::$app->request->post();
  847. $id = $post['id'] ?? 0;
  848. $sonId = $post['sonId'] ?? 0;
  849. $optionId = $post['optionId'] ?? 0;
  850. $refund = RefundOrderClass::getById($id, true);
  851. if (empty($refund)) {
  852. util::fail('没有找到退款信息');
  853. }
  854. if ($refund->mainId != $this->mainId) {
  855. util::fail('没有权限');
  856. }
  857. $orderSn = $refund->orderSn;
  858. $son = RefundOrderItemClass::getById($sonId, true);
  859. if (empty($son)) {
  860. util::fail('没有找到花材信息');
  861. }
  862. if ($son->orderSn != $orderSn) {
  863. util::fail('退款信息有问题');
  864. }
  865. $map = dict::getDict('itemRefundOption');
  866. $info = $map[$optionId] ?? [];
  867. $name = $info['name'] ?? '未选';
  868. $son->refundOptionId = $optionId;
  869. $son->refundOptionName = $name;
  870. $son->save();
  871. util::complete('修改成功');
  872. }
  873. }