Aftersale.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. <?php
  2. namespace addons\shopro\controller\order;
  3. use think\Db;
  4. use addons\shopro\controller\Common;
  5. use app\admin\model\shopro\order\Order as OrderModel;
  6. use app\admin\model\shopro\order\OrderItem as OrderItemModel;
  7. use app\admin\model\shopro\order\Aftersale as AftersaleModel;
  8. use app\admin\model\shopro\order\AftersaleLog as AftersaleLogModel;
  9. use app\admin\model\shopro\order\Action as OrderActionModel;
  10. use addons\shopro\library\express\Express as ExpressLib;
  11. class Aftersale extends Common
  12. {
  13. protected $noNeedLogin = [];
  14. protected $noNeedRight = ['*'];
  15. //售后原因
  16. public function aftersale_reason(){
  17. $data = [
  18. '不想要了',
  19. '不喜欢、效果不好',
  20. '货物与描述不符',
  21. '质量问题',
  22. '收到商品少件(含少配件)',
  23. '商品破损或污渍',
  24. '商家发错货',
  25. '假冒品牌',
  26. '其他原因',
  27. ];
  28. $this->success(1, $data);
  29. }
  30. //售后列表
  31. public function index() {
  32. $user = auth_user();
  33. $params = $this->request->param();
  34. $type = $params['type'] ?? 'all';
  35. $aftersales = AftersaleModel::where('user_id', $user->id);
  36. if ($type != 'all') {
  37. $aftersales = $aftersales->{$type}();
  38. }
  39. $aftersales = $aftersales->order('id', 'desc')
  40. ->autopage()->select();
  41. // ->paginate($this->request->param('list_rows', 10));
  42. //综合状态
  43. foreach($aftersales as $key => $aftersale){
  44. $aftersale['status_show_text'] = $aftersale['aftersale_status_text'].','.$aftersale['refund_status_text'];
  45. $aftersales[$key] = $aftersale;
  46. }
  47. $this->success('获取成功', $aftersales);
  48. }
  49. //售后详情
  50. public function detail()
  51. {
  52. $user = auth_user();
  53. $id = $this->request->param('id');
  54. $aftersale = AftersaleModel::where('user_id', $user->id)->with('logs')->where('id', $id)->find();
  55. if (!$aftersale) {
  56. $this->error(__('No Results were found'));
  57. }
  58. //寄回地址
  59. $aftersale_address = Db::name('shopro_aftersale_address')->order('is_default','desc')->order('id desc')->find();
  60. $aftersale['aftersale_address'] = $aftersale_address;
  61. //综合状态
  62. $aftersale['status_show_text'] = $aftersale['aftersale_status_text'].','.$aftersale['refund_status_text'];
  63. $this->success('获取成功', $aftersale);
  64. }
  65. //申请售后
  66. public function add()
  67. {
  68. $user = auth_user();
  69. $params = $this->request->param();
  70. $this->svalidate($params, ".add");
  71. $aftersale = Db::transaction(function () use ($user, $params) {
  72. $type = $params['type'];
  73. $order_id = $params['order_id'];
  74. $order_item_id = $params['order_item_id'];
  75. $mobile = $params['mobile'] ?? '';
  76. $reason = $params['reason'] ?? '用户申请售后';
  77. $content = $params['content'] ?? '';
  78. $images = $params['images'] ? json_decode(htmlspecialchars_decode($params['images']),true) : [];
  79. //申请退款金额
  80. $refund_money = round(floatval($params['apply_refund_price']), 2);
  81. if ($refund_money <= 0) {
  82. $this->error('请输入正确的退款金额');
  83. }
  84. //订单状态:已支付,已完成
  85. $order = OrderModel::canAftersale()->where('user_id', $user->id)->lock(true)->where('id', $order_id)->find();
  86. if (!$order) {
  87. error_stop('订单不存在或不可售后');
  88. }
  89. $item = OrderItemModel::where('user_id', $user->id)->where('order_id',$order_id)->where('id', $order_item_id)->find();
  90. if (!$item) {
  91. error_stop('参数错误');
  92. }
  93. if (!in_array($item->aftersale_status, [
  94. OrderItemModel::AFTERSALE_STATUS_REFUSE, //拒绝
  95. OrderItemModel::AFTERSALE_STATUS_NOAFTER //未申请
  96. ])) {
  97. error_stop('当前订单商品不可申请售后');
  98. }
  99. //apply_refund_price 限制金额
  100. $ordernew = OrderModel::withTrashed()->with('items')->find($order_id);
  101. if (!$ordernew) {
  102. $this->error('订单不存在');
  103. }
  104. $items = $ordernew->items;
  105. $items = array_column($items, null, 'id');
  106. // 当前订单已退款总金额
  107. $refunded_money = array_sum(array_column($items, 'refund_fee'));
  108. // 剩余可退款金额
  109. $refund_surplus_money = bcsub($order->pay_fee, (string)$refunded_money, 2);
  110. // 如果退款金额大于订单支付总金额
  111. if (bccomp((string)$refund_money, $refund_surplus_money, 2) === 1) {
  112. $this->error('退款总金额不能大于实际支付金额');
  113. }
  114. $aftersale = new AftersaleModel();
  115. $aftersale->aftersale_sn = get_sn($user->id, 'A');
  116. $aftersale->user_id = $user->id;
  117. $aftersale->type = $type;
  118. $aftersale->mobile = $mobile;
  119. $aftersale->activity_id = $item['activity_id'];
  120. $aftersale->activity_type = $item['activity_type'];
  121. $aftersale->order_id = $order_id;
  122. $aftersale->order_item_id = $order_item_id;
  123. $aftersale->goods_id = $item['goods_id'];
  124. $aftersale->goods_sku_price_id = $item['goods_sku_price_id'];
  125. $aftersale->goods_sku_text = $item['goods_sku_text'];
  126. $aftersale->goods_title = $item['goods_title'];
  127. $aftersale->goods_image = $item['goods_image'];
  128. $aftersale->goods_original_price = $item['goods_original_price'];
  129. $aftersale->discount_fee = $item['discount_fee'];
  130. $aftersale->goods_price = $item['goods_price'];
  131. $aftersale->goods_num = $item['goods_num'];
  132. $aftersale->dispatch_status = $item['dispatch_status'];
  133. $aftersale->dispatch_fee = $item['dispatch_fee'];
  134. $aftersale->aftersale_status = AftersaleModel::AFTERSALE_STATUS_NOOPER; // 未处理
  135. $aftersale->refund_status = AftersaleModel::REFUND_STATUS_NOREFUND; // 未退款
  136. $aftersale->apply_refund_price = $refund_money;
  137. $aftersale->refund_fee = 0;
  138. $aftersale->reason = $reason;
  139. $aftersale->content = $content;
  140. $aftersale->express_status = 'noinfo';
  141. $aftersale->save();
  142. // 增加售后单变动记录、
  143. AftersaleLogModel::add($order, $aftersale, $user, 'user', [
  144. 'log_type' => 'apply_aftersale',
  145. 'content' => "申请原因:$reason <br>相关描述: $content",
  146. 'images' => $images
  147. ]);
  148. $ext = $item->ext ?: [];
  149. $ext['aftersale_id'] = $aftersale->id;
  150. // 修改订单 item 状态,申请售后
  151. $item->aftersale_status = OrderItemModel::AFTERSALE_STATUS_ING;
  152. $item->ext = $ext;
  153. $item->save();
  154. OrderActionModel::add($order, $item, $user, 'user', '用户申请售后');
  155. return $aftersale;
  156. });
  157. $this->success('申请成功', $aftersale);
  158. }
  159. //售后寄回
  160. public function send(){
  161. $user = auth_user();
  162. $id = input('id',0,'intval');
  163. $express_id = input('express_id',0,'intval');
  164. $express_no = input('express_no','','trim');
  165. if(!$id || !$express_id || !$express_no){
  166. $this->error();
  167. }
  168. $express = Db::name('shopro_data_express')->where('id',$express_id)->find();
  169. if(!$express){
  170. $this->error('请输入正确的快递公司');
  171. }
  172. $aftersale = Db::name('shopro_order_aftersale')->where('id',$id)->where('user_id',$user['id'])->find();
  173. if (!$aftersale) {
  174. $this->error('售后订单不存在');
  175. }
  176. if($aftersale['type'] != 'return'){
  177. $this->error('退货退款的订单才需要寄回商品');
  178. }
  179. // 同意并处理中
  180. if($aftersale['aftersale_status'] != AftersaleModel::AFTERSALE_STATUS_ING){
  181. $this->error('商家还没有同意售后');
  182. }
  183. // 不要重复寄回
  184. if(!empty($aftersale['express_no'])){
  185. $this->error('已经寄回了无需重复操作');
  186. }
  187. $data = [
  188. 'express_name' => $express['name'],
  189. 'express_code' => $express['code'],
  190. 'express_no' => $express_no,
  191. ];
  192. $rs = Db::name('shopro_order_aftersale')->where('id',$id)->update($data);
  193. //参照后台发货
  194. $this->subscribeExpressInfo($data);
  195. $this->success('操作成功');
  196. }
  197. // 订阅物流追踪
  198. private function subscribeExpressInfo($orderExpress)
  199. {
  200. try {
  201. $expressLib = new ExpressLib();
  202. $a = $expressLib->subscribe([
  203. 'express_code' => $orderExpress['express_code'],
  204. 'express_no' => $orderExpress['express_no'],
  205. 'Callback' => 'Aftersale',
  206. ]);
  207. } catch (\Exception $e) {
  208. // Nothing TODO
  209. return;
  210. }
  211. }
  212. //取消售后
  213. public function cancel()
  214. {
  215. $user = auth_user();
  216. $id = $this->request->param('id');
  217. $aftersale = AftersaleModel::canCancel()->where('user_id', $user->id)->where('id', $id)->find();
  218. if (!$aftersale) {
  219. $this->error('售后单不存在或不可取消');
  220. }
  221. if ($aftersale['refund_status'] != AftersaleModel::REFUND_STATUS_NOREFUND) {
  222. //已经退款
  223. $this->error('退款商品已退款');
  224. }
  225. $order = OrderModel::where('user_id', $user->id)->find($aftersale['order_id']);
  226. if (!$order) {
  227. $this->error(__('No Results were found'));
  228. }
  229. $orderItem = OrderItemModel::find($aftersale['order_item_id']);
  230. if (!$orderItem) {
  231. // 不存在
  232. $this->error('退款商品不存在');
  233. }
  234. //这里用了两个状态,因为shopro也搞不清是哪个
  235. if (in_array($orderItem['refund_status'], [OrderItemModel::REFUND_STATUS_AGREE, OrderItemModel::REFUND_STATUS_COMPLETED])) {
  236. //已经退款
  237. $this->error('退款商品已退款');
  238. }
  239. $aftersale = Db::transaction(function () use ($aftersale, $order, $orderItem, $user) {
  240. $aftersale->aftersale_status = AftersaleModel::AFTERSALE_STATUS_CANCEL; // 取消售后单
  241. $aftersale->save();
  242. AftersaleLogModel::add($order, $aftersale, $user, 'user', [
  243. 'log_type' => 'cancel',
  244. 'content' => '用户取消申请售后',
  245. 'images' => []
  246. ]);
  247. // 修改订单 item 为未申请售后
  248. $orderItem->aftersale_status = OrderItemModel::AFTERSALE_STATUS_NOAFTER;
  249. $orderItem->refund_status = OrderItemModel::REFUND_STATUS_NOREFUND;
  250. $orderItem->save();
  251. OrderActionModel::add($order, $orderItem, $user, 'user', '用户取消申请售后');
  252. return $aftersale;
  253. });
  254. $this->success('取消成功', $aftersale);
  255. }
  256. public function delete()
  257. {
  258. $user = auth_user();
  259. $id = $this->request->param('id');
  260. $aftersale = AftersaleModel::canDelete()->where('user_id', $user->id)->where('id', $id)->find();
  261. if (!$aftersale) {
  262. $this->error('售后单不存在或不可删除');
  263. }
  264. $order = OrderModel::withTrashed()->where('id', $aftersale['order_id'])->find();
  265. Db::transaction(function () use ($aftersale, $order, $user) {
  266. AftersaleLogModel::add($order, $aftersale, $user, 'user', [
  267. 'log_type' => 'delete',
  268. 'content' => '用户删除售后单',
  269. 'images' => []
  270. ]);
  271. $aftersale->delete(); // 删除售后单(后删除,否则添加记录时 $aftersale 没数据)
  272. });
  273. $this->success('删除成功');
  274. }
  275. //退款的物流信息
  276. public function express()
  277. {
  278. $user = auth_user();
  279. $id = $this->request->param('id');
  280. $expresses = AftersaleModel::with(['expresslogs'])->where('user_id', $user->id)->where('id', $id)->find();
  281. // 更新包裹信息(5分钟缓存)
  282. (new ExpressLib)->updateOrderExpress($expresses['order_id']);
  283. $order_sn = Db::name('shopro_order')->where('id',$expresses['order_id'])->value('order_sn');
  284. //寄回地址
  285. $aftersale_address = Db::name('shopro_aftersale_address')->order('is_default','desc')->order('id desc')->find();
  286. $result = [
  287. 'order_sn' => $order_sn,
  288. 'address' => $aftersale_address,
  289. 'expresses' => $expresses,
  290. 'goods_image' => localpath_to_netpath($expresses['goods_image']),
  291. ];
  292. $this->success('获取成功', $result);
  293. }
  294. }