增加pc端显示售后纠纷处理
This commit is contained in:
parent
a64f1728ac
commit
c55ac047c0
|
|
@ -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 +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -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<AfterServiceRecord> afterServiceRecordList = afterServiceRecordService.selectAfterServiceRecordList(afterServiceRecord);
|
||||
|
||||
// 踢重后的子单ids
|
||||
List<Long> 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<OrderDetail> 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<OrderDetail> orderDetailList = orderDetailService.selectOrderDetailList(orderDetail);
|
||||
|
||||
if (orderDetailList.isEmpty()) {
|
||||
logger.info("主单[{}]没有子单", orderMaster.getId());
|
||||
return AjaxResult.success(new ArrayList<>());
|
||||
}
|
||||
|
||||
// 获取所有子单ID
|
||||
List<Long> 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<AfterServiceRecord> disputeRecords = afterServiceRecordService.selectAfterServiceRecordList(queryRecord);
|
||||
|
||||
logger.info("主单[{}]的子单IDs: {},找到{}条售后纠纷记录", orderMaster.getId(), orderDetailIds, disputeRecords.size());
|
||||
|
||||
// 为每个售后记录添加子单信息
|
||||
Map<Long, OrderDetail> 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());
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@
|
|||
</a>
|
||||
<a class="btn btn-default btn-outline" onclick="selectConditionBtn(this, {orderStatusName : '售后纠纷', orderStatus: -1})">
|
||||
售后纠纷
|
||||
(<span>0</span>)
|
||||
(<span id="afterServiceDisputeNum">0</span>)
|
||||
</a>
|
||||
</div>
|
||||
<div class="flex-board">
|
||||
|
|
@ -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('<a class="btn btn-success btn-xs " href="javascript:void(0)" onclick="pcOrderInsurance(\'' + row.id + '\')"></i>选择保险</a> ');
|
||||
}
|
||||
// 售后纠纷处理按钮
|
||||
if (row.afterServiceStatus == 1) {
|
||||
actions.push('<a class="btn btn-warning btn-xs" href="javascript:void(0)" onclick="handleAfterServiceDispute(\'' + row.id + '\')"><i class="fa fa-gavel"></i>售后纠纷处理</a> ');
|
||||
}
|
||||
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 = '<div class="modal fade" id="afterServiceDisputeModal" tabindex="-1" role="dialog">';
|
||||
html += '<div class="modal-dialog modal-lg" role="document">';
|
||||
html += '<div class="modal-content">';
|
||||
html += '<div class="modal-header">';
|
||||
html += '<h4 class="modal-title">售后纠纷处理</h4>';
|
||||
html += '<button type="button" class="close" data-dismiss="modal">×</button>';
|
||||
html += '</div>';
|
||||
html += '<div class="modal-body">';
|
||||
|
||||
if (afterServiceRecords && afterServiceRecords.length > 0) {
|
||||
html += '<div class="table-responsive">';
|
||||
html += '<table class="table table-bordered table-striped">';
|
||||
html += '<thead><tr><th>子单号</th><th>售后类型</th><th>申请原因</th><th>申请金额</th><th>师傅反馈</th><th>客户确认</th><th>操作</th></tr></thead>';
|
||||
html += '<tbody>';
|
||||
|
||||
afterServiceRecords.forEach(function(record) {
|
||||
html += '<tr>';
|
||||
html += '<td>' + (record.orderDetailCode || '') + '</td>';
|
||||
html += '<td>' + getAfterServiceTypeText(record.afterServiceType) + '</td>';
|
||||
html += '<td>' + (record.customerReason || '') + '</td>';
|
||||
html += '<td>¥' + (record.refund || 0) + '</td>';
|
||||
html += '<td>' + getWorkerFeedbackText(record.workerFeedbackResult) + '</td>';
|
||||
html += '<td>' + getCustomerCheckText(record.customerFinalCheck) + '</td>';
|
||||
html += '<td>';
|
||||
html += '<div class="input-group" style="width: 200px;">';
|
||||
html += '<input type="number" class="form-control" id="refundAmount_' + record.id + '" placeholder="退款金额" value="' + (record.refund || 0) + '" min="0" step="0.01">';
|
||||
html += '<div class="input-group-append">';
|
||||
html += '<button class="btn btn-primary btn-sm" onclick="processRefund(\'' + record.id + '\', \'' + orderMasterId + '\')">处理退款</button>';
|
||||
html += '</div></div>';
|
||||
html += '</td>';
|
||||
html += '</tr>';
|
||||
});
|
||||
|
||||
html += '</tbody></table></div>';
|
||||
} else {
|
||||
html += '<div class="alert alert-info">该订单暂无售后纠纷记录</div>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
html += '<div class="modal-footer">';
|
||||
html += '<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>';
|
||||
html += '</div>';
|
||||
html += '</div></div></div>';
|
||||
|
||||
// 移除已存在的弹窗
|
||||
$('#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 '未确认';
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
<script id="importTpl" type="text/template">
|
||||
|
|
|
|||
|
|
@ -173,6 +173,12 @@ public class AfterServiceRecord extends BaseEntity
|
|||
@Excel(name = "客户不同意理由")
|
||||
private String customerDisagreeReason;
|
||||
|
||||
/** 子单号(用于显示,非数据库字段) */
|
||||
private String orderDetailCode;
|
||||
|
||||
/** 子单ID列表(用于IN查询,非数据库字段) */
|
||||
private String orderDetailIds;
|
||||
|
||||
private boolean excludeAfterServiceFinished;
|
||||
|
||||
private List<AfterServiceImgs> imgsList;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@
|
|||
<if test="customerReasonType != null "> and customer_reason_type = #{customerReasonType}</if>
|
||||
<if test="customerReason != null and customerReason != ''"> and customer_reason = #{customerReason}</if>
|
||||
<if test="orderDetailId != null "> and order_detail_id = #{orderDetailId}</if>
|
||||
<if test="orderDetailIds != null and orderDetailIds != ''"> and order_detail_id in (${orderDetailIds})</if>
|
||||
<if test="operType != null "> and oper_type = #{operType}</if>
|
||||
<if test="workerFeedbackResult != null "> and worker_feedback_result = #{workerFeedbackResult}</if>
|
||||
<if test="workerFeedbackReasonType != null "> and worker_feedback_reason_type = #{workerFeedbackReasonType}</if>
|
||||
|
|
|
|||
|
|
@ -136,8 +136,8 @@
|
|||
return_reason,
|
||||
return_reason_detail,
|
||||
return_images,
|
||||
worker_remark
|
||||
|
||||
worker_remark,
|
||||
after_service_status
|
||||
FROM order_master
|
||||
</sql>
|
||||
<sql id="selectOrderMasterMoreInfo">
|
||||
|
|
@ -203,7 +203,8 @@
|
|||
om.return_reason,
|
||||
om.return_reason_detail,
|
||||
om.return_images,
|
||||
om.worker_remark
|
||||
om.worker_remark,
|
||||
om.after_service_status
|
||||
FROM order_master om
|
||||
LEFT JOIN customer_address ca ON ca.customer_address_id = om.address_id
|
||||
LEFT JOIN goods g ON g.goods_id = om.goods_id
|
||||
|
|
|
|||
Loading…
Reference in New Issue