11package org .linlinjava .litemall .admin .web ;
22
3+ import com .github .binarywang .wxpay .bean .request .WxPayRefundRequest ;
4+ import com .github .binarywang .wxpay .bean .result .WxPayRefundResult ;
5+ import com .github .binarywang .wxpay .exception .WxPayException ;
6+ import com .github .binarywang .wxpay .service .WxPayService ;
37import org .apache .commons .logging .Log ;
48import org .apache .commons .logging .LogFactory ;
59import org .apache .shiro .authz .annotation .RequiresPermissions ;
610import org .linlinjava .litemall .admin .annotation .RequiresPermissionsDesc ;
11+ import org .linlinjava .litemall .admin .service .LogHelper ;
12+ import org .linlinjava .litemall .admin .util .AdminResponseCode ;
13+ import org .linlinjava .litemall .core .notify .NotifyService ;
14+ import org .linlinjava .litemall .core .notify .NotifyType ;
715import org .linlinjava .litemall .core .util .JacksonUtil ;
816import org .linlinjava .litemall .core .util .ResponseUtil ;
917import org .linlinjava .litemall .core .validator .Order ;
1018import org .linlinjava .litemall .core .validator .Sort ;
1119import org .linlinjava .litemall .db .domain .LitemallAftersale ;
20+ import org .linlinjava .litemall .db .domain .LitemallGoodsProduct ;
21+ import org .linlinjava .litemall .db .domain .LitemallOrder ;
22+ import org .linlinjava .litemall .db .domain .LitemallOrderGoods ;
1223import org .linlinjava .litemall .db .service .*;
24+ import org .linlinjava .litemall .db .util .AftersaleConstant ;
25+ import org .linlinjava .litemall .db .util .OrderUtil ;
1326import org .springframework .beans .factory .annotation .Autowired ;
1427import org .springframework .validation .annotation .Validated ;
1528import org .springframework .web .bind .annotation .*;
29+
30+ import java .math .BigDecimal ;
31+ import java .time .LocalDateTime ;
1632import java .util .List ;
1733
34+ import static org .linlinjava .litemall .admin .util .AdminResponseCode .ORDER_REFUND_FAILED ;
35+
1836@ RestController
1937@ RequestMapping ("/admin/aftersale" )
2038@ Validated
@@ -27,34 +45,188 @@ public class AdminAftersaleController {
2745 private LitemallOrderService orderService ;
2846 @ Autowired
2947 private LitemallOrderGoodsService orderGoodsService ;
48+ @ Autowired
49+ private LitemallGoodsProductService goodsProductService ;
50+ @ Autowired
51+ private LogHelper logHelper ;
52+ @ Autowired
53+ private WxPayService wxPayService ;
54+ @ Autowired
55+ private NotifyService notifyService ;
3056
3157 @ RequiresPermissions ("admin:aftersale:list" )
3258 @ RequiresPermissionsDesc (menu = {"商城管理" , "售后管理" }, button = "查询" )
3359 @ GetMapping ("/list" )
34- public Object list (Integer orderId , String aftersaleSn ,
60+ public Object list (Integer orderId , String aftersaleSn , Short status ,
3561 @ RequestParam (defaultValue = "1" ) Integer page ,
3662 @ RequestParam (defaultValue = "10" ) Integer limit ,
3763 @ Sort @ RequestParam (defaultValue = "add_time" ) String sort ,
3864 @ Order @ RequestParam (defaultValue = "desc" ) String order ) {
39- List <LitemallAftersale > aftersaleList = aftersaleService .querySelective (orderId , aftersaleSn , page , limit , sort , order );
65+ List <LitemallAftersale > aftersaleList = aftersaleService .querySelective (orderId , aftersaleSn , status , page , limit , sort , order );
4066 return ResponseUtil .okList (aftersaleList );
4167 }
4268
69+ @ RequiresPermissions ("admin:aftersale:recept" )
70+ @ RequiresPermissionsDesc (menu = {"商城管理" , "售后管理" }, button = "审核通过" )
71+ @ PostMapping ("/recept" )
72+ public Object recept (@ RequestBody LitemallAftersale aftersale ) {
73+ Integer id = aftersale .getId ();
74+ LitemallAftersale aftersaleOne = aftersaleService .findById (id );
75+ if (aftersaleOne == null ){
76+ return ResponseUtil .fail (AdminResponseCode .AFTERSALE_NOT_ALLOWED , "售后不存在" );
77+ }
78+ Short status = aftersaleOne .getStatus ();
79+ if (!status .equals (AftersaleConstant .STATUS_REQUEST )){
80+ return ResponseUtil .fail (AdminResponseCode .AFTERSALE_NOT_ALLOWED , "售后不能进行审核通过操作" );
81+ }
82+ aftersaleOne .setStatus (AftersaleConstant .STATUS_RECEPT );
83+ aftersaleOne .setHandleTime (LocalDateTime .now ());
84+ aftersaleService .updateById (aftersaleOne );
85+
86+ // 订单也要更新售后状态
87+ orderService .updateAftersaleStatus (aftersaleOne .getOrderId (), AftersaleConstant .STATUS_RECEPT );
88+ return ResponseUtil .ok ();
89+ }
90+
91+ @ RequiresPermissions ("admin:aftersale:batch-recept" )
92+ @ RequiresPermissionsDesc (menu = {"商城管理" , "售后管理" }, button = "批量通过" )
93+ @ PostMapping ("/batch-recept" )
94+ public Object batchRecept (@ RequestBody String body ) {
95+ List <Integer > ids = JacksonUtil .parseIntegerList (body , "ids" );
96+ // NOTE
97+ // 批量操作中,如果一部分数据项失败,应该如何处理
98+ // 这里采用忽略失败,继续处理其他项。
99+ // 当然开发者可以采取其他处理方式,具体情况具体分析,例如利用事务回滚所有操作然后返回用户失败信息
100+ for (Integer id : ids ) {
101+ LitemallAftersale aftersale = aftersaleService .findById (id );
102+ if (aftersale == null ){
103+ continue ;
104+ }
105+ Short status = aftersale .getStatus ();
106+ if (!status .equals (AftersaleConstant .STATUS_REQUEST )){
107+ continue ;
108+ }
109+ aftersale .setStatus (AftersaleConstant .STATUS_RECEPT );
110+ aftersale .setHandleTime (LocalDateTime .now ());
111+ aftersaleService .updateById (aftersale );
112+
113+ // 订单也要更新售后状态
114+ orderService .updateAftersaleStatus (aftersale .getOrderId (), AftersaleConstant .STATUS_RECEPT );
115+ }
116+ return ResponseUtil .ok ();
117+ }
118+
119+ @ RequiresPermissions ("admin:aftersale:reject" )
120+ @ RequiresPermissionsDesc (menu = {"商城管理" , "售后管理" }, button = "审核拒绝" )
121+ @ PostMapping ("/reject" )
122+ public Object reject (@ RequestBody LitemallAftersale aftersale ) {
123+ Integer id = aftersale .getId ();
124+ LitemallAftersale aftersaleOne = aftersaleService .findById (id );
125+ if (aftersaleOne == null ){
126+ return ResponseUtil .badArgumentValue ();
127+ }
128+ Short status = aftersaleOne .getStatus ();
129+ if (!status .equals (AftersaleConstant .STATUS_REQUEST )){
130+ return ResponseUtil .fail (AdminResponseCode .AFTERSALE_NOT_ALLOWED , "售后不能进行审核拒绝操作" );
131+ }
132+ aftersaleOne .setStatus (AftersaleConstant .STATUS_REJECT );
133+ aftersaleOne .setHandleTime (LocalDateTime .now ());
134+ aftersaleService .updateById (aftersaleOne );
43135
44- @ RequiresPermissions ("admin:aftersale:delete" )
45- @ RequiresPermissionsDesc (menu = {"商城管理" , "售后管理" }, button = "删除" )
46- @ PostMapping ("/delete" )
47- public Object delete (@ RequestBody LitemallAftersale aftersale ) {
48- aftersaleService .deleteById (aftersale .getId ());
136+ // 订单也要更新售后状态
137+ orderService .updateAftersaleStatus (aftersaleOne .getOrderId (), AftersaleConstant .STATUS_REJECT );
49138 return ResponseUtil .ok ();
50139 }
51140
52- @ RequiresPermissions ("admin:aftersale:batch-delete " )
53- @ RequiresPermissionsDesc (menu = {"商城管理" , "售后管理" }, button = "批量删除 " )
54- @ PostMapping ("/batch-delete " )
55- public Object batchDelete (@ RequestBody String body ) {
141+ @ RequiresPermissions ("admin:aftersale:batch-reject " )
142+ @ RequiresPermissionsDesc (menu = {"商城管理" , "售后管理" }, button = "批量拒绝 " )
143+ @ PostMapping ("/batch-reject " )
144+ public Object batchReject (@ RequestBody String body ) {
56145 List <Integer > ids = JacksonUtil .parseIntegerList (body , "ids" );
57- aftersaleService .deleteByIds (ids );
146+ for (Integer id : ids ) {
147+ LitemallAftersale aftersale = aftersaleService .findById (id );
148+ if (aftersale == null ){
149+ continue ;
150+ }
151+ Short status = aftersale .getStatus ();
152+ if (!status .equals (AftersaleConstant .STATUS_REQUEST )){
153+ continue ;
154+ }
155+ aftersale .setStatus (AftersaleConstant .STATUS_REJECT );
156+ aftersale .setHandleTime (LocalDateTime .now ());
157+ aftersaleService .updateById (aftersale );
158+
159+ // 订单也要更新售后状态
160+ orderService .updateAftersaleStatus (aftersale .getOrderId (), AftersaleConstant .STATUS_REJECT );
161+ }
162+ return ResponseUtil .ok ();
163+ }
164+
165+ @ RequiresPermissions ("admin:aftersale:refund" )
166+ @ RequiresPermissionsDesc (menu = {"商城管理" , "售后管理" }, button = "退款" )
167+ @ PostMapping ("/refund" )
168+ public Object refund (@ RequestBody LitemallAftersale aftersale ) {
169+ Integer id = aftersale .getId ();
170+ LitemallAftersale aftersaleOne = aftersaleService .findById (id );
171+ if (aftersaleOne == null ){
172+ return ResponseUtil .badArgumentValue ();
173+ }
174+ if (!aftersaleOne .getStatus ().equals (AftersaleConstant .STATUS_RECEPT )){
175+ return ResponseUtil .fail (AdminResponseCode .AFTERSALE_NOT_ALLOWED , "售后不能进行退款操作" );
176+ }
177+ Integer orderId = aftersaleOne .getOrderId ();
178+ LitemallOrder order = orderService .findById (orderId );
179+
180+ // 微信退款
181+ WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest ();
182+ wxPayRefundRequest .setOutTradeNo (order .getOrderSn ());
183+ wxPayRefundRequest .setOutRefundNo ("refund_" + order .getOrderSn ());
184+ // 元转成分
185+ Integer totalFee = aftersaleOne .getAmount ().multiply (new BigDecimal (100 )).intValue ();
186+ wxPayRefundRequest .setTotalFee (totalFee );
187+ wxPayRefundRequest .setRefundFee (totalFee );
188+
189+ WxPayRefundResult wxPayRefundResult ;
190+ try {
191+ wxPayRefundResult = wxPayService .refund (wxPayRefundRequest );
192+ } catch (WxPayException e ) {
193+ logger .error (e .getMessage (), e );
194+ return ResponseUtil .fail (ORDER_REFUND_FAILED , "订单退款失败" );
195+ }
196+ if (!wxPayRefundResult .getReturnCode ().equals ("SUCCESS" )) {
197+ logger .warn ("refund fail: " + wxPayRefundResult .getReturnMsg ());
198+ return ResponseUtil .fail (ORDER_REFUND_FAILED , "订单退款失败" );
199+ }
200+ if (!wxPayRefundResult .getResultCode ().equals ("SUCCESS" )) {
201+ logger .warn ("refund fail: " + wxPayRefundResult .getReturnMsg ());
202+ return ResponseUtil .fail (ORDER_REFUND_FAILED , "订单退款失败" );
203+ }
204+
205+ aftersaleOne .setStatus (AftersaleConstant .STATUS_REFUND );
206+ aftersaleOne .setHandleTime (LocalDateTime .now ());
207+ aftersaleService .updateById (aftersaleOne );
208+
209+ orderService .updateAftersaleStatus (orderId , AftersaleConstant .STATUS_REFUND );
210+
211+ // NOTE
212+ // 如果是“退货退款”类型的售后,这里退款说明用户的货已经退回,则需要商品货品数量增加
213+ // 开发者也可以删除一下代码,在其他地方增加商品货品入库操作
214+ if (aftersale .getType ().equals (AftersaleConstant .TYPE_GOODS_REQUIRED )) {
215+ List <LitemallOrderGoods > orderGoodsList = orderGoodsService .queryByOid (orderId );
216+ for (LitemallOrderGoods orderGoods : orderGoodsList ) {
217+ Integer productId = orderGoods .getProductId ();
218+ Short number = orderGoods .getNumber ();
219+ goodsProductService .addStock (productId , number );
220+ }
221+ }
222+
223+ // 发送短信通知,这里采用异步发送
224+ // 退款成功通知用户, 例如“您申请的订单退款 [ 单号:{1} ] 已成功,请耐心等待到账。”
225+ // TODO 注意订单号只发后6位
226+ notifyService .notifySmsTemplate (order .getMobile (), NotifyType .REFUND ,
227+ new String []{order .getOrderSn ().substring (8 , 14 )});
228+
229+ logHelper .logOrderSucceed ("退款" , "订单编号 " + order .getOrderSn () + " 售后编号 " + aftersale .getAftersaleSn ());
58230 return ResponseUtil .ok ();
59231 }
60232}
0 commit comments