package com.ruoyi.mall.controller; import java.math.BigDecimal; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.utils.ApiResult; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.sign.Md5Utils; import com.ruoyi.mall.domain.MallOrderOrder; import com.ruoyi.mall.domain.MallSalesmanAchievement; import com.ruoyi.mall.domain.MallShopShop; import com.ruoyi.mall.domain.vo.MallOrderGoodsVO; import com.ruoyi.mall.mapper.MallSalesmanAchievementMapper; import com.ruoyi.mall.service.IMallOrderGoodsService; import com.ruoyi.mall.service.IMallOrderOrderService; import com.ruoyi.mall.service.IMallShopShopService; import com.ruoyi.web.controller.utils.XiaochengxuPayService; import io.swagger.annotations.Api; import org.apache.commons.lang3.ObjectUtils; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.mall.domain.MallOrderBack; import com.ruoyi.mall.service.IMallOrderBackService; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.core.page.TableDataInfo; /** * 退款单Controller * * @author chang * @date 2021-11-25 */ @RestController @RequestMapping("/mall/mallOrderBack") public class MallOrderBackController extends BaseController { @Autowired private IMallOrderBackService mallOrderBackService; @Autowired private IMallOrderOrderService orderOrderService; @Autowired private IMallShopShopService shopShopService; @Autowired private IMallOrderGoodsService orderGoodsService; @Autowired private MallSalesmanAchievementMapper mallSalesmanAchievementMapper; /** * 查询退款单列表 */ @PreAuthorize("@ss.hasPermi('mall:mallOrderBack:list')") @GetMapping("/list") public TableDataInfo list(MallOrderBack mallOrderBack) { LoginUser loginUser = SecurityUtils.getLoginUser(); MallShopShop mallShopShop = shopShopService.selectMallShopShopBySysUserId(loginUser.getUserId()); if (ObjectUtils.isNotEmpty(mallShopShop)){ mallOrderBack.setShopId(mallShopShop.getShopId()); } startPage(); List list = mallOrderBackService.selectMallOrderBackList(mallOrderBack); return getDataTable(list); } /** * 导出退款单列表 */ @PreAuthorize("@ss.hasPermi('mall:mallOrderBack:export')") @Log(title = "退款单", businessType = BusinessType.EXPORT) @GetMapping("/export") public AjaxResult export(MallOrderBack mallOrderBack) { LoginUser loginUser = SecurityUtils.getLoginUser(); MallShopShop mallShopShop = shopShopService.selectMallShopShopBySysUserId(loginUser.getUserId()); if (ObjectUtils.isNotEmpty(mallShopShop)){ mallOrderBack.setShopId(mallShopShop.getShopId()); } List list = mallOrderBackService.selectMallOrderBackList(mallOrderBack); ExcelUtil util = new ExcelUtil(MallOrderBack.class); return util.exportExcel(list, "退款单数据"); } /** * 获取退款单详细信息 */ @PreAuthorize("@ss.hasPermi('mall:mallOrderBack:query')") @GetMapping(value = "/{id}") public AjaxResult getInfo(@PathVariable("id") Long id) { return AjaxResult.success(mallOrderBackService.selectMallOrderBackById(id)); } /** * 新增退款单 */ @PreAuthorize("@ss.hasPermi('mall:mallOrderBack:add')") @Log(title = "退款单", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@RequestBody MallOrderBack mallOrderBack) { return toAjax(mallOrderBackService.insertMallOrderBack(mallOrderBack)); } /** * 修改退款单 */ @PreAuthorize("@ss.hasPermi('mall:mallOrderBack:edit')") @Log(title = "退款单", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@RequestBody MallOrderBack mallOrderBack) { if ("1".equals(mallOrderBack.getStatus())){ return refundAgree(mallOrderBack); } if ("3".equals(mallOrderBack.getStatus())){ mallOrderBackService.updateMallOrderBack(mallOrderBack); return AjaxResult.success("操作完成"); } return AjaxResult.error("错误操作,只能同意或拒绝!"); } public AjaxResult refundAgree(MallOrderBack mallOrderBack) { MallOrderBack orderBack = mallOrderBackService.selectMallOrderBackById(mallOrderBack.getId()); if (orderBack == null) { return AjaxResult.error("退款信息异常"); } if (!"0".equals(orderBack.getStatus())) { return AjaxResult.error("只有待审核状态才能退款"); } MallOrderOrder orderOrder = orderOrderService.selectMallOrderOrderById(orderBack.getOrderId()); List orderList = orderOrderService.selectMallOrderOrderByTotalOrderSn(orderOrder.getTotalOrderSn()); BigDecimal totalPayment = BigDecimal.ZERO; for (MallOrderOrder order : orderList) { totalPayment = totalPayment.add(order.getPayment());//支付的时候按合同号这么支付的,这里金额也要这么对应 } if (orderOrder == null) { return AjaxResult.error("订单信息异常"); } SortedMap data = new TreeMap<>(); //退款到用户微信 String nonce_str = Md5Utils.getRandomStringByLength(32); data.put("nonce_str", nonce_str); //商户订单号 data.put("out_trade_no", orderOrder.getTotalOrderSn()); //商户退款单号,一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号 data.put("out_refund_no", orderBack.getId().toString());//分批退款,退款单号不能相同,取退款单主键刚好 int total_fee = Math.round(Float.valueOf(orderBack.getPrice().multiply(new BigDecimal(100)).toString())); //支付金额,微信支付提交的金额是不能带小数点的,且是以分为单位,这边需要转成字符串类型,否则后面的签名会失败 data.put("total_fee", String.valueOf(totalPayment.multiply(new BigDecimal("100")).intValue())); //退款总金额,单位为分,只能为整数 data.put("refund_fee", String.valueOf(Math.round(total_fee))); String str = XiaochengxuPayService.wxXcxRefund(data); if (str.length() > 0) { return AjaxResult.error(str); } // 查询该订单所有退款单中,所有的退款金额相加 List mallOrderBacks = mallOrderBackService.selectMallOrderBackByOrderId(orderOrder.getId()); BigDecimal totalRefund = BigDecimal.ZERO; for (MallOrderBack item : mallOrderBacks){ if ("1".equals(item.getStatus())){//只计算退款成功的 totalRefund = totalRefund.add(item.getPrice()); } }; //订单商品明细列表(用于计算退款后的提成变化) List list = orderGoodsService.selectMallOrderGoodsByOrderId(orderOrder.getId()); BigDecimal currentCommission = BigDecimal.ZERO;//退款部分提成 for (MallOrderGoodsVO mallOrderGoodsVO : list) { if ("1".equals(mallOrderGoodsVO.getReturnStatus())){ //退货数量【由于每次是累加的,所以计算出订单的剩余提成就行】 BigDecimal num = new BigDecimal(mallOrderGoodsVO.getTotal() - mallOrderGoodsVO.getReturnTotal()); currentCommission = currentCommission.add(mallOrderGoodsVO.getCommission().multiply(num)); } } //订单支付金额-退款单已退款金额 orderOrder.setReturnablePrice(orderOrder.getPayment().subtract(totalRefund));//todo 1待测试优惠券情况-支付金额减还可以吗 2上面的微信退款接口还可能微信支付金额不一样 // 如果没有全部退款, 订单状态恢复待发货 (该退款单和剩余可退款金额比较) System.out.println("退款金额:" + orderBack.getPrice() + " 剩余可退款金额:" + orderOrder.getReturnablePrice()); if (orderBack.getPrice().compareTo(orderOrder.getReturnablePrice()) < 0){ // 部分退款 → 恢复订单状态 System.out.println("状态改为待配送"); orderOrder.setStatus("1"); orderOrder.setOrderStatus("1"); orderOrder.setIsExamine("0"); //订单除去退款部分后的提成 orderOrder.setCommissionPrice(currentCommission); }else { // 全额退款 → 关闭订单(根据业务需求) System.out.println("状态改为已退款"); orderOrder.setStatus("6"); // 例如:6 表示退货成功 orderOrder.setOrderStatus("10"); // 例如:10 表示退款成功 orderOrder.setCommissionPrice(BigDecimal.ZERO);//全额退款提成归零 //审核状态已经是1了 } System.out.println(orderOrder); orderOrderService.updateMallOrderOrder(orderOrder); //更新业务员业绩 MallSalesmanAchievement mallSalesmanAchievement = mallSalesmanAchievementMapper.selectMallSalesmanAchievementByOrderId(orderOrder.getId()); if (mallSalesmanAchievement != null){ mallSalesmanAchievement.setMoney(orderOrder.getCommissionPrice()); mallSalesmanAchievementMapper.updateMallSalesmanAchievement(mallSalesmanAchievement); } mallOrderBack.setStatus("1");//该退款单状态改为退款成功 mallOrderBackService.updateMallOrderBack(mallOrderBack); return AjaxResult.success("退款成功"); } /** * 删除退款单 */ @PreAuthorize("@ss.hasPermi('mall:mallOrderBack:remove')") @Log(title = "退款单", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") public AjaxResult remove(@PathVariable Long[] ids) { return toAjax(mallOrderBackService.deleteMallOrderBackByIds(ids)); } @PostMapping("/handleRefund") public ApiResult handleRefund(@RequestBody Map params) { if (!params.containsKey("refundId")||StringUtils.isEmpty(params.get("refundId").toString())){ return ApiResult.error("缺少参数"); } Boolean isAccept = orderOrderService.refundStatusRoute(Integer.parseInt("1"),params.get("refundId").toString()); if (isAccept == true) { int status = mallOrderBackService.handleRefund(params); return status > 0 ? ApiResult.ok("操作成功") : ApiResult.error("操作失败"); }else { return ApiResult.error("订单异常"); } } }