CashierOrderRefund.php 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040
  1. <?php
  2. /**
  3. * Niushop商城系统 - 团队十年电商经验汇集巨献!
  4. * =========================================================
  5. * Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
  6. * ----------------------------------------------
  7. * 官方网址: https://www.niushop.com
  8. * =========================================================
  9. */
  10. namespace addon\store\model\cashier;
  11. use addon\memberrecharge\model\RechargeOrder;
  12. use addon\store\model\member\MemberOnceCard;
  13. use addon\store\model\store\Store;
  14. use app\model\BaseModel;
  15. use app\model\member\Member;
  16. use app\model\member\MemberAccount;
  17. use app\model\member\MemberLevelOrder;
  18. use app\model\order\OrderCommon;
  19. use app\model\order\OrderCreateTool;
  20. use app\model\order\OrderGoods;
  21. use app\model\site\Site;
  22. use app\model\system\Pay;
  23. use think\facade\Cache;
  24. use think\facade\Db;
  25. use think\facade\Queue;
  26. /**
  27. * 收银订单
  28. *
  29. * @author Administrator
  30. *
  31. */
  32. class CashierOrderRefund extends BaseModel
  33. {
  34. /*********************************************************************************订单退款状态*****************************************************/
  35. // 卖家关闭退款
  36. const REFUND_CLOSE = 'refund_close';
  37. //已完成
  38. const REFUND_COMPLETE = 'refund_complete';
  39. public $order_refund_status = [
  40. self::REFUND_COMPLETE => [
  41. 'status' => self::REFUND_COMPLETE,
  42. 'name' => '退款成功',
  43. 'action' => [
  44. ],
  45. 'member_action' => [
  46. ],
  47. 'remind' => [
  48. '如通过“微信支付”付款订单,退款3~7个工作日到账。'
  49. ],
  50. 'member_remind' => [
  51. ]
  52. ],
  53. self::REFUND_CLOSE => [
  54. 'status' => self::REFUND_CLOSE,
  55. 'name' => '退款关闭',
  56. 'action' => [
  57. ],
  58. 'member_action' => [
  59. ],
  60. 'remind' => [
  61. ],
  62. 'member_remind' => [
  63. // '“买家主动/客服/系统”撤销申请,退款关闭',
  64. '如果后续仍有问题,你可再次发起售后申请。'
  65. ]
  66. ],
  67. ];
  68. /**
  69. * 退款转账方式
  70. * @param int $online_money
  71. * @return array
  72. */
  73. public function getRefundTransferType($online_money = -1){
  74. $list = array(
  75. 'cash' =>['name' => '现金退款','desc' => '与客户协商一致, 以现金的形式退款给客户'],
  76. 'offline' => ['name' => '线下退款','desc' => '与客户协商一致, 在线下以支付宝或微信等形式退款给客户'],
  77. );
  78. if($online_money != 0){
  79. $list['back'] = ['name' => '原路退款','desc' => '与客户协商一致,原路退款给客户'];
  80. }
  81. return $list;
  82. }
  83. /**
  84. * 退款类型
  85. * @return array
  86. */
  87. public function getRefundTradeType(){
  88. $list = array(
  89. 'order' => '订单退款',
  90. 'balance' => '储值退款',
  91. );
  92. return $list;
  93. }
  94. /**
  95. * 数据转化
  96. * @param $item
  97. * @return mixed
  98. */
  99. public function tran($item){
  100. $refund_transfer_type = $item['refund_transfer_type'] ?? '';
  101. if(!empty($refund_transfer_type)){
  102. $refund_transfer_type_list = $this->getRefundTransferType();
  103. $item['refund_transfer_type_name'] = $refund_transfer_type_list[$refund_transfer_type]['name'] ?? '';
  104. }
  105. $refund_status = $item['refund_status'] ?? '';
  106. if(!empty($refund_status)){
  107. $refund_status_list = $this->order_refund_status;
  108. $item['refund_status_name'] = $refund_status_list[$refund_status]['name'] ?? '';
  109. }
  110. $refund_trade_type = $item['refund_trade_type'] ?? '';
  111. if(!empty($refund_trade_type)){
  112. $refund_trade_type_list = $this->getRefundTradeType();
  113. $item['refund_trade_type_name'] = $refund_trade_type_list[$refund_trade_type] ?? '';
  114. }
  115. return $item;
  116. }
  117. public function refund($params){
  118. $refund_array = $params['refund_array'] ?? [];
  119. $site_id = $params['site_id'] ?? 0;
  120. $member_id = $params['member_id'] ?? 0;
  121. $store_id = $params['store_id'] ?? 0;
  122. $item_array = [];
  123. $operator = $params['operator'] ?? [];
  124. $operator_id = $operator['uid'] ?? 0;
  125. $operator_name = $operator['username'] ?? '';
  126. $params['operator_id'] = $operator_id;
  127. $params['operator_name'] = $operator_name;
  128. foreach($refund_array as $k => $v){
  129. $item_params = $params;
  130. $item_params['order_id'] = $k;
  131. $item_params['order_goods_params'] = $v;
  132. $item_result = $this->orderRefund($item_params);
  133. if($item_result['code'] < 0){
  134. return $item_result;
  135. }
  136. }
  137. return $this->success();
  138. }
  139. public function orderRefund($params){
  140. $site_id = $params['site_id'] ?? 0;
  141. $member_id = $params['member_id'] ?? 0;
  142. $store_id = $params['store_id'] ?? 0;
  143. $order_id = $params['order_id'];
  144. $order_goods_params = $params['order_goods_params'];
  145. $refund_transfer_type = $params['refund_transfer_type'] ?? '';
  146. $item_params = array(
  147. 'order_id' => $order_id,
  148. 'order_goods_ids' => array_keys($order_goods_params),
  149. 'site_id' => $site_id,
  150. 'store_id' => $store_id,
  151. 'member_id' => $member_id,
  152. );
  153. $order_refund_result = $this->getRefundApplyOrderData($item_params);
  154. if($order_refund_result['code'] < 0){
  155. return $order_refund_result;
  156. }
  157. $order_refund_data = $order_refund_result['data'];
  158. $online_money = $order_refund_data['online_money'];
  159. $refund_transfer_type_list = $this->getRefundTransferType($online_money);
  160. if(empty($refund_transfer_type_list[$refund_transfer_type])){
  161. return $this->error([], '退款方式不支持!');
  162. }
  163. $item_order_goods_list = $order_refund_data['order_goods_list'];
  164. $pay_model = new Pay();
  165. $refund_no = $pay_model->createRefundNo();
  166. $refund_reason = $params['refund_reason'] ?? '';
  167. $refund_remark = $params['refund_remark'] ?? '';
  168. $insert_data = array(
  169. 'order_id' => $order_id,
  170. 'member_id' => $member_id,
  171. 'refund_no' => $refund_no,
  172. 'store_id' => $store_id,
  173. 'site_id' => $site_id,
  174. 'refund_point' => $order_refund_data['total_refund_point'],
  175. 'refund_point_money' => $order_refund_data['total_refund_point_money'],
  176. 'refund_balance_money' => $order_refund_data['total_refund_balance'],
  177. 'refund_balance' => $order_refund_data['total_refund_balance_money'],
  178. 'refund_money' => $order_refund_data['total_refund_money'],
  179. 'refund_reason' => $refund_reason,
  180. 'refund_remark' => $refund_remark,
  181. 'create_time' => time(),
  182. 'refund_status' => self::REFUND_COMPLETE,
  183. 'refund_transfer_type' => $refund_transfer_type,
  184. 'refund_trade_type' => 'order',
  185. 'operator_id' => $params['operator_id'] ?? 0,
  186. 'operator_name' => $params['operator_name'] ?? '',
  187. );
  188. $insert_data = $this->tran($insert_data);
  189. //实际退款
  190. $refund_id = model('store_cashier_order_refund')->add($insert_data);
  191. $total_refund_transfer_money = 0;
  192. foreach($item_order_goods_list as $order_goods_k => $order_goods_v){
  193. $item_order_goods_id = $order_goods_v['order_goods_id'];
  194. $temp_item = $order_goods_params[$item_order_goods_id];
  195. $item_order_goods_data = $order_goods_v;
  196. $item_order_goods_data['refund_id'] = $refund_id;
  197. $item_order_goods_data['item_order_goods_params'] = $temp_item;
  198. $item_order_goods_data['refund_transfer_type'] = $refund_transfer_type;
  199. $order_goods_result = $this->orderGoodsRefund($item_order_goods_data);
  200. if($order_goods_result['code'] < 0){
  201. return $order_goods_result;
  202. }
  203. $total_refund_transfer_money += $order_goods_result['data']['refund_transfer_money'];
  204. }
  205. $update_data = array(
  206. 'refund_pay_money' => $total_refund_transfer_money
  207. );
  208. model('store_cashier_order_refund')->update($update_data, [['refund_id', '=', $refund_id]]);
  209. $insert_data['refund_id'] = $refund_id;
  210. $insert_data['refund_id'] = $refund_id;
  211. $this->complete($insert_data);
  212. return $this->success();
  213. }
  214. public function orderGoodsRefund($params){
  215. $item_order_goods_params = $params['item_order_goods_params'];
  216. $item_refund_transfer_money = $item_order_goods_params['refund_transfer_money'] ?? 0;
  217. $item_refund_num = $item_order_goods_params['refund_num'] ?? $params['num'];
  218. $item_refund_money = $params['refund_money'] ?? 0;
  219. $item_refund_pay_money = $params['refund_pay_money'] ?? 0;
  220. $item_refund_point = $params['refund_point'] ?? 0;
  221. $item_refund_point_money = $params['refund_point_money'] ?? 0;
  222. $item_refund_balance = $params['refund_balance'] ?? 0;
  223. $item_refund_balance_money = $params['refund_balance_money'] ?? 0;
  224. $refund_id = $params['refund_id'];
  225. $store_id = $params['store_id'];
  226. $order_goods_id = $params['order_goods_id'];
  227. $refund_transfer_type = $params['refund_transfer_type'] ?? '';
  228. if($item_refund_transfer_money == 'total'){
  229. $item_refund_transfer_money = $item_refund_pay_money;
  230. }
  231. if($item_refund_transfer_money > $item_refund_pay_money){
  232. return $this->error([], '退款金额不能大于订单支付金额');
  233. }
  234. $pay_model = new Pay();
  235. $refund_transfer_no = $pay_model->createRefundNo();
  236. $insert_data = array(
  237. 'order_goods_id' => $params['order_goods_id'],
  238. 'order_id' => $params['order_id'],
  239. 'member_id' => $params['member_id'],
  240. 'refund_transfer_no' => $refund_transfer_no,
  241. 'site_id' => $params['site_id'],
  242. 'store_id' => $store_id,
  243. 'refund_num' => $item_refund_num,
  244. 'refund_pay_money' => $item_refund_pay_money,
  245. 'refund_point' => $item_refund_point,
  246. 'refund_point_money' => $item_refund_point_money,
  247. 'refund_balance_money' => $item_refund_balance_money,
  248. 'refund_balance' => $item_refund_balance,
  249. 'refund_money' => $item_refund_money,
  250. 'refund_id' => $refund_id,
  251. 'name' => $params['goods_name'],
  252. 'img' => $params['goods_image'],
  253. );
  254. //实际退款
  255. $refund_goods_id = model('store_cashier_order_goods_refund')->add($insert_data);
  256. $result = $this->refundAccount(['refund_goods_id' => $refund_goods_id, 'refund_transfer_type' => $refund_transfer_type]);
  257. $this->setOrderGoodsRefund(['order_goods_id' => $order_goods_id]);
  258. return $this->success(['refund_transfer_money' => $item_refund_transfer_money]);
  259. }
  260. /**
  261. * 设置订单项的维权状态
  262. * @param $params
  263. * @return mixed
  264. */
  265. public function setOrderGoodsRefund($params){
  266. $order_goods_id = $params['order_goods_id'];
  267. $condition = array(
  268. ['order_goods_id', '=', $order_goods_id]
  269. );
  270. $data = array(
  271. 'refund_status' => 'refund_complete',
  272. 'is_can_refund' => 0//这个订单项不可以再退了
  273. );
  274. model('store_cashier_order_goods')->update($data, $condition);
  275. return $this->success();
  276. }
  277. /**
  278. * 设置订单的维权状态
  279. * @param $params
  280. * @return mixed
  281. */
  282. public function setOrderRefund($params){
  283. $order_id = $params['order_id'];
  284. $condition = array(
  285. ['order_id', '=', $order_id]
  286. );
  287. $data = array(
  288. 'is_can_refund' => 0//这个订单项不可以再退了
  289. );
  290. model('store_cashier_order')->update($data, $condition);
  291. return $this->success();
  292. }
  293. /**
  294. * 交易退款
  295. * @param $params
  296. * @return array
  297. */
  298. public function refundAccount($params){
  299. $refund_goods_id = $params['refund_goods_id'];
  300. $refund_transfer_type = $params['refund_transfer_type'] ?? '';
  301. //退还积分、余额 ....
  302. $refund_condition = array(
  303. ['refund_goods_id', '=', $refund_goods_id]
  304. );
  305. $info = model('store_cashier_order_goods_refund')->getInfo($refund_condition);
  306. $info['refund_transfer_type'] = $refund_transfer_type;
  307. $order_goods_id = $info['order_goods_id'];
  308. $order_goods_condition = array(
  309. ['order_goods_id', '=', $order_goods_id]
  310. );
  311. $order_goods_info = model('store_cashier_order_goods')->getInfo($order_goods_condition);
  312. $info['order_goods_info'] = $order_goods_info;
  313. $order_id = $info['order_id'];
  314. $order_condition = array(
  315. ['order_id', '=', $order_id]
  316. );
  317. $order_info = model('store_cashier_order')->getInfo($order_condition);
  318. $info['order_info'] = $order_info;
  319. //退积分
  320. $point_result = $this->refundPoint($info);
  321. if ($point_result['code'] < 0) {
  322. return $point_result;
  323. }
  324. //退余额
  325. $balance_result = $this->refundBalance($info);
  326. if ($balance_result['code'] < 0) {
  327. return $balance_result;
  328. }
  329. //退真实支付金额
  330. $pay_result = $this->refundPayMoney($info);
  331. if ($pay_result['code'] < 0) {
  332. return $pay_result;
  333. }
  334. return $this->success();
  335. }
  336. /**
  337. * 退款真实金额
  338. * @param $params
  339. * @return array
  340. */
  341. public function refundPayMoney($params){
  342. $refund_pay_money = $params['refund_pay_money'];
  343. $refund_transfer_type = $params['refund_transfer_type'] ?? '';
  344. if($refund_pay_money > 0){
  345. if($refund_transfer_type == 'back'){
  346. $refund_transfer_no = $params['refund_transfer_no'];
  347. $order_info = $params['order_info'];
  348. $pay_money = $order_info['pay_money'];
  349. $out_trade_no = $order_info['out_trade_no'];
  350. //根据订单的支付方式来退款
  351. //尝试退真实金额,或开启退款步骤
  352. $pay_model = new Pay();
  353. $result = $pay_model->refund($refund_transfer_no, $refund_pay_money, $out_trade_no, '', $pay_money, $order_info[ 'site_id' ], 1, 'CashierOrderPayRefund');
  354. if($result['code'] < 0){
  355. return $result;
  356. }
  357. //改变退款转账状态
  358. $refund_data = array(
  359. 'refund_transfer_status' => 'transfer_ing'
  360. );
  361. $refund_condition = array(
  362. ['refund_transfer_no', '=', $refund_transfer_no]
  363. );
  364. model('store_cashier_order_goods_refund')->update($refund_data, $refund_condition);
  365. }
  366. }
  367. return $this->success();
  368. }
  369. /**
  370. * 退还积分
  371. * @param $params
  372. * @return array
  373. */
  374. public function refundPoint($params)
  375. {
  376. $member_account_model = new MemberAccount();
  377. $member_id = $params['member_id'];
  378. $site_id = $params['site_id'];
  379. $refund_point = $params['refund_point'] ?? 0;
  380. if ($refund_point > 0) {
  381. $from_type = 'refund';
  382. $relate_tag = '积分返还';
  383. $remark = '订单退款,退还积分:' . $refund_point;
  384. $account_title = '订单退款,退还积分:' . $refund_point;
  385. $result = $member_account_model->addMemberAccount($site_id, $member_id, 'point', $refund_point, $from_type, $relate_tag, $remark, $account_title);
  386. if ($result['code'] < 0) {
  387. return $result;
  388. }
  389. }
  390. return $this->success();
  391. }
  392. /**
  393. * 退还积分
  394. * @param $params
  395. * @return array
  396. */
  397. public function refundBalance($params)
  398. {
  399. $member_account_model = new MemberAccount();
  400. $member_id = $params['member_id'];
  401. $site_id = $params['site_id'];
  402. $refund_balance_money = $params['refund_balance_money'];//可退不可提现拥佣金
  403. $refund_balance = $params['refund_balance'];//可退可提现佣金
  404. if ($refund_balance_money > 0) {
  405. $from_type = 'refund';
  406. $relate_tag = '现金余额退还';
  407. $remark = '订单退款,退还现金余额:' . $refund_balance_money;
  408. $account_title = '订单退款,退还现金余额';
  409. $result = $member_account_model->addMemberAccount($site_id, $member_id, 'balance_money', $refund_balance_money, $from_type, $relate_tag, $remark, $account_title);
  410. if ($result['code'] < 0) {
  411. return $result;
  412. }
  413. }
  414. if ($refund_balance > 0) {
  415. $from_type = 'refund';
  416. $relate_tag = '储值余额退还';
  417. $remark = '订单退款,退还储值余额:' . $refund_balance;
  418. $account_title = '订单退款,退还储值余额';
  419. $result = $member_account_model->addMemberAccount($site_id, $member_id, 'balance', $refund_balance, $from_type, $relate_tag, $remark, $account_title);
  420. if ($result['code'] < 0) {
  421. return $result;
  422. }
  423. }
  424. return $this->success();
  425. }
  426. /**
  427. * 退款到账通知事件
  428. * @param $params
  429. */
  430. public function refundPayNotify($params){
  431. $refund_transfer_no = $params['refund_no'];
  432. $refund_condition = array(
  433. ['refund_transfer_no', '=', $refund_transfer_no]
  434. );
  435. $refund_info = model('order_refund')->getInfo($refund_condition);
  436. if(empty($refund_info))
  437. return $this->error();
  438. //改变退款转账状态
  439. $refund_data = array(
  440. 'refund_transfer_status' => 'transfer_complete'
  441. );
  442. $refund_condition = array(
  443. ['refund_transfer_no', '=', $refund_transfer_no]
  444. );
  445. model('store_cashier_order_goods_refund')->update($refund_data, $refund_condition);
  446. return $this->success();
  447. }
  448. public function getRefundApplyData($params){
  449. $item_array = $params['refund_array'] ?? [];
  450. $site_id = $params['site_id'] ?? 0;
  451. $member_id = $params['member_id'] ?? 0;
  452. $store_id = $params['store_id'] ?? 0;
  453. $order_goods_id_array = [];
  454. $refund_data = [];
  455. $refund_array = [];
  456. $total_refund_money = 0;
  457. $total_refund_pay_money = 0;
  458. $total_refund_point = 0;
  459. $total_refund_point_money = 0;
  460. $total_refund_balance = 0;
  461. $total_refund_balance_money = 0;
  462. $total_online_money = 0;
  463. foreach($item_array as $k => $v){
  464. $item_params = array(
  465. 'order_id' => $k,
  466. 'order_goods_ids' => $v,
  467. 'site_id' => $site_id,
  468. 'store_id' => $store_id,
  469. 'member_id' => $member_id,
  470. );
  471. $order_refund_result = $this->getRefundApplyOrderData($item_params);
  472. if($order_refund_result['code'] < 0){
  473. return $order_refund_result;
  474. }
  475. $order_refund = $order_refund_result['data'];
  476. $item_total_refund_money = $order_refund['total_refund_money'] ?? 0;
  477. $item_total_refund_pay_money = $order_refund['total_refund_pay_money'] ?? 0;
  478. $item_total_refund_point = $order_refund['total_refund_point'] ?? 0;
  479. $item_total_refund_point_money = $order_refund['total_refund_point_money'] ?? 0;
  480. $item_total_refund_balance = $order_refund['total_refund_balance'] ?? 0;
  481. $item_total_refund_balance_money = $order_refund['total_refund_balance_money'] ?? 0;
  482. $total_refund_money += $item_total_refund_money;
  483. $total_refund_pay_money += $item_total_refund_pay_money;
  484. $total_refund_point += $item_total_refund_point;
  485. $total_refund_point_money += $item_total_refund_point_money;
  486. $total_refund_balance += $item_total_refund_balance;
  487. $total_refund_balance_money += $item_total_refund_balance_money;
  488. $refund_array[] = $order_refund;
  489. $total_online_money += $order_refund['online_money'];
  490. }
  491. $refund_data['refund_list'] = $refund_array;
  492. $refund_data['total_refund_money'] = $total_refund_money;
  493. $refund_data['total_refund_pay_money'] = $total_refund_pay_money;
  494. $refund_data['total_refund_point'] = $total_refund_point;
  495. $refund_data['total_refund_point_money'] = $total_refund_point_money;
  496. $refund_data['total_refund_balance'] = $total_refund_balance;
  497. $refund_data['total_refund_balance_money'] = $total_refund_balance_money;
  498. $refund_data['total_online_money'] = $total_online_money;
  499. $refund_transfer_type = $this->getRefundTransferType($total_online_money);
  500. $refund_data['refund_transfer_type'] = $refund_transfer_type;
  501. return $this->success($refund_data);
  502. }
  503. public function getRefundApplyOrderData($params){
  504. $order_id = $params['order_id'] ?? 0;
  505. $site_id = $params['site_id'] ?? 0;
  506. $member_id = $params['member_id'] ?? 0;
  507. $store_id = $params['store_id'] ?? 0;
  508. $order_condition = array(
  509. ['order_id', '=', $order_id]
  510. );
  511. if($site_id > 0){
  512. $order_condition[] = ['site_id', '=', $site_id];
  513. }
  514. if($member_id > 0){
  515. $order_condition[] = ['member_id', '=', $member_id];
  516. }
  517. if($store_id > 0){
  518. $order_condition[] = ['store_id', '=', $store_id];
  519. }
  520. $order_info = model('store_cashier_order')->getInfo($order_condition);
  521. if(empty($order_info))
  522. return $this->error();
  523. //订单整体项
  524. //查询正处于退款中和退款成功的退款记录,计算已经退的钱以及退的余额 积分 红包
  525. $refund_temp_condition = array(
  526. ['order_id', '=', $order_id],
  527. ['refund_status', '<>', self::REFUND_CLOSE],
  528. );
  529. $refund_temp_list = model('store_cashier_order_refund')->getList($refund_temp_condition);
  530. //统计已经扣除的
  531. $over_refund_money = 0;
  532. $over_refund_pay_money = 0;//已退款真实退款金额
  533. $over_refund_balance_money = 0;//已退款退款现金余额
  534. $over_refund_balance = 0;//已退款退款储值余额
  535. $over_refund_point_money = 0;//已退积分金额
  536. $over_refund_point = 0;//已退积分
  537. foreach ($refund_temp_list as $k => $v) {
  538. $over_refund_money += $v['refund_money'];
  539. $over_refund_pay_money += $v['refund_pay_money'];
  540. $over_refund_point += $v['refund_point'];//退的积分
  541. $over_refund_point_money += $v['refund_point_money'];//退的积分金额
  542. $over_refund_balance += $v['refund_balance'];//储值余额
  543. $over_refund_balance_money += $v['refund_balance_money'];//现金余额
  544. }
  545. $order_goods_ids = $params['order_goods_ids'] ?? '';
  546. $order_goods_condition = array(
  547. ['order_goods_id', 'in', $order_goods_ids],
  548. );
  549. $order_goods_list = model('store_cashier_order_goods')->getList($order_goods_condition);
  550. $order_offset_model = new CashierOrderOffset();
  551. //订单的抵扣信息
  552. $offset_array = $order_offset_model->getOrderOffset(['order_id' => $order_id]) ?? [];
  553. $total_point = $offset_array['point'];
  554. $total_point_money = $offset_array['point_money'];
  555. $total_balance_money = $offset_array['balance_money'];
  556. $total_balance = $offset_array['balance'];
  557. $total_refund_money = 0;
  558. $total_refund_pay_money = 0;
  559. $total_refund_point = 0;
  560. $total_refund_point_money = 0;
  561. $total_refund_balance = 0;
  562. $total_refund_balance_money = 0;
  563. foreach($order_goods_list as $k => $v){
  564. $refund_params = array(
  565. 'over_refund_money' => $over_refund_money,
  566. 'over_refund_pay_money' => $over_refund_pay_money,
  567. 'over_refund_point' => $over_refund_point,
  568. 'over_refund_point_money' => $over_refund_point_money,
  569. 'over_refund_balance' => $over_refund_balance,
  570. 'over_refund_balance_money' => $over_refund_balance_money,
  571. 'order_goods_info' => $v,
  572. 'total_point' => $total_point,
  573. 'total_point_money' => $total_point_money,
  574. 'total_balance_money' => $total_balance_money,
  575. 'total_balance' => $total_balance,
  576. );
  577. $refund_params = array_merge($order_info, $refund_params);
  578. $item_refund_data = $this->getRefundApplyRefundMoney($refund_params);
  579. $item_refund_money = $item_refund_data['refund_money'] ?? 0;
  580. $item_refund_pay_money = $item_refund_data['refund_pay_money'] ?? 0;
  581. $item_refund_point = $item_refund_data['refund_point'] ?? 0;
  582. $item_refund_point_money = $item_refund_data['refund_point_money'] ?? 0;
  583. $item_refund_balance = $item_refund_data['refund_balance'] ?? 0;
  584. $item_refund_balance_money = $item_refund_data['refund_balance_money'] ?? 0;
  585. $over_refund_money -= $item_refund_money;
  586. $over_refund_pay_money -= $item_refund_pay_money;
  587. $over_refund_point -= $item_refund_point;
  588. $over_refund_point_money -= $item_refund_point_money;
  589. $over_refund_balance -= $item_refund_balance;
  590. $over_refund_balance_money -= $item_refund_balance_money;
  591. $total_refund_money += $item_refund_money;
  592. $total_refund_pay_money += $item_refund_pay_money;
  593. $total_refund_point += $item_refund_point;
  594. $total_refund_point_money += $item_refund_point_money;
  595. $total_refund_balance += $item_refund_balance;
  596. $total_refund_balance_money += $item_refund_balance_money;
  597. $order_goods_list[$k] = array_merge($v, $item_refund_data);//todo 订单和订单项重复的字段会被覆盖
  598. }
  599. $order_info['order_goods_list'] = $order_goods_list;
  600. $order_info['total_refund_money'] = $total_refund_money;
  601. $order_info['total_refund_pay_money'] = $total_refund_pay_money;
  602. $order_info['total_refund_point'] = $total_refund_point;
  603. $order_info['total_refund_point_money'] = $total_refund_point_money;
  604. $order_info['total_refund_balance'] = $total_refund_balance;
  605. $order_info['total_refund_balance_money'] = $total_refund_balance_money;
  606. return $this->success($order_info);
  607. }
  608. public function getRefundApplyRefundMoney($params){
  609. $order_goods_info = $params['order_goods_info'] ?? [];
  610. $over_refund_money = $params['over_refund_money'];
  611. $over_refund_pay_money = $params['over_refund_pay_money'];
  612. $over_refund_point = $params['over_refund_point'];//退的积分
  613. $over_refund_point_money = $params['over_refund_point_money'];//退的积分金额
  614. $over_refund_balance = $params['over_refund_balance'];//储值余额
  615. $over_refund_balance_money = $params['over_refund_balance_money'];//现金余额
  616. $order_id = $order_goods_info['order_id'];
  617. $order_goods_id = $order_goods_info['order_goods_id'];
  618. $order_money = $params['order_money'];
  619. $pay_money = $params['pay_money'];
  620. $total_point = $params['point'];
  621. $total_point_money = $params['point_money'];
  622. $total_balance_money = $params['balance_money'];
  623. $total_balance = $params['balance'];
  624. $cashier_order_goods_model = new CashierOrderGoods();
  625. //订单项真实商品金额
  626. $refund_goods_real_goods_money = $cashier_order_goods_model->getOrderGoodsRealMoney($order_goods_info);
  627. $refund_commission_rate = $refund_array['refund_commission_rate'] ?? 0;//退款手续费比率
  628. if($refund_goods_real_goods_money > 0){
  629. $surplus_order_money = $order_money - $over_refund_money;//剩余还能退的钱
  630. $surplus_pay_money = $pay_money - $over_refund_pay_money;//剩余真实金额
  631. $surplus_point = $total_point - $over_refund_point;//剩余可退积分
  632. $surplus_point_money = $total_point_money - $over_refund_point_money;//剩余积分可抵金额
  633. $surplus_balance_money = $total_balance_money - $over_refund_balance_money;//剩余现金余额
  634. $surplus_balance = $total_balance - $over_refund_balance;//剩余真储值余额
  635. $refund_shipping_money = 0;
  636. if ($refund_shipping_money > 0) {
  637. $refund_shipping_money = $refund_shipping_money > $surplus_order_money ? $surplus_order_money : $refund_shipping_money;
  638. $surplus_order_money -= $refund_shipping_money;
  639. }
  640. //真实金额所占比率
  641. $refund_goods_real_goods_money = $refund_goods_real_goods_money > $surplus_order_money ? $surplus_order_money : $refund_goods_real_goods_money;
  642. $refund_money = $refund_goods_real_goods_money + $refund_shipping_money;
  643. $refund_goods_real_goods_rate = $refund_goods_real_goods_money / ($refund_money+1);
  644. $real_rate = $refund_money / $order_money;
  645. $refund_balance = $total_balance * $real_rate;
  646. $refund_balance = $refund_balance > $surplus_balance ? $surplus_balance : $refund_balance;
  647. $refund_balance_money = round($total_balance_money * $real_rate, 2);
  648. $refund_balance_money = $refund_balance_money > $surplus_balance_money ? $surplus_balance_money : $refund_balance_money;
  649. $refund_point = round($total_point * $real_rate);
  650. $refund_point = $refund_point > $surplus_point ? $surplus_point : $refund_point;
  651. $refund_point_money = round($total_point_money * $real_rate, 2);
  652. $refund_point_money = $refund_point_money > $surplus_point_money ? $surplus_point_money : $refund_point_money;
  653. $refund_pay_money = round($pay_money * $real_rate, 2);
  654. $refund_pay_money = $refund_pay_money > $surplus_pay_money ? $surplus_pay_money : $refund_pay_money;
  655. //计算退款手续费
  656. if ($refund_pay_money > 0) {
  657. $refund_goods_pay_money = $refund_pay_money * $refund_goods_real_goods_rate;
  658. $refund_commission = $refund_goods_pay_money * $refund_commission_rate / 100;//
  659. }
  660. }
  661. $refund_array['refund_money'] = $refund_money ?? 0;
  662. $refund_array['refund_shipping_money'] = $refund_shipping_money ?? 0;
  663. $refund_array['refund_balance'] = $refund_balance ?? 0;
  664. $refund_array['refund_balance_money'] = $refund_balance_money ?? 0;
  665. $refund_array['refund_point'] = $refund_point ?? 0;
  666. $refund_array['refund_point_money'] = $refund_point_money ?? 0;
  667. $refund_array['refund_pay_money'] = $refund_pay_money ?? 0;
  668. $refund_array['refund_commission'] = $refund_commission ?? 0;
  669. return $refund_array;
  670. }
  671. /**
  672. * 收银订单退款
  673. * @param $params
  674. */
  675. public function activeOrderRefund($params)
  676. {
  677. $order_id = $params['order_id'];
  678. $cashier_condition = array(
  679. ['order_id', '=', $order_id]
  680. );
  681. $cashier_order_info = model('store_cashier_order')->getInfo($cashier_condition, '*');
  682. $site_id = $cashier_order_info['site_id'];
  683. $out_trade_no = $cashier_order_info['out_trade_no'];
  684. $online_money = $cashier_order_info['online_money'];
  685. //如果存在支付金额的话
  686. if ($online_money > 0) {
  687. $pay_model = new Pay();
  688. //退款编号
  689. $refund_no = $pay_model->createRefundNo();
  690. $pay_model->refund($refund_no, $online_money, $out_trade_no, '收银订单' . $cashier_order_info . '关闭,退款:' . $online_money, $online_money, $site_id, 1);
  691. }
  692. $member_id = $cashier_order_info['member_id'];
  693. //单纯退优惠券
  694. $offset_limit = ['balance', 'balance_money', 'point'];
  695. $order_offset_model = new CashierOrderOffset();
  696. $discount_params = array(
  697. 'site_id' => $site_id,
  698. 'member_id' => $member_id,
  699. 'order_id' => $order_id,
  700. 'limit' => $offset_limit
  701. );
  702. $discount_result = $order_offset_model->orderOffsetRefund($discount_params);
  703. if ($discount_result['code'] < 0) {
  704. return $discount_result;
  705. }
  706. $cashier_common_model = new CashierOrderCommon();
  707. $close_result = $cashier_common_model->orderClose([['order_id', '=', $order_id]]);
  708. if($close_result['code'] < 0)
  709. return $close_result;
  710. return $this->success();
  711. }
  712. /**
  713. * 获取退款分页列表
  714. * @param array $condition
  715. * @param bool $field
  716. * @param string $order
  717. * @param int $page
  718. * @param int $list_rows
  719. * @param string $alias
  720. * @param array $join
  721. * @return array
  722. */
  723. public function getRefundPageList($condition = [], $field = true, $order = '', $page = 1, $list_rows = PAGE_LIST_ROWS, $alias = 'a', $join = [])
  724. {
  725. $data = model('store_cashier_order_refund')->pageList($condition, $field, $order, $page, $list_rows, $alias, $join);
  726. return $this->success($data);
  727. }
  728. /**
  729. * 获取退款信息
  730. * @param array $condition
  731. * @param bool $field
  732. * @param string $alias
  733. * @param array $join
  734. * @return array
  735. */
  736. public function getRefundInfo($condition = [], $field = true, $alias = 'a', $join = [])
  737. {
  738. $data = model('store_cashier_order_refund')->getInfo($condition, $field, $alias, $join);
  739. return $this->success($data);
  740. }
  741. /**
  742. * 获取退款项列表
  743. * @param array $condition
  744. * @param bool $field
  745. * @param string $order
  746. * @param string $alias
  747. * @param array $join
  748. * @return array
  749. */
  750. public function getRefundGoodsList($condition = [], $field = true, $order = '', $alias = 'a', $join = [])
  751. {
  752. $data = model('store_cashier_order_goods_refund')->getList($condition, $field, $order, $alias, $join);
  753. return $this->success($data);
  754. }
  755. /**
  756. * 查询储值可退
  757. * @param $params
  758. * @return array
  759. */
  760. public function getMemberBalanceRefundData($params){
  761. $site_id = $params['site_id'] ?? 0;
  762. $member_id = $params['member_id'] ?? 0;
  763. // $store_id = $params['store_id'] ?? 0;
  764. //统计查询会员在充值上花的钱
  765. $recharge_condition = array(
  766. ['site_id', '=', $site_id],
  767. ['member_id', '=', $member_id],
  768. ['status', '=','complete', ]
  769. // ['store_id', '=', $store_id],
  770. );
  771. $refund_total_balance = model('store_cashier_order')->getSum( $recharge_condition, Db::raw('pay_money - refund_pay_money'));
  772. $use_condition = array(
  773. ['site_id', '=', $site_id],
  774. ['member_id', '=', $member_id],
  775. ['is_deduct_balance', '=', 1]
  776. );
  777. $use_total_balance = model('store_cashier_order')->getSum( $use_condition, 'total_balance');
  778. $member_account_condition = array(
  779. ['site_id', '=', $site_id],
  780. ['member_id', '=', $member_id],
  781. );
  782. $member_account_model =new MemberAccount();
  783. $member_account_result = $member_account_model->getMemberAccount($member_account_condition);
  784. $member_account = $member_account_result['data'] ?? [];
  785. $can_refund_balance = $refund_total_balance - $use_total_balance;
  786. if($can_refund_balance < 0){
  787. $can_refund_balance = 0;
  788. }
  789. $return_data = array(
  790. 'refund_total_balance' => $refund_total_balance,
  791. 'member_account' => $member_account,
  792. 'use_total_balance' => $use_total_balance,
  793. 'can_refund_balance' => $can_refund_balance,
  794. 'refund_transfer_type_list' => $this->getRefundTransferType(0)
  795. );
  796. return $this->success($return_data);
  797. }
  798. /**
  799. * 退款
  800. * @param $params
  801. * @return array
  802. */
  803. public function memberRefundBalance($params){
  804. $result = $this->getMemberBalanceRefundData($params);
  805. if($result['code'] < 0)
  806. return $result;
  807. $refund_data = $result['data'];
  808. $site_id = $params['site_id'] ?? 0;
  809. $member_id = $params['member_id'] ?? 0;
  810. $store_id = $params['store_id'];
  811. $member_account = $refund_data['member_account'] ?? [];
  812. $can_refund_balance = $refund_data['can_refund_balance'];
  813. if($can_refund_balance <= 0){
  814. return $this->error([], '没有可退的余额');
  815. }
  816. $refund_total_balance = $refund_data['refund_total_balance'];
  817. $refund_transfer_type = $params['refund_transfer_type'] ?? '';
  818. $refund_balance = $params['refund_balance'] ?? 0;
  819. if($refund_balance > $can_refund_balance){
  820. return $this->error([], '申请退款不能大于可退金额');
  821. }
  822. $pay_model = new Pay();
  823. $refund_no = $pay_model->createRefundNo();
  824. $refund_reason = $params['refund_reason'] ?? '';
  825. $refund_remark = $params['refund_remark'] ?? '';
  826. $operator = $params['operator'] ?? [];
  827. $operator_id = $operator['uid'] ?? 0;
  828. $operator_name = $operator['username'] ?? '';
  829. $insert_data = array(
  830. 'order_id' => 0,
  831. 'member_id' => $member_id,
  832. 'refund_no' => $refund_no,
  833. 'store_id' => $store_id,
  834. 'site_id' => $site_id,
  835. 'refund_pay_money' => $refund_balance,
  836. 'refund_money' => $refund_balance,
  837. 'refund_reason' => $refund_reason,
  838. 'refund_remark' => $refund_remark,
  839. 'create_time' => time(),
  840. 'refund_status' => self::REFUND_COMPLETE,
  841. 'refund_transfer_type' => $refund_transfer_type,
  842. 'refund_trade_type' => 'balance',
  843. 'operator_id' => $operator_id,
  844. 'operator_name' => $operator_name,
  845. );
  846. $insert_data = $this->tran($insert_data);
  847. //实际退款
  848. $refund_id = model('store_cashier_order_refund')->add($insert_data);
  849. $pay_model = new Pay();
  850. $refund_transfer_no = $pay_model->createRefundNo();
  851. $refund_name = '储值退款';
  852. $refund_img = 'upload/cashier/member-recharge-icon.png';
  853. $insert_goods_data = array(
  854. 'member_id' => $params['member_id'],
  855. 'refund_transfer_no' => $refund_transfer_no,
  856. 'site_id' => $site_id,
  857. 'store_id' => $store_id,
  858. 'refund_num' => 1,
  859. 'refund_pay_money' => $refund_balance,
  860. 'refund_money' => $refund_balance,
  861. 'refund_id' => $refund_id,
  862. 'name' => $refund_name,
  863. 'img' => $refund_img,
  864. );
  865. //实际退款
  866. $refund_goods_id = model('store_cashier_order_goods_refund')->add($insert_goods_data);
  867. //todo 这儿可以调用实际退款
  868. $this->refundPayMoney($insert_goods_data);
  869. //余额清零
  870. $member_account_model = new MemberAccount();
  871. $refund_balance = $member_account['balance'];
  872. $refund_balance_money = $member_account['balance_money'];
  873. if ($refund_balance_money > 0) {
  874. $from_type = 'refund';//todo 需要改
  875. $relate_tag = '现金余额清零';
  876. $remark = '订单退款,退还现金余额:' . $refund_balance_money;
  877. $account_title = '订单退款,退还现金余额';
  878. $result = $member_account_model->addMemberAccount($site_id, $member_id, 'balance_money', -$refund_balance_money, $from_type, $relate_tag, $remark, $account_title);
  879. if ($result['code'] < 0) {
  880. return $result;
  881. }
  882. }
  883. if ($refund_balance > 0) {
  884. $from_type = 'refund';
  885. $relate_tag = '储值余额清零';
  886. $remark = '订单退款,退还储值余额:' . $refund_balance;
  887. $account_title = '订单退款,退还储值余额';
  888. $result = $member_account_model->addMemberAccount($site_id, $member_id, 'balance', -$refund_balance, $from_type, $relate_tag, $remark, $account_title);
  889. if ($result['code'] < 0) {
  890. return $result;
  891. }
  892. }
  893. $insert_data['refund_id'] = $refund_id;
  894. $this->complete($insert_data);
  895. return $this->success();
  896. }
  897. /**
  898. * 退款完毕
  899. * @param $params
  900. */
  901. public function complete($params){
  902. $order_id = $params['order_id'];
  903. $refund_id = $params['refund_id'];
  904. $refund_info = $this->getRefundInfo([['refund_id', '=', $refund_id]])['data'] ?? [];
  905. $refund_trade_type = $params['refund_trade_type'];
  906. if($refund_trade_type == 'order'){
  907. //累加订单退款
  908. $refund_data = array(
  909. 'refund_money' => Db::raw('refund_money + '.$refund_info['refund_money']),
  910. 'refund_pay_money' => Db::raw('refund_pay_money + '.$refund_info['refund_pay_money']),
  911. 'refund_point' => Db::raw('refund_point + '.$refund_info['refund_point']),
  912. 'refund_point_money' => Db::raw('refund_point_money + '.$refund_info['refund_point_money']),
  913. 'refund_balance_money' => Db::raw('refund_balance_money + '.$refund_info['refund_balance_money']),
  914. 'refund_balance' => Db::raw('refund_balance + '.$refund_info['refund_balance']),
  915. );
  916. model('store_cashier_order')->update($refund_data, [['order_id', '=', $order_id]]);
  917. //核验订单
  918. $this->checkOrderRefund(['order_id' => $order_id]);
  919. }
  920. event('SiteStat', [
  921. 'site_id' => $refund_info['site_id'],
  922. 'store_id' => $refund_info['store_id'] ?? 0,
  923. 'stat_type' => 'order_refund',
  924. 'stat_data' => $refund_info['refund_pay_money'],
  925. ]);
  926. return $this->success();
  927. }
  928. /**
  929. * 核验订单是否全部退完
  930. * @param $params
  931. * @return array
  932. */
  933. public function checkOrderRefund($params){
  934. $order_id = $params['order_id'];
  935. $refund_order_goods_condition = array(
  936. ['order_id', '=', $order_id],
  937. ['refund_status', '=', 'refund_complete']
  938. );
  939. $refund_goods_count = model('store_cashier_order_goods')->getCount($refund_order_goods_condition);
  940. $order_goods_condition = array(
  941. ['order_id', '=', $order_id],
  942. // ['is_can_refund', '=', 1],
  943. );
  944. $order_goods_count = model('store_cashier_order_goods')->getCount($order_goods_condition);
  945. if($refund_goods_count == $order_goods_count){//如果订单项全部都退完的话,订单会关闭
  946. $this->setOrderRefund(['order_id' => $order_id]);
  947. $cashier_order_model = new CashierOrderCommon();
  948. $order_close_condition = array(
  949. ['order_id', '=', $order_id]
  950. );
  951. $cashier_order_model->orderClose($order_close_condition);
  952. }
  953. return $this->success();
  954. }
  955. }