diff --git a/ghy-admin/src/main/java/com/ghy/web/controller/order/AfterServiceDisputeRequest.java b/ghy-admin/src/main/java/com/ghy/web/controller/order/AfterServiceDisputeRequest.java new file mode 100644 index 00000000..22a06eed --- /dev/null +++ b/ghy-admin/src/main/java/com/ghy/web/controller/order/AfterServiceDisputeRequest.java @@ -0,0 +1,60 @@ +package com.ghy.web.controller.order; + +import java.math.BigDecimal; + +/** + * 售后纠纷处理请求 + * + * @author system + * @date 2024-12-19 + */ +public class AfterServiceDisputeRequest { + + /** + * 售后记录ID + */ + private String recordId; + + /** + * 主单ID + */ + private Long orderMasterId; + + /** + * 退款金额 + */ + private BigDecimal refundAmount; + + public String getRecordId() { + return recordId; + } + + public void setRecordId(String recordId) { + this.recordId = recordId; + } + + public Long getOrderMasterId() { + return orderMasterId; + } + + public void setOrderMasterId(Long orderMasterId) { + this.orderMasterId = orderMasterId; + } + + public BigDecimal getRefundAmount() { + return refundAmount; + } + + public void setRefundAmount(BigDecimal refundAmount) { + this.refundAmount = refundAmount; + } + + @Override + public String toString() { + return "AfterServiceDisputeRequest{" + + "recordId='" + recordId + '\'' + + ", orderMasterId=" + orderMasterId + + ", refundAmount=" + refundAmount + + '}'; + } +} diff --git a/ghy-admin/src/main/java/com/ghy/web/controller/order/OrderMasterController.java b/ghy-admin/src/main/java/com/ghy/web/controller/order/OrderMasterController.java index 3264ff40..136cd468 100644 --- a/ghy-admin/src/main/java/com/ghy/web/controller/order/OrderMasterController.java +++ b/ghy-admin/src/main/java/com/ghy/web/controller/order/OrderMasterController.java @@ -22,6 +22,7 @@ import com.ghy.order.request.SysOrderAssignRequest; import com.ghy.order.request.SysOrderGoodsStandards; import com.ghy.order.request.TransferOrderRequest; import com.ghy.order.service.*; +import com.ghy.web.controller.order.AfterServiceDisputeRequest; import com.ghy.payment.domain.FinancialChangeRecord; import com.ghy.payment.domain.FinancialDetail; import com.ghy.payment.domain.FinancialMaster; @@ -1430,6 +1431,157 @@ public class OrderMasterController extends BaseController { return AjaxResult.success(orderMasterService.countOrderMasterList(orderMaster)); } + @PostMapping("/after/dispute/count") + @ResponseBody + public AjaxResult countAfterDisputeList(@RequestBody OrderMaster orderMaster) { + // 查所有售后纠纷的单 + AfterServiceRecord afterServiceRecord = new AfterServiceRecord(); + afterServiceRecord.setExcludeAfterServiceFinished(Boolean.TRUE); + // 只查询售后纠纷的记录(客户不同意的记录) + afterServiceRecord.setCustomerFinalCheck(0L); // 客户不同意 + List afterServiceRecordList = afterServiceRecordService.selectAfterServiceRecordList(afterServiceRecord); + + // 踢重后的子单ids + List detailIds = afterServiceRecordList.stream().map(AfterServiceRecord::getOrderDetailId).distinct().collect(Collectors.toList()); + StringBuilder orderDetailIds = new StringBuilder(); + OrderDetail orderDetail = new OrderDetail(); + orderDetail.setCustomerId(orderMaster.getCustomerId()); + orderDetail.setDeptId(orderMaster.getDeptId()); + detailIds.forEach(id -> { + orderDetailIds.append(id).append(","); + }); + String ids = orderDetailIds.toString(); + if (StringUtils.isNotEmpty(ids)) { + orderDetail.setOrderDetailIds(ids.substring(0, ids.length() - 1)); + } else { + orderDetail.setOrderDetailIds("0"); + } + + // 所有售后纠纷的子单 + List orderDetailList = orderDetailService.selectOrderDetailList(orderDetail); + StringBuilder orderMasterIds = new StringBuilder(); + orderDetailList.stream().map(OrderDetail::getOrderMasterId).distinct() + .collect(Collectors.toList()).forEach(id -> { + orderMasterIds.append(id).append(","); + }); + String orderIds = orderMasterIds.toString(); + if (StringUtils.isNotEmpty(orderIds)) { + orderMaster.setOrderMasterIds(orderIds.substring(0, orderIds.length() - 1)); + } else { + orderMaster.setOrderMasterIds("0"); + } + + return AjaxResult.success(orderMasterService.countOrderMasterList(orderMaster)); + } + + @PostMapping("/after/records/byMasterId") + @ResponseBody + public AjaxResult getAfterServiceRecordsByMasterId(@RequestBody OrderMaster orderMaster) { + try { + logger.info("查询主单[{}]的售后纠纷记录", orderMaster.getId()); + + // 查询主单下的所有子单 + OrderDetail orderDetail = new OrderDetail(); + orderDetail.setOrderMasterId(orderMaster.getId()); + List orderDetailList = orderDetailService.selectOrderDetailList(orderDetail); + + if (orderDetailList.isEmpty()) { + logger.info("主单[{}]没有子单", orderMaster.getId()); + return AjaxResult.success(new ArrayList<>()); + } + + // 获取所有子单ID + List orderDetailIds = orderDetailList.stream() + .map(OrderDetail::getId) + .collect(Collectors.toList()); + + logger.info("主单[{}]的子单IDs: {}", orderMaster.getId(), orderDetailIds); + + // 使用IN查询一次性获取所有售后纠纷记录 + AfterServiceRecord queryRecord = new AfterServiceRecord(); + queryRecord.setCustomerFinalCheck(0L); // 客户不同意 + queryRecord.setExcludeAfterServiceFinished(Boolean.TRUE); // 排除已完成的售后 + + // 构建子单ID的IN查询条件 + StringBuilder orderDetailIdsStr = new StringBuilder(); + for (int i = 0; i < orderDetailIds.size(); i++) { + if (i > 0) { + orderDetailIdsStr.append(","); + } + orderDetailIdsStr.append(orderDetailIds.get(i)); + } + + // 设置子单ID列表用于IN查询 + queryRecord.setOrderDetailIds(orderDetailIdsStr.toString()); + + List disputeRecords = afterServiceRecordService.selectAfterServiceRecordList(queryRecord); + + logger.info("主单[{}]的子单IDs: {},找到{}条售后纠纷记录", orderMaster.getId(), orderDetailIds, disputeRecords.size()); + + // 为每个售后记录添加子单信息 + Map orderDetailMap = orderDetailList.stream() + .collect(Collectors.toMap(OrderDetail::getId, detail -> detail)); + + disputeRecords.forEach(record -> { + OrderDetail detail = orderDetailMap.get(record.getOrderDetailId()); + if (detail != null) { + record.setOrderDetailCode(detail.getCode()); + logger.info("售后记录[{}]属于子单[{}]", record.getId(), detail.getCode()); + } else { + logger.warn("售后记录[{}]的子单ID[{}]在子单列表中未找到", record.getId(), record.getOrderDetailId()); + } + }); + + logger.info("主单[{}]总共找到{}条售后纠纷记录", orderMaster.getId(), disputeRecords.size()); + return AjaxResult.success(disputeRecords); + + } catch (Exception e) { + logger.error("查询主单[{}]售后纠纷记录异常", orderMaster.getId(), e); + return AjaxResult.error("查询售后纠纷记录失败:" + e.getMessage()); + } + } + + @PostMapping("/after/dispute/handle") + @ResponseBody + public AjaxResult handleAfterServiceDispute(@RequestBody AfterServiceDisputeRequest request) { + try { + logger.info("处理售后纠纷退款,记录ID:{},退款金额:{}", request.getRecordId(), request.getRefundAmount()); + + // 查询售后记录 + AfterServiceRecord record = afterServiceRecordService.selectAfterServiceRecordById(request.getRecordId()); + if (record == null) { + return AjaxResult.error("售后记录不存在"); + } + + // 验证是否为售后纠纷(客户不同意) + if (record.getCustomerFinalCheck() == null || !record.getCustomerFinalCheck().equals(0L)) { + return AjaxResult.error("该记录不是售后纠纷,无法处理"); + } + + // 设置退款金额 + record.setRefund(request.getRefundAmount()); + record.setAgreedRefund(request.getRefundAmount()); + record.setRefundApplyTime(new Date()); + + // 更新售后记录 + afterServiceRecordService.updateAfterServiceRecord(record); + + // 执行退款逻辑 + try { + afterServiceRecordService.executeRefundLogic(record); + logger.info("售后纠纷退款处理成功,记录ID:{},退款金额:{}", request.getRecordId(), request.getRefundAmount()); + return AjaxResult.success("退款处理成功"); + } catch (Exception e) { + logger.error("售后纠纷退款执行失败,记录ID:{},错误:{}", request.getRecordId(), e.getMessage()); + return AjaxResult.error("退款执行失败:" + e.getMessage()); + } + + } catch (Exception e) { + logger.error("处理售后纠纷异常,记录ID:{}", request.getRecordId(), e); + return AjaxResult.error("处理售后纠纷失败:" + e.getMessage()); + } + } + @PostMapping("/app/detail") @ResponseBody public AjaxResult appDetail(@RequestBody OrderMaster request) { @@ -1802,6 +1954,12 @@ public class OrderMasterController extends BaseController { if(StringUtils.isNotEmpty(orderMaster.getOrderStatusName())){ master.setOrderStatusName(orderMaster.getOrderStatusName()); } + + // 如果数据库中的afterServiceStatus为null,则设置为0(无售后) + if (master.getAfterServiceStatus() == null) { + master.setAfterServiceStatus(0); + } + FinancialMaster fm = financialMasterMap.get(master.getId()); if (fm != null) { master.setFinancialMasterMoney(fm.getPayMoney()); diff --git a/ghy-admin/src/main/resources/templates/order/orderManager.html b/ghy-admin/src/main/resources/templates/order/orderManager.html index 396bc620..e4bddc3e 100644 --- a/ghy-admin/src/main/resources/templates/order/orderManager.html +++ b/ghy-admin/src/main/resources/templates/order/orderManager.html @@ -165,7 +165,7 @@ 售后纠纷 - (0) + (0)
@@ -573,6 +573,22 @@ } } }) + + + $.ajax({ + type: "POST", + dataType:"json", + url: prefix + '/after/dispute/count', + contentType: 'application/json', + data: JSON.stringify({}), + success: function (result) { + if (result.code == web_status.SUCCESS) { + $('#afterServiceDisputeNum').text(result.data); + } else { + $.modal.msgError("售后纠纷数据加载错误,请重试!") + } + } + }) }); function changeOrderMode(orderMode) { @@ -757,6 +773,10 @@ } else { actions.push('选择保险 '); } + // 售后纠纷处理按钮 + if (row.afterServiceStatus == 1) { + actions.push('售后纠纷处理 '); + } return actions.join(''); } }, @@ -1212,6 +1232,148 @@ // 设置定时器,每隔一分钟执行一次 fetchData 函数 setInterval(fetchData, 60000); + // 售后纠纷处理弹窗 + function handleAfterServiceDispute(orderMasterId) { + // 查询该主单的售后记录 + $.ajax({ + type: "POST", + dataType: "json", + url: prefix + '/after/records/byMasterId', + contentType: 'application/json', + data: JSON.stringify({id: orderMasterId}), + success: function (result) { + if (result.code == web_status.SUCCESS) { + showAfterServiceDisputeModal(orderMasterId, result.data); + } else { + $.modal.msgError("查询售后记录失败:" + result.msg); + } + }, + error: function() { + $.modal.msgError("查询售后记录失败,请重试!"); + } + }); + } + + // 显示售后纠纷处理弹窗 + function showAfterServiceDisputeModal(orderMasterId, afterServiceRecords) { + var html = ''; + + // 移除已存在的弹窗 + $('#afterServiceDisputeModal').remove(); + + // 添加弹窗到页面 + $('body').append(html); + + // 显示弹窗 + $('#afterServiceDisputeModal').modal('show'); + } + + // 处理退款 + function processRefund(recordId, orderMasterId) { + var refundAmount = $('#refundAmount_' + recordId).val(); + if (!refundAmount || refundAmount <= 0) { + $.modal.msgError("请输入有效的退款金额"); + return; + } + + $.modal.confirm("确认处理退款 ¥" + refundAmount + " 吗?", function() { + $.ajax({ + type: "POST", + dataType: "json", + url: prefix + '/after/dispute/handle', + contentType: 'application/json', + data: JSON.stringify({ + recordId: recordId, + orderMasterId: orderMasterId, + refundAmount: parseFloat(refundAmount) + }), + success: function (result) { + if (result.code == web_status.SUCCESS) { + $.modal.msgSuccess("退款处理成功"); + $('#afterServiceDisputeModal').modal('hide'); + // 刷新页面数据 + $.table.refresh(); + } else { + $.modal.msgError("退款处理失败:" + result.msg); + } + }, + error: function() { + $.modal.msgError("退款处理失败,请重试!"); + } + }); + }); + } + + // 获取售后类型文本 + function getAfterServiceTypeText(type) { + var types = { + 1: '未收到货退单退款', + 2: '未收到货退款', + 3: '已收到货退款退货' + }; + return types[type] || '未知'; + } + + // 获取师傅反馈文本 + function getWorkerFeedbackText(result) { + var results = { + 0: '拒绝', + 1: '同意', + 2: '上门补做/重做', + 3: '重做/补做完成' + }; + return results[result] || '未处理'; + } + + // 获取客户确认文本 + function getCustomerCheckText(check) { + if (check === 1) return '同意'; + if (check === 0) return '不同意'; + return '未确认'; + } +