接入清分和订单异常待办

This commit is contained in:
jsowell
2026-07-22 17:03:24 +08:00
parent 8941596264
commit de395326a1
16 changed files with 674 additions and 15 deletions

View File

@@ -0,0 +1,15 @@
package com.jsowell.pile.constant;
/**
* 汇付清分异常待办常量。
*/
public final class AdapayClearingTodoConstants {
public static final String TASK_TYPE = "CLEARING_EXCEPTION";
public static final String BUSINESS_TYPE = "ADAPAY_UNSPLIT_RECORD";
public static final String ROUTE_NAME = "financeDetail";
public static final String HANDLE_FLAG_FAILED = "FAILED";
public static final String HANDLE_FLAG_SUCCESS = "SUCCESS";
private AdapayClearingTodoConstants() {
}
}

View File

@@ -0,0 +1,13 @@
package com.jsowell.pile.constant;
/**
* 订单异常待办常量。
*/
public final class OrderAbnormalTodoConstants {
public static final String TASK_TYPE = "ORDER_ABNORMAL";
public static final String BUSINESS_TYPE = "ORDER_ABNORMAL_RECORD";
public static final String ROUTE_NAME = "AbnormalRecord";
private OrderAbnormalTodoConstants() {
}
}

View File

@@ -0,0 +1,10 @@
package com.jsowell.pile.service;
import com.jsowell.pile.domain.AdapayUnsplitRecord;
/**
* 汇付清分状态与待办联动服务。
*/
public interface AdapayClearingTodoService {
void syncUnsplitRecordTodo(AdapayUnsplitRecord record);
}

View File

@@ -49,7 +49,7 @@ public interface OrderAbnormalRecordService {
* @param ids 需要删除的订单异常记录主键集合
* @return 结果
*/
public int deleteOrderAbnormalRecordByIds(Integer[] ids);
public int deleteOrderAbnormalRecordByIds(Integer[] ids, String operatorName);
/**
* 删除订单异常记录信息
@@ -57,5 +57,5 @@ public interface OrderAbnormalRecordService {
* @param id 订单异常记录主键
* @return 结果
*/
public int deleteOrderAbnormalRecordById(Integer id);
public int deleteOrderAbnormalRecordById(Integer id, String operatorName);
}

View File

@@ -0,0 +1,159 @@
package com.jsowell.pile.service.impl;
import com.alibaba.fastjson2.JSON;
import com.jsowell.common.util.StringUtils;
import com.jsowell.pile.constant.AdapayClearingTodoConstants;
import com.jsowell.pile.domain.AdapayUnsplitRecord;
import com.jsowell.pile.domain.OrderBasicInfo;
import com.jsowell.pile.domain.PileMerchantInfo;
import com.jsowell.pile.service.AdapayClearingTodoService;
import com.jsowell.pile.service.OrderBasicInfoService;
import com.jsowell.pile.service.PileMerchantInfoService;
import com.jsowell.system.constant.TodoTaskConstants;
import com.jsowell.system.domain.dto.TodoTaskCreateCommand;
import com.jsowell.system.service.TodoTaskAssigneeService;
import com.jsowell.system.service.TodoTaskService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 汇付清分失败状态与待办联动服务实现。
*/
@Service
public class AdapayClearingTodoServiceImpl implements AdapayClearingTodoService {
private static final Logger log = LoggerFactory.getLogger(AdapayClearingTodoServiceImpl.class);
private static final String TODO_OPERATOR = "adapay-clearing";
@Autowired
private OrderBasicInfoService orderBasicInfoService;
@Autowired
private PileMerchantInfoService pileMerchantInfoService;
@Autowired
private TodoTaskAssigneeService todoTaskAssigneeService;
@Autowired
private TodoTaskService todoTaskService;
@Override
@Transactional(rollbackFor = Exception.class)
public void syncUnsplitRecordTodo(AdapayUnsplitRecord record) {
if (record == null || StringUtils.isBlank(record.getPaymentId())) {
return;
}
boolean failed = AdapayClearingTodoConstants.HANDLE_FLAG_FAILED.equals(record.getRefundFlag())
|| AdapayClearingTodoConstants.HANDLE_FLAG_FAILED.equals(record.getSplitFlag());
boolean succeeded = AdapayClearingTodoConstants.HANDLE_FLAG_SUCCESS.equals(record.getRefundFlag())
&& AdapayClearingTodoConstants.HANDLE_FLAG_SUCCESS.equals(record.getSplitFlag());
if (!failed && !succeeded) {
return;
}
String paymentId = record.getPaymentId().trim();
if (succeeded) {
todoTaskService.completeByBusinessAsSystem(AdapayClearingTodoConstants.BUSINESS_TYPE,
paymentId, null, TODO_OPERATOR);
return;
}
createClearingExceptionTodos(record, paymentId);
}
private void createClearingExceptionTodos(AdapayUnsplitRecord record, String paymentId) {
if (StringUtils.isBlank(record.getOrderCode())) {
log.warn("清分失败记录缺少订单号无法创建待办paymentId={}", paymentId);
return;
}
OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(record.getOrderCode());
if (orderInfo == null || StringUtils.isBlank(orderInfo.getMerchantId())) {
log.warn("清分失败记录未找到订单运营商无法创建待办paymentId={}, orderCode={}",
paymentId, record.getOrderCode());
return;
}
PileMerchantInfo merchantInfo;
try {
merchantInfo = pileMerchantInfoService.selectPileMerchantInfoById(
Long.parseLong(orderInfo.getMerchantId()));
} catch (NumberFormatException exception) {
log.warn("清分失败记录运营商 ID 非法无法创建待办paymentId={}, merchantId={}",
paymentId, orderInfo.getMerchantId());
return;
}
if (merchantInfo == null || StringUtils.isBlank(merchantInfo.getDeptId())) {
log.warn("清分失败记录运营商未配置部门无法创建待办paymentId={}, merchantId={}",
paymentId, orderInfo.getMerchantId());
return;
}
Long deptId;
try {
deptId = Long.parseLong(merchantInfo.getDeptId());
} catch (NumberFormatException exception) {
log.warn("清分失败记录运营商部门 ID 非法无法创建待办paymentId={}, deptId={}",
paymentId, merchantInfo.getDeptId());
return;
}
List<Long> assigneeUserIds = todoTaskAssigneeService.findActiveOperatorAdminUserIdsByDeptTree(deptId);
if (CollectionUtils.isEmpty(assigneeUserIds)) {
log.warn("清分失败记录运营商部门下没有正常管理员无法创建待办paymentId={}, deptId={}",
paymentId, deptId);
return;
}
String summary = buildSummary(record);
String content = "退款处理状态:" + displayFlag(record.getRefundFlag())
+ ",分账处理状态:" + displayFlag(record.getSplitFlag());
for (Long assigneeUserId : assigneeUserIds) {
todoTaskService.createTask(TodoTaskCreateCommand.builder()
.taskType(AdapayClearingTodoConstants.TASK_TYPE)
.title("清分异常待处理")
.summary(summary)
.content(content)
.businessType(AdapayClearingTodoConstants.BUSINESS_TYPE)
.businessId(paymentId)
.routeName(AdapayClearingTodoConstants.ROUTE_NAME)
.routeParams(buildRouteParams(record, orderInfo.getMerchantId()))
.assigneeUserId(assigneeUserId)
.assigneeMerchantId(orderInfo.getMerchantId())
.priority(TodoTaskConstants.PRIORITY_IMPORTANT)
.idempotentKey(AdapayClearingTodoConstants.TASK_TYPE + ":"
+ AdapayClearingTodoConstants.BUSINESS_TYPE + ":" + paymentId + ":" + assigneeUserId)
.createBy(TODO_OPERATOR)
.build());
}
}
private String buildSummary(AdapayUnsplitRecord record) {
String summary = "订单清分或退款处理失败,需要人工核对,订单号:" + record.getOrderCode().trim();
if (AdapayClearingTodoConstants.HANDLE_FLAG_FAILED.equals(record.getRefundFlag())) {
summary += ",退款状态失败";
}
if (AdapayClearingTodoConstants.HANDLE_FLAG_FAILED.equals(record.getSplitFlag())) {
summary += ",分账状态失败";
}
return summary.length() <= 500 ? summary : summary.substring(0, 500);
}
private String buildRouteParams(AdapayUnsplitRecord record, String merchantId) {
Map<String, Object> query = new HashMap<>();
query.put("merchantId", merchantId);
query.put("orderCode", record.getOrderCode());
query.put("paymentId", record.getPaymentId());
Map<String, Object> routeParams = new HashMap<>();
routeParams.put("query", query);
return JSON.toJSONString(routeParams);
}
private String displayFlag(String flag) {
return StringUtils.isBlank(flag) ? "未确认" : flag;
}
}

View File

@@ -1,12 +1,29 @@
package com.jsowell.pile.service.impl;
import com.alibaba.fastjson2.JSON;
import com.jsowell.common.util.StringUtils;
import com.jsowell.pile.constant.OrderAbnormalTodoConstants;
import com.jsowell.pile.domain.OrderAbnormalRecord;
import com.jsowell.pile.domain.PileMerchantInfo;
import com.jsowell.pile.mapper.OrderAbnormalRecordMapper;
import com.jsowell.pile.service.OrderAbnormalRecordService;
import com.jsowell.pile.service.PileBasicInfoService;
import com.jsowell.pile.service.PileMerchantInfoService;
import com.jsowell.pile.vo.base.PileInfoVO;
import com.jsowell.system.constant.TodoTaskConstants;
import com.jsowell.system.domain.dto.TodoTaskCreateCommand;
import com.jsowell.system.service.TodoTaskAssigneeService;
import com.jsowell.system.service.TodoTaskService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 订单异常记录Service业务层处理
@@ -16,9 +33,25 @@ import java.util.List;
*/
@Service
public class OrderAbnormalRecordServiceImpl implements OrderAbnormalRecordService {
private static final Logger log = LoggerFactory.getLogger(OrderAbnormalRecordServiceImpl.class);
private static final String TODO_OPERATOR = "order-abnormal-system";
private static final String CANCEL_REASON = "订单异常记录已关闭";
@Autowired
private OrderAbnormalRecordMapper orderAbnormalRecordMapper;
@Autowired
private PileBasicInfoService pileBasicInfoService;
@Autowired
private PileMerchantInfoService pileMerchantInfoService;
@Autowired
private TodoTaskAssigneeService todoTaskAssigneeService;
@Autowired
private TodoTaskService todoTaskService;
/**
* 查询订单异常记录
*
@@ -48,9 +81,13 @@ public class OrderAbnormalRecordServiceImpl implements OrderAbnormalRecordServic
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int insertOrderAbnormalRecord(OrderAbnormalRecord orderAbnormalRecord) {
// orderAbnormalRecord.setCreateTime(DateUtils.getNowDate());
return orderAbnormalRecordMapper.insertOrderAbnormalRecord(orderAbnormalRecord);
int rows = orderAbnormalRecordMapper.insertOrderAbnormalRecord(orderAbnormalRecord);
if (rows > 0) {
createOrderAbnormalTodo(orderAbnormalRecord);
}
return rows;
}
/**
@@ -71,8 +108,15 @@ public class OrderAbnormalRecordServiceImpl implements OrderAbnormalRecordServic
* @return 结果
*/
@Override
public int deleteOrderAbnormalRecordByIds(Integer[] ids) {
return orderAbnormalRecordMapper.deleteOrderAbnormalRecordByIds(ids);
@Transactional(rollbackFor = Exception.class)
public int deleteOrderAbnormalRecordByIds(Integer[] ids, String operatorName) {
int rows = orderAbnormalRecordMapper.deleteOrderAbnormalRecordByIds(ids);
if (rows > 0 && ids != null) {
for (Integer id : ids) {
cancelOrderAbnormalTodo(id, operatorName);
}
}
return rows;
}
/**
@@ -82,7 +126,123 @@ public class OrderAbnormalRecordServiceImpl implements OrderAbnormalRecordServic
* @return 结果
*/
@Override
public int deleteOrderAbnormalRecordById(Integer id) {
return orderAbnormalRecordMapper.deleteOrderAbnormalRecordById(id);
@Transactional(rollbackFor = Exception.class)
public int deleteOrderAbnormalRecordById(Integer id, String operatorName) {
int rows = orderAbnormalRecordMapper.deleteOrderAbnormalRecordById(id);
if (rows > 0) {
cancelOrderAbnormalTodo(id, operatorName);
}
return rows;
}
private void createOrderAbnormalTodo(OrderAbnormalRecord record) {
if (record == null || record.getId() == null || StringUtils.isBlank(record.getPileSn())) {
log.warn("订单异常记录缺少主键或桩号无法创建待办recordId={}, pileSn={}",
record == null ? null : record.getId(), record == null ? null : record.getPileSn());
return;
}
PileInfoVO pileInfo = pileBasicInfoService.selectPileInfoBySn(record.getPileSn());
if (pileInfo == null || StringUtils.isBlank(pileInfo.getMerchantId())) {
log.warn("订单异常记录未找到桩所属运营商无法创建待办recordId={}, pileSn={}",
record.getId(), record.getPileSn());
return;
}
Long merchantId;
try {
merchantId = Long.parseLong(pileInfo.getMerchantId());
} catch (NumberFormatException exception) {
log.warn("订单异常记录运营商 ID 非法无法创建待办recordId={}, merchantId={}",
record.getId(), pileInfo.getMerchantId());
return;
}
PileMerchantInfo merchantInfo = pileMerchantInfoService.selectPileMerchantInfoById(merchantId);
if (merchantInfo == null || StringUtils.isBlank(merchantInfo.getDeptId())) {
log.warn("订单异常记录运营商未配置部门无法创建待办recordId={}, merchantId={}",
record.getId(), pileInfo.getMerchantId());
return;
}
Long deptId;
try {
deptId = Long.parseLong(merchantInfo.getDeptId());
} catch (NumberFormatException exception) {
log.warn("订单异常记录运营商部门 ID 非法无法创建待办recordId={}, deptId={}",
record.getId(), merchantInfo.getDeptId());
return;
}
List<Long> assigneeUserIds = todoTaskAssigneeService.findActiveOperatorAdminUserIdsByDeptTree(deptId);
if (CollectionUtils.isEmpty(assigneeUserIds)) {
log.warn("订单异常记录运营商部门下没有正常管理员无法创建待办recordId={}, deptId={}",
record.getId(), deptId);
return;
}
String businessId = String.valueOf(record.getId());
String summary = buildSummary(record);
String content = StringUtils.isBlank(record.getStopReasonMsg())
? null : truncate(record.getStopReasonMsg(), 20000);
for (Long assigneeUserId : assigneeUserIds) {
todoTaskService.createTask(TodoTaskCreateCommand.builder()
.taskType(OrderAbnormalTodoConstants.TASK_TYPE)
.title("订单异常待处理")
.summary(summary)
.content(content)
.businessType(OrderAbnormalTodoConstants.BUSINESS_TYPE)
.businessId(businessId)
.routeName(OrderAbnormalTodoConstants.ROUTE_NAME)
.routeParams(buildRouteParams(record))
.assigneeUserId(assigneeUserId)
.assigneeMerchantId(pileInfo.getMerchantId())
.priority(TodoTaskConstants.PRIORITY_IMPORTANT)
.idempotentKey(OrderAbnormalTodoConstants.TASK_TYPE + ":"
+ OrderAbnormalTodoConstants.BUSINESS_TYPE + ":" + businessId + ":" + assigneeUserId)
.createBy(TODO_OPERATOR)
.build());
}
}
private void cancelOrderAbnormalTodo(Integer id, String operatorName) {
if (id == null) {
return;
}
todoTaskService.cancelByBusiness(OrderAbnormalTodoConstants.BUSINESS_TYPE, String.valueOf(id), null,
normalizeOperator(operatorName), CANCEL_REASON);
}
private String buildSummary(OrderAbnormalRecord record) {
String summary = "发现需要人工核对的异常充电订单";
if (StringUtils.isNotBlank(record.getOrderCode())) {
summary += ",交易流水号:" + record.getOrderCode().trim();
}
if (StringUtils.isNotBlank(record.getStopReasonMsg())) {
summary += ",停止原因:" + record.getStopReasonMsg().trim();
}
return truncate(summary, 500);
}
private String buildRouteParams(OrderAbnormalRecord record) {
Map<String, Object> query = new HashMap<>();
if (StringUtils.isNotBlank(record.getOrderCode())) {
query.put("orderCode", record.getOrderCode().trim());
}
if (StringUtils.isNotBlank(record.getPileSn())) {
query.put("pileSn", record.getPileSn().trim());
}
Map<String, Object> routeParams = new HashMap<>();
routeParams.put("query", query);
return JSON.toJSONString(routeParams);
}
private String truncate(String value, int maxLength) {
if (value == null || value.length() <= maxLength) {
return value;
}
return value.substring(0, maxLength);
}
private String normalizeOperator(String operatorName) {
return StringUtils.isBlank(operatorName) ? TODO_OPERATOR : operatorName.trim();
}
}

View File

@@ -3386,6 +3386,7 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService {
public void saveAbnormalOrder(TransactionRecordsData data) {
OrderAbnormalRecord record = new OrderAbnormalRecord();
BeanUtils.copyBeanProp(record, data);
record.setOrderCode(data.getTransactionCode());
orderAbnormalRecordService.insertOrderAbnormalRecord(record);
// 保存到订单主表

View File

@@ -2,10 +2,13 @@ package com.jsowell.web.controller.pile;
import com.jsowell.pile.domain.AdapayUnsplitRecord;
import com.jsowell.pile.mapper.AdapayUnsplitRecordMapper;
import com.jsowell.pile.service.AdapayClearingTodoService;
import com.jsowell.pile.service.AdapayUnsplitRecordService;
import com.jsowell.pile.vo.AdapayUnsplitRecordVO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.List;
@@ -15,6 +18,9 @@ public class AdapayUnsplitRecordServiceImpl implements AdapayUnsplitRecordServic
@Autowired
private AdapayUnsplitRecordMapper adapayUnsplitRecordMapper;
@Autowired
private AdapayClearingTodoService adapayClearingTodoService;
@Override
public int deleteByPrimaryKey(Integer id) {
return adapayUnsplitRecordMapper.deleteByPrimaryKey(id);
@@ -31,8 +37,15 @@ public class AdapayUnsplitRecordServiceImpl implements AdapayUnsplitRecordServic
}
@Override
@Transactional(rollbackFor = Exception.class)
public int insertOrUpdateSelective(AdapayUnsplitRecord record) {
return adapayUnsplitRecordMapper.insertOrUpdateSelective(record);
int rows = adapayUnsplitRecordMapper.insertOrUpdateSelective(record);
if (rows > 0 && record != null
&& (record.getRefundFlag() != null || record.getSplitFlag() != null)) {
AdapayUnsplitRecord currentRecord = loadCurrentRecord(record);
adapayClearingTodoService.syncUnsplitRecordTodo(currentRecord);
}
return rows;
}
@Override
@@ -98,4 +111,16 @@ public class AdapayUnsplitRecordServiceImpl implements AdapayUnsplitRecordServic
return adapayUnsplitRecordMapper.queryFailedList(startTime, endTime);
}
private AdapayUnsplitRecord loadCurrentRecord(AdapayUnsplitRecord record) {
if (record.getId() != null) {
return adapayUnsplitRecordMapper.selectByPrimaryKey(record.getId());
}
if (record.getPaymentId() == null) {
return record;
}
List<AdapayUnsplitRecord> records = adapayUnsplitRecordMapper.selectByPaymentIds(
Collections.singletonList(record.getPaymentId()));
return CollectionUtils.isEmpty(records) ? record : records.get(0);
}
}