|
|
@@ -1,21 +1,17 @@
|
|
|
package org.dromara.server.consume.business;
|
|
|
|
|
|
-import cn.hutool.core.bean.BeanUtil;
|
|
|
import cn.hutool.core.collection.CollectionUtil;
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
-import cn.hutool.core.thread.ThreadUtil;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
import cn.hutool.json.JSONUtil;
|
|
|
+import lombok.Data;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.dromara.backstage.api.domain.bo.RemoteSendMessageRecordBo;
|
|
|
import org.dromara.backstage.api.domain.vo.RemoteCardVo;
|
|
|
import org.dromara.backstage.api.domain.vo.RemoteMealTypeVo;
|
|
|
-import org.dromara.backstage.api.domain.vo.RemoteOperatorVo;
|
|
|
import org.dromara.backstage.api.domain.vo.RemoteUserAccountVo;
|
|
|
-import org.dromara.common.core.config.DefaultConfig;
|
|
|
import org.dromara.common.core.constant.ApiErrorTypeConstants;
|
|
|
-import org.dromara.common.core.constant.DefaultConstants;
|
|
|
import org.dromara.common.core.domain.R;
|
|
|
import org.dromara.common.core.domain.model.ErrorInfo;
|
|
|
import org.dromara.common.core.enums.ConsumeRecordTypeEnum;
|
|
|
@@ -37,10 +33,7 @@ import org.springframework.scheduling.annotation.Async;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import java.text.MessageFormat;
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
+import java.util.*;
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
|
/**
|
|
|
@@ -61,8 +54,6 @@ public class ConsumeBusiness {
|
|
|
private final ConsumeRequestCheck requestCheck;
|
|
|
private final ConsumeUploadCheck uploadCheck;
|
|
|
private final BaseBusiness baseBusiness;
|
|
|
- private final DefaultConfig defaultConfig;
|
|
|
-
|
|
|
|
|
|
/**
|
|
|
* 请求消费
|
|
|
@@ -74,11 +65,10 @@ public class ConsumeBusiness {
|
|
|
*/
|
|
|
public R<ErrorInfo> createOrder(ConsumptionBo bo, String mac, String xfPwd) {
|
|
|
long startTime = System.currentTimeMillis();
|
|
|
- log.warn("[请求交易]-[开始记录有效性验证]-[{}]", JSONUtil.toJsonStr(bo));
|
|
|
AllowConsumeValidationContext ctx = AllowConsumeValidationContext.create(bo);
|
|
|
R<ErrorInfo> result = commonCheck.consumeValidation(ctx);
|
|
|
if (R.isError(result)) {
|
|
|
- log.error("[请求交易]-[记录有效性验证失败]-[耗时: {} 毫秒]-[错误:{}]", System.currentTimeMillis() - startTime, result.getData());
|
|
|
+ log.error("[请求交易]-[记录有效性验证失败]-[错误: {}毫秒]-[数据:{}]", result.getData(), JSONUtil.toJsonStr(bo));
|
|
|
return result;
|
|
|
}
|
|
|
log.info("[请求交易]-[记录有效性验证完成]-[耗时: {} 毫秒]-[记录:{}]", System.currentTimeMillis() - startTime, JSONUtil.toJsonStr(bo));
|
|
|
@@ -87,22 +77,20 @@ public class ConsumeBusiness {
|
|
|
RemoteCardVo userCardVo = ctx.getUserCardVo();
|
|
|
XfTermVo termVo = ctx.getUseTermVo();
|
|
|
|
|
|
- log.warn("[请求交易]-[交易流程验证]-[{}]", JSONUtil.toJsonStr(bo));
|
|
|
Map<String, Boolean> mapCardLimited = new HashMap<>(4);
|
|
|
XfCardLimitedVo cardLimitedVo = new XfCardLimitedVo();
|
|
|
startTime = System.currentTimeMillis();
|
|
|
result = requestCheck.checkConsume(bo, userAccountVo, userCardVo, termVo, mapCardLimited, cardLimitedVo);
|
|
|
if (R.isError(result)) {
|
|
|
- log.error("[请求交易]-[交易验证失败]-[{}]", JSONUtil.toJsonStr(result.getData()));
|
|
|
+ log.error("[请求交易]-[交易流程验证失败]-[错误: {}]-[数据:{}]", result.getData(), JSONUtil.toJsonStr(bo));
|
|
|
return result;
|
|
|
}
|
|
|
- log.warn("[请求交易]-[交易流程验证]-[耗时: {} 毫秒]", System.currentTimeMillis() - startTime);
|
|
|
+ log.warn("[请求交易]-[交易流程验证完成]-[耗时: {} 毫秒]", System.currentTimeMillis() - startTime);
|
|
|
|
|
|
- log.warn("[请求交易]-[生成原始消费记录]-[{}]", JSONUtil.toJsonStr(bo));
|
|
|
startTime = System.currentTimeMillis();
|
|
|
result = requestCheck.completeConsumeRequest(bo, userAccountVo, userCardVo, termVo, mapCardLimited, cardLimitedVo);
|
|
|
if (R.isError(result)) {
|
|
|
- log.error("[请求交易]-[消费原始记录表入库失败]-[{}]", JSONUtil.toJsonStr(result.getData()));
|
|
|
+ log.error("[请求交易]-[消费原始记录失败]-[错误: {}]-[数据:{}]", result.getData(), JSONUtil.toJsonStr(bo));
|
|
|
return result;
|
|
|
}
|
|
|
log.info("[请求交易]-[生成原始消费记录完成]-[耗时: {} 毫秒]", System.currentTimeMillis() - startTime);
|
|
|
@@ -120,34 +108,35 @@ public class ConsumeBusiness {
|
|
|
*/
|
|
|
public R<ErrorInfo> postOrder(ConsumptionBo bo, String mac, String xfPwd) {
|
|
|
long startTime = System.currentTimeMillis();
|
|
|
- // log.warn("[上传交易]-[开始记录有效性验证]-[{}]", JSONUtil.toJsonStr(bo));
|
|
|
AllowConsumeValidationContext ctx = AllowConsumeValidationContext.create(bo);
|
|
|
R<ErrorInfo> result = commonCheck.consumeValidation(ctx);
|
|
|
- log.info("[上传交易]-[记录有效性验证完成]-[耗时: {} 毫秒]-[记录:{}]", System.currentTimeMillis() - startTime, JSONUtil.toJsonStr(bo));
|
|
|
if (R.isError(result)) {
|
|
|
- log.error("[上传交易]-[记录有效性验证失败]-[{}]", result.getData());
|
|
|
+ log.error("[上传交易]-[记录有效性验证失败]-[错误: {}]-[数据:{}]", result.getData(), JSONUtil.toJsonStr(bo));
|
|
|
return result;
|
|
|
}
|
|
|
+ log.info("[上传交易]-[记录有效性验证完成]-[耗时: {} 毫秒]-[记录:{}]", System.currentTimeMillis() - startTime, JSONUtil.toJsonStr(bo));
|
|
|
|
|
|
- log.warn("[上传交易]-[交易账单处理]-[{}]", JSONUtil.toJsonStr(bo));
|
|
|
+ startTime = System.currentTimeMillis();
|
|
|
List<PtBagVo> bagVos = new ArrayList<>();
|
|
|
RemoteUserAccountVo userAccountVo = ctx.getUserAccountVo();
|
|
|
RemoteCardVo userCardVo = ctx.getUserCardVo();
|
|
|
XfTermVo termVo = ctx.getUseTermVo();
|
|
|
RemoteMealTypeVo mealTypeVo = new RemoteMealTypeVo();
|
|
|
- RemoteOperatorVo operatorVo = new RemoteOperatorVo();
|
|
|
result = uploadCheck.checkBill(bo, userAccountVo, termVo, bagVos, mealTypeVo);
|
|
|
if (R.isError(result)) {
|
|
|
- log.error("[上传交易]-[交易账单处理失败]-[{}]", result.getData());
|
|
|
+ log.error("[上传交易]-[交易账单处理失败]-[错误: {}]-[数据:{}]", result.getData(), JSONUtil.toJsonStr(bo));
|
|
|
return result;
|
|
|
}
|
|
|
- log.warn("[上传交易]-[交易入库]-[{}]", JSONUtil.toJsonStr(bo));
|
|
|
+ log.info("[上传交易]-[交易账单处理完成]-[耗时: {} 毫秒]-[记录:{}]", System.currentTimeMillis() - startTime, JSONUtil.toJsonStr(bo));
|
|
|
+
|
|
|
+ startTime = System.currentTimeMillis();
|
|
|
try {
|
|
|
result = baseBusiness.postConsumeRecord(bo, userAccountVo, userCardVo, bagVos, termVo, mealTypeVo, "");
|
|
|
if (R.isError(result)) {
|
|
|
- log.error("[上传交易]-[交易入库失败]-[{}]", result.getData());
|
|
|
+ log.error("[上传交易]-[交易入库失败]-[错误:{}]-[数据:{}]", result.getData(), JsonUtils.toJsonString(bo));
|
|
|
return result;
|
|
|
}
|
|
|
+ log.info("[上传交易]-[交易入库处理完成]-[耗时: {} 毫秒]-[记录:{}]", System.currentTimeMillis() - startTime, JSONUtil.toJsonStr(bo));
|
|
|
return R.ok();
|
|
|
} catch (ConsumeException e) {
|
|
|
log.error("[[上传交易]-[交易入库失败]-[{}]", e.getMessage(), e);
|
|
|
@@ -175,62 +164,31 @@ public class ConsumeBusiness {
|
|
|
}
|
|
|
|
|
|
R<ErrorInfo> result = this.createOrder(bo, mac, xfPwd);
|
|
|
- if (!R.isSuccess(result)) {
|
|
|
- log.error("[请求交易]-[请求交易处理失败]-[{}]", JSONUtil.toJsonStr(result.getData()));
|
|
|
- return result;
|
|
|
- }
|
|
|
- result = this.postOrder(bo, mac, xfPwd);
|
|
|
- if (!R.isSuccess(result)) {
|
|
|
- log.error("[交易上传]-[交易上传处理失败]-[{}]", JSONUtil.toJsonStr(result.getData()));
|
|
|
+ if (R.isError(result)) {
|
|
|
return result;
|
|
|
}
|
|
|
- return R.ok();
|
|
|
+ return this.postOrder(bo, mac, xfPwd);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 原始消费对账,将有原始消费记录但没有消费明细的消费记录写入消费明细
|
|
|
+ * 异步处理消费机上传的消费订单。
|
|
|
+ * 该方法用于在后台线程中提交消费订单,避免阻塞主线程,适用于需要高性能处理的场景。
|
|
|
*
|
|
|
- * @return 对账结果
|
|
|
+ * @param bo 消费记录对象 (ConsumptionBo)。
|
|
|
+ * 包含当前消费订单的详细信息,例如用户ID、消费金额、时间戳等。
|
|
|
+ * @param mac 设备的 MAC 地址 (String)。
|
|
|
+ * 表示发起消费请求的设备的唯一标识符,通常用于验证设备合法性。
|
|
|
+ * @param xfPwd 消费密码 (String)。
|
|
|
+ * 用户提供的消费密码,用于验证用户的操作权限。
|
|
|
*/
|
|
|
- public R<ErrorInfo> originalReconciliation(String consumeDate) {
|
|
|
- // 先查询没有写入消费明细的原始消费记录
|
|
|
- List<ConsumptionBo> list = baseBusiness.selectOriginalReconciliation(DateUtil.parseDate(consumeDate));
|
|
|
- if (CollectionUtil.isEmpty(list)) {
|
|
|
- return R.ok(new ErrorInfo(ResultCodeEnum.DATA_NOT_FOUND.code(), ApiErrorTypeConstants.NOT_FOUND, "没有待入账的原始消费记录"));
|
|
|
- }
|
|
|
- List<String> doMessage = new ArrayList<>();
|
|
|
- // 循环写入原始消费记录
|
|
|
- int total = list.size();
|
|
|
- AtomicInteger success = new AtomicInteger();
|
|
|
- AtomicInteger fail = new AtomicInteger();
|
|
|
- list.forEach(p -> {
|
|
|
- p.setUseType(SystemUseTypeEnum.CONSUME.code());
|
|
|
- p.setCreditType(baseBusiness.getCreditType(p.getStatusFlag()));
|
|
|
- p.setRecordStatus(364L);
|
|
|
- try {
|
|
|
- R<ErrorInfo> result = fullOrder(p, "", "");
|
|
|
- if (R.isSuccess(result)) {
|
|
|
- doMessage.add(MessageFormat.format("[入账成功]-[{0}]", JsonUtils.toJsonString(p)));
|
|
|
- success.getAndIncrement();
|
|
|
- // 如果是本地消费服务成功后需要发消息到云端同步处理
|
|
|
- if (ObjectUtil.equals(defaultConfig.getLocationFlag(), DefaultConstants.LOCAL_FLAG)) {
|
|
|
- ConsumptionBo bo = BeanUtil.copyProperties(p, ConsumptionBo.class);
|
|
|
- ThreadUtil.execAsync(() -> baseBusiness.sendCloudConsume(bo));
|
|
|
- }
|
|
|
- } else {
|
|
|
- doMessage.add(MessageFormat.format("[入账失败]-[{0}]-[{1}]", JsonUtils.toJsonString(p), JSONUtil.toJsonStr(result.getData())));
|
|
|
- fail.getAndIncrement();
|
|
|
- }
|
|
|
- } catch (Exception e) {
|
|
|
- doMessage.add(MessageFormat.format("[入账失败]-[{0}]-[{1}]", JsonUtils.toJsonString(p), e.getStackTrace()));
|
|
|
- fail.getAndIncrement();
|
|
|
- log.error("[对账失败]-[{}]", JSONUtil.toJsonStr(p), e);
|
|
|
- }
|
|
|
- });
|
|
|
- doMessage.forEach(System.out::println);
|
|
|
- return R.ok(MessageFormat.format("[对账处理完成]-[待处理:{0}条,成功:{1}条,失败:{2}条]", total, success.get(), fail.get()));
|
|
|
+ @Async
|
|
|
+ public void postOrderAsync(ConsumptionBo bo, String mac, String xfPwd) {
|
|
|
+ R<ErrorInfo> result = SpringUtils.getAopProxy(this).postOrder(bo, mac, xfPwd);
|
|
|
+ log.info("[上传交易结果完成]");
|
|
|
}
|
|
|
|
|
|
+ //region 云端消费对账
|
|
|
+
|
|
|
/**
|
|
|
* 云端同步对账,将接收到kafka消息但没有处理成功的消费记录重新处理.处理成功后将记录的处理状态设置成已处理
|
|
|
*
|
|
|
@@ -238,46 +196,208 @@ public class ConsumeBusiness {
|
|
|
* @return 处理结果.
|
|
|
*/
|
|
|
public R<ErrorInfo> syncReconciliation(String consumeDate) {
|
|
|
+ // 1. 查询未处理的原始消费记录
|
|
|
RemoteSendMessageRecordBo remoteBo = new RemoteSendMessageRecordBo();
|
|
|
remoteBo.setEventType("12000001");
|
|
|
remoteBo.setUpdateTime(DateUtil.parseDateTime(consumeDate));
|
|
|
remoteBo.setConsumeStatus("N");
|
|
|
- List<RemoteSendMessageRecordBo> messageRecordBoList = baseBusiness.queryConsumeErrorList(remoteBo);
|
|
|
- if (CollectionUtil.isEmpty(messageRecordBoList)) {
|
|
|
- return R.ok();
|
|
|
+ List<RemoteSendMessageRecordBo> noSendBos = baseBusiness.queryConsumeErrorList(remoteBo);
|
|
|
+
|
|
|
+ if (CollectionUtil.isEmpty(noSendBos)) {
|
|
|
+ log.warn("[云端对账完成]-[没有向云端请求消费失败记录消费记录]");
|
|
|
+ return R.ok(new ErrorInfo(ResultCodeEnum.DATA_NOT_FOUND.code(),
|
|
|
+ ApiErrorTypeConstants.NOT_FOUND,
|
|
|
+ "没有向云端请求消费失败记录消费记录"));
|
|
|
}
|
|
|
- int total = messageRecordBoList.size();
|
|
|
- AtomicInteger success = new AtomicInteger();
|
|
|
- AtomicInteger fail = new AtomicInteger();
|
|
|
- List<String> doMessage = new ArrayList<>();
|
|
|
- messageRecordBoList.forEach(p -> {
|
|
|
- ConsumptionBo bo = JSONUtil.toBean(p.getMessage(), ConsumptionBo.class);
|
|
|
- bo.setUseType(SystemUseTypeEnum.CONSUME.code());
|
|
|
- bo.setRecordId(0L);
|
|
|
+
|
|
|
+ // 2.将取出的未发送成功的数据转换成消费对象列表
|
|
|
+ List<ConsumptionBo> records = new ArrayList<>();
|
|
|
+ noSendBos.forEach(p -> {
|
|
|
+ records.add(JSONUtil.toBean(p.getMessage(), ConsumptionBo.class));
|
|
|
+ });
|
|
|
+
|
|
|
+ // 3. 并行处理记录
|
|
|
+ ReconciliationResult result = processCloudRecordsInParallel(records);
|
|
|
+
|
|
|
+ // 4. 记录处理结果
|
|
|
+ result.getMessages().forEach(log::info);
|
|
|
+ return R.ok(MessageFormat.format("[云端对账完成]-[待处理:{0}条,成功:{1}条,失败:{2}条]",
|
|
|
+ records.size(), result.getSuccessCount(), result.getFailCount()));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 并行处理消费记录列表,并返回对账结果。
|
|
|
+ * 该方法通过并行化处理提高性能,适用于需要处理大量消费记录的场景。
|
|
|
+ *
|
|
|
+ * @param records 消费记录列表 (List<ConsumptionBo>)。
|
|
|
+ * 表示需要处理的所有消费记录。每条记录包含与消费相关的详细信息,
|
|
|
+ * 如用户ID、消费金额、时间戳等。
|
|
|
+ * @return 对账结果对象 (ReconciliationResult)。
|
|
|
+ * 包含处理后的结果信息,包括成功处理的记录、失败的记录以及异常详情。
|
|
|
+ */
|
|
|
+ private ReconciliationResult processCloudRecordsInParallel(List<ConsumptionBo> records) {
|
|
|
+ ReconciliationResult result = new ReconciliationResult();
|
|
|
+ // 使用并行流处理
|
|
|
+ records.parallelStream().forEach(record -> {
|
|
|
try {
|
|
|
- R<ErrorInfo> result = fullOrder(bo, "", "");
|
|
|
- if (R.isSuccess(result)) {
|
|
|
- doMessage.add(MessageFormat.format("[同步消费成功]-[{0}]", JsonUtils.toJsonString(p)));
|
|
|
- success.getAndIncrement();
|
|
|
- baseBusiness.updateConsumeStatusById(p.getRecordId());
|
|
|
+ R<ErrorInfo> response = fullOrder(record, "", "");
|
|
|
+
|
|
|
+ if (R.isSuccess(response)) {
|
|
|
+ handleSuccessfulRecord(record, result);
|
|
|
} else {
|
|
|
- doMessage.add(
|
|
|
- MessageFormat.format("[同步消费失败]-[{0}]-[{1}]", JsonUtils.toJsonString(p), JSONUtil.toJsonStr(result.getData())));
|
|
|
- fail.getAndIncrement();
|
|
|
+ handleFailedRecord(record, response.getData(), result);
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
- doMessage.add(MessageFormat.format("[同步消费失败]-[{0}]-[{1}]", JsonUtils.toJsonString(p), e.getStackTrace()));
|
|
|
- fail.getAndIncrement();
|
|
|
- log.error("[对账失败]-[{}]", JSONUtil.toJsonStr(p), e);
|
|
|
+ handleException(record, e, result);
|
|
|
}
|
|
|
});
|
|
|
- doMessage.forEach(System.out::println);
|
|
|
- return R.ok(MessageFormat.format("[同步消费完成]-[待处理:{0}条,成功:{1}条,失败:{2}条]", total, success.get(), fail.get()));
|
|
|
+
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
- @Async
|
|
|
- public void postOrderAsync(ConsumptionBo bo, String mac, String xfPwd) {
|
|
|
- R<ErrorInfo> result = SpringUtils.getAopProxy(this).postOrder(bo, mac, xfPwd);
|
|
|
- log.info("[上传交易结果完成]");
|
|
|
+ //endregion
|
|
|
+
|
|
|
+ //region 原始消费记录对账
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 原始消费对账,将有原始消费记录但没有消费明细的消费记录写入消费明细
|
|
|
+ *
|
|
|
+ * @return 对账结果
|
|
|
+ */
|
|
|
+ public R<ErrorInfo> originalReconciliation(String consumeDate) {
|
|
|
+ // 1. 查询未处理的原始消费记录
|
|
|
+ List<ConsumptionBo> records = baseBusiness.selectOriginalReconciliation(DateUtil.parseDate(consumeDate));
|
|
|
+ if (CollectionUtil.isEmpty(records)) {
|
|
|
+ log.warn("[对账处理完成]-[没有待入账的原始消费记录]");
|
|
|
+ return R.ok(new ErrorInfo(ResultCodeEnum.DATA_NOT_FOUND.code(),
|
|
|
+ ApiErrorTypeConstants.NOT_FOUND,
|
|
|
+ "没有待入账的原始消费记录"));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 并行处理记录
|
|
|
+ ReconciliationResult result = processRecordsInParallel(records);
|
|
|
+
|
|
|
+ // 3. 记录处理结果
|
|
|
+ result.getMessages().forEach(log::info);
|
|
|
+ return R.ok(MessageFormat.format("[对账处理完成]-[待处理:{0}条,成功:{1}条,失败:{2}条]",
|
|
|
+ records.size(), result.getSuccessCount(), result.getFailCount()));
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 并行处理消费记录列表,并返回对账结果。
|
|
|
+ * 该方法通过并行化处理提高性能,适用于需要处理大量消费记录的场景。
|
|
|
+ *
|
|
|
+ * @param records 消费记录列表 (List<ConsumptionBo>)。
|
|
|
+ * 表示需要处理的所有消费记录。每条记录包含与消费相关的详细信息,
|
|
|
+ * 如用户ID、消费金额、时间戳等。
|
|
|
+ * @return 对账结果对象 (ReconciliationResult)。
|
|
|
+ * 包含处理后的结果信息,包括成功处理的记录、失败的记录以及异常详情。
|
|
|
+ */
|
|
|
+
|
|
|
+ private ReconciliationResult processRecordsInParallel(List<ConsumptionBo> records) {
|
|
|
+ ReconciliationResult result = new ReconciliationResult();
|
|
|
+
|
|
|
+ // 使用并行流处理
|
|
|
+ records.parallelStream().forEach(record -> {
|
|
|
+ try {
|
|
|
+ R<ErrorInfo> response = postOrder(record, "", "");
|
|
|
+
|
|
|
+ if (R.isSuccess(response)) {
|
|
|
+ handleSuccessfulRecord(record, result);
|
|
|
+ } else {
|
|
|
+ handleFailedRecord(record, response.getData(), result);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ handleException(record, e, result);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ //endregion
|
|
|
+
|
|
|
+ //region 对账通用处理方法
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对账对账成功情况的处理。
|
|
|
+ * 该方法通常用于记录对账的成功信息并将信息记录到结果对象中,以便后续分析或展示。
|
|
|
+ *
|
|
|
+ * @param record 异常相关的消费记录对象 (ConsumptionBo)。
|
|
|
+ * 包含当前处理的消费记录的详细信息(如用户ID、消费金额等)。
|
|
|
+ * @param result 对账结果对象 (ReconciliationResult)。
|
|
|
+ * 用于存储对账过程的结果信息,包括成功记录、失败记录以及异常详情。
|
|
|
+ */
|
|
|
+ private void handleSuccessfulRecord(ConsumptionBo record, ReconciliationResult result) {
|
|
|
+ String successMsg = MessageFormat.format("[入账成功]-[{0}]", JsonUtils.toJsonString(record));
|
|
|
+ result.addMessage(successMsg);
|
|
|
+ result.incrementSuccess();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对账对账失败情况的处理。
|
|
|
+ * 该方法通常用于记录对账的失败信息并将错误信息记录到结果对象中,以便后续分析或展示。
|
|
|
+ *
|
|
|
+ * @param record 异常相关的消费记录对象 (ConsumptionBo)。
|
|
|
+ * 包含当前处理的消费记录的详细信息(如用户ID、消费金额等)。
|
|
|
+ * @param result 对账结果对象 (ReconciliationResult)。
|
|
|
+ * 用于存储对账过程的结果信息,包括成功记录、失败记录以及异常详情。
|
|
|
+ */
|
|
|
+ private void handleFailedRecord(ConsumptionBo record, ErrorInfo errorInfo, ReconciliationResult result) {
|
|
|
+ String errorMsg = MessageFormat.format("[入账失败]-[{0}]-[{1}]",
|
|
|
+ JsonUtils.toJsonString(record),
|
|
|
+ JSONUtil.toJsonStr(errorInfo));
|
|
|
+ result.addMessage(errorMsg);
|
|
|
+ result.incrementFail();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对账异常处理异常情况的方法。
|
|
|
+ * 该方法通常用于在对账或消费记录处理过程中捕获并处理异常,
|
|
|
+ * 同时将异常信息记录到结果对象中,以便后续分析或展示。
|
|
|
+ *
|
|
|
+ * @param record 异常相关的消费记录对象 (ConsumptionBo)。
|
|
|
+ * 包含当前处理的消费记录的详细信息(如用户ID、消费金额等)。
|
|
|
+ * @param e 捕获到的异常对象 (Exception)。
|
|
|
+ * 表示在处理消费记录时发生的错误或异常情况。
|
|
|
+ * @param result 对账结果对象 (ReconciliationResult)。
|
|
|
+ * 用于存储对账过程的结果信息,包括成功记录、失败记录以及异常详情。
|
|
|
+ */
|
|
|
+ private void handleException(ConsumptionBo record, Exception e, ReconciliationResult result) {
|
|
|
+ String stackTrace = Arrays.stream(e.getStackTrace())
|
|
|
+ .findFirst()
|
|
|
+ .map(StackTraceElement::toString)
|
|
|
+ .orElse("No stack trace available");
|
|
|
+
|
|
|
+ String errorMsg = MessageFormat.format("[入账失败]-[{0}]-[{1}]",
|
|
|
+ JsonUtils.toJsonString(record),
|
|
|
+ stackTrace);
|
|
|
+
|
|
|
+ result.addMessage(errorMsg);
|
|
|
+ result.incrementFail();
|
|
|
+ log.error("[对账失败]-[{}]-{}", JSONUtil.toJsonStr(record), e.getMessage(), e);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对账结果封装
|
|
|
+ */
|
|
|
+ @Data
|
|
|
+ private static class ReconciliationResult {
|
|
|
+ private final List<String> messages = Collections.synchronizedList(new ArrayList<>());
|
|
|
+ private final AtomicInteger successCount = new AtomicInteger();
|
|
|
+ private final AtomicInteger failCount = new AtomicInteger();
|
|
|
+
|
|
|
+ public void addMessage(String message) {
|
|
|
+ messages.add(message);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void incrementSuccess() {
|
|
|
+ successCount.incrementAndGet();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void incrementFail() {
|
|
|
+ failCount.incrementAndGet();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //endregion
|
|
|
+
|
|
|
}
|