feat: 积分商城-对账优化
This commit is contained in:
+44
@@ -0,0 +1,44 @@
|
||||
package com.budwk.app.zhgh.pointsmall.mallbridge.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class OrderInfoByReconciliationDTO {
|
||||
/**
|
||||
* 订单id
|
||||
*/
|
||||
private String orderId;
|
||||
|
||||
/**
|
||||
* 供应商id
|
||||
*/
|
||||
private String supplierId;
|
||||
|
||||
/**
|
||||
* 商品购买总价格(含税价)
|
||||
*/
|
||||
private BigDecimal totalPrice;
|
||||
|
||||
/**
|
||||
* 订单消耗积分数,有退货需要计算
|
||||
*/
|
||||
private BigDecimal pointsPrice;
|
||||
|
||||
/**
|
||||
* 订单微信支付或支付宝支付数目,有退货需要计算
|
||||
*/
|
||||
private BigDecimal wPayOrAPay;
|
||||
|
||||
/**
|
||||
* 总价格(不含税)
|
||||
*/
|
||||
private BigDecimal invoiceNakedPrice;
|
||||
|
||||
/**
|
||||
* 下单商品信息
|
||||
*/
|
||||
private List<OrderProInfoDTO> orderProInfos;
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.budwk.app.zhgh.pointsmall.mallbridge.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class QueryReconciliationInfoDTO {
|
||||
private String supplierId;
|
||||
private String token;
|
||||
private Integer reconciliationType;
|
||||
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
private String orderId;
|
||||
|
||||
/**
|
||||
* 格式为:yyyy-MM-dd(包含单日)
|
||||
*/
|
||||
private String startDate;
|
||||
|
||||
/**
|
||||
* 格式为:yyyy-MM-dd(包含单日)
|
||||
*/
|
||||
private String endDate;
|
||||
private Integer page;
|
||||
private Integer pageSize;
|
||||
private Long timestamp;
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.budwk.app.zhgh.pointsmall.mallbridge.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ReconciliationResultNoticeDTO {
|
||||
private String supplierId;
|
||||
private String token;
|
||||
private Long timestamp;
|
||||
private String reconciliationBatchNo;
|
||||
private String reconciliationTime;
|
||||
private List<ReconciliationResultOrderDTO> reconciliationResults;
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.budwk.app.zhgh.pointsmall.mallbridge.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class ReconciliationResultOrderDTO {
|
||||
private String orderId;
|
||||
private String userId;
|
||||
private Integer reconciliationStatus;
|
||||
private Integer diffType;
|
||||
private String diffReason;
|
||||
private BigDecimal platformTotalPrice;
|
||||
private BigDecimal platformCashAmount;
|
||||
private BigDecimal platformPointsPrice;
|
||||
private BigDecimal platformRefundPrice;
|
||||
private BigDecimal supplierTotalPrice;
|
||||
private BigDecimal supplierCashAmount;
|
||||
private BigDecimal supplierPointsPrice;
|
||||
private BigDecimal supplierRefundPrice;
|
||||
}
|
||||
+1
@@ -7,6 +7,7 @@ public class UnReconciledMsgNoticeDTO {
|
||||
private String uniqueSeqNo;
|
||||
private String supplierId;
|
||||
private String token;
|
||||
private Long timestamp;
|
||||
private String orderIds;
|
||||
private String unReconciledMsg;
|
||||
private String unReconciledType;
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package com.budwk.app.zhgh.pointsmall.mallbridge.model;
|
||||
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.dto.OrderInfoByReconciliationDTO;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class MallOutboundPageResult {
|
||||
/**
|
||||
* 0: 查询成功, 其他: 响应失败错误码
|
||||
*/
|
||||
private int resultCode;
|
||||
|
||||
/**
|
||||
* 失败时, 返回失败原因
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 总页
|
||||
*/
|
||||
private Integer totalPage;
|
||||
|
||||
/**
|
||||
* 当前页
|
||||
*/
|
||||
private Integer currentPage;
|
||||
|
||||
//9.2.2 获取订单详情接口时不能为空
|
||||
private List<OrderInfoByReconciliationDTO> orderInfos;
|
||||
|
||||
public static MallOutboundPageResult success() {
|
||||
MallOutboundPageResult r = new MallOutboundPageResult();
|
||||
r.resultCode = 0;
|
||||
r.message = "成功";
|
||||
r.orderInfos = null;
|
||||
return r;
|
||||
}
|
||||
|
||||
public static MallOutboundPageResult success(List<OrderInfoByReconciliationDTO> o) {
|
||||
MallOutboundPageResult r = new MallOutboundPageResult();
|
||||
r.resultCode = 0;
|
||||
r.message = "成功";
|
||||
r.orderInfos = o;
|
||||
return r;
|
||||
}
|
||||
|
||||
public static MallOutboundPageResult fail(int code, String message) {
|
||||
MallOutboundPageResult r = new MallOutboundPageResult();
|
||||
r.resultCode = code;
|
||||
r.message = message;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
package com.budwk.app.zhgh.pointsmall.mallbridge.service;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.dto.OrderInfoByReconciliationDTO;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.dto.QueryReconciliationInfoDTO;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallOutboundPageResult;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.util.MallBridgeCryptoUtil;
|
||||
import com.budwk.app.zhgh.pointsmall.supplier.models.PointsMallSupplier;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.impl.PropertiesProxy;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 获取对账信息
|
||||
*/
|
||||
@Slf4j
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class MallReconciliationInfoQueryService {
|
||||
|
||||
private final Dao dao;
|
||||
|
||||
@Inject
|
||||
private PropertiesProxy conf;
|
||||
|
||||
public MallReconciliationInfoQueryService(Dao dao) {
|
||||
this.dao = dao;
|
||||
}
|
||||
|
||||
public List<OrderInfoByReconciliationDTO> queryReconciliationInfo(QueryReconciliationInfoDTO dto) {
|
||||
// 从供应商获取对账订单信息
|
||||
return getOrderInfoFromSupplier(dto);
|
||||
}
|
||||
|
||||
private List<OrderInfoByReconciliationDTO> getOrderInfoFromSupplier(QueryReconciliationInfoDTO dto) {
|
||||
log.info("9.2.4 对账接口执行开始:{}", dto);
|
||||
String clientBAB7ServerUrl = conf.get("spdb.bab7.url", "");
|
||||
if (StrUtil.isBlank(clientBAB7ServerUrl)) {
|
||||
throw new IllegalArgumentException("未配置 BAB7 服务地址");
|
||||
}
|
||||
|
||||
PointsMallSupplier supplier = dao.fetch(PointsMallSupplier.class,
|
||||
Cnd.where("supplierId", "=", dto.getSupplierId()).and("delFlag", "=", false));
|
||||
if (supplier == null) {
|
||||
log.error("9.2.4 对账接口 未找到对应供应商信息");
|
||||
throw new IllegalArgumentException("未找到对应供应商信息");
|
||||
}
|
||||
long timestamp = System.currentTimeMillis();
|
||||
// 计算token
|
||||
String token = MallBridgeCryptoUtil.generateSign(supplier.getSupplierId(), supplier.getClientId(), timestamp);
|
||||
dto.setToken(token);
|
||||
dto.setTimestamp(timestamp);
|
||||
// 组装请求报文
|
||||
HashMap<String, Object> bodyMap = buildReqParam(dto, supplier);
|
||||
log.info("9.2.4 通过对接接口从供应商获取对账订单数据:{}", dto);
|
||||
String response = HttpUtil.createPost(clientBAB7ServerUrl)
|
||||
.contentType("application/json;charset=UTF-8")
|
||||
.body(JSONUtil.toJsonStr(bodyMap))
|
||||
.execute()
|
||||
.body();
|
||||
if (response == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
JSONObject returnResult = JSONUtil.parseObj(response);
|
||||
log.info("通过对账接口获取对账订单数据,响应结果:{}", returnResult);
|
||||
if ("-1".equals(returnResult.getStr("resultCode"))) {
|
||||
throw new IllegalArgumentException("查询对账信息异常:" + returnResult);
|
||||
}
|
||||
|
||||
MallOutboundPageResult mallOutboundPageResult = JSONUtil.toBean(returnResult, MallOutboundPageResult.class);
|
||||
if (mallOutboundPageResult == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 错误码为0表示查询成功,不等于0表示查询失败
|
||||
Integer resultCode = mallOutboundPageResult.getResultCode();
|
||||
if (resultCode != 0) {
|
||||
log.info("通过对账接口获取对账订单数据,查询失败:{}", dto);
|
||||
}
|
||||
if (CollUtil.isEmpty(mallOutboundPageResult.getOrderInfos())) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<OrderInfoByReconciliationDTO> orderInfoList = new ArrayList<>(mallOutboundPageResult.getOrderInfos());
|
||||
// 页码
|
||||
Integer page = dto.getPage();
|
||||
// 总页数
|
||||
Integer totalPage = mallOutboundPageResult.getTotalPage();
|
||||
// 当返回的总页数没有变化,以传入的page来循环拉取
|
||||
while (page < totalPage) {
|
||||
// 循环拉取page页的数据
|
||||
dto.setPage(page + 1);
|
||||
log.info("9.2.4 对账接口-分页循环拉取,入参:{}", dto);
|
||||
bodyMap = buildReqParam(dto, supplier);
|
||||
response = HttpUtil.createPost(clientBAB7ServerUrl)
|
||||
.contentType("application/json;charset=UTF-8")
|
||||
.body(JSONUtil.toJsonStr(bodyMap))
|
||||
.execute()
|
||||
.body();
|
||||
mallOutboundPageResult = JSONUtil.toBean(response, MallOutboundPageResult.class);
|
||||
log.info("9.2.4 对账接口-分页循环拉取,返回报文:{}", mallOutboundPageResult);
|
||||
// 错误码为0表示查询成功,不等于0表示查询失败
|
||||
if (mallOutboundPageResult.getResultCode() != 0) {
|
||||
log.info("通过对账接口获取对账订单数据,查询失败:{}", dto);
|
||||
}
|
||||
orderInfoList.addAll(mallOutboundPageResult.getOrderInfos());
|
||||
page++;
|
||||
}
|
||||
|
||||
log.info("9.2.4 通过对接接口从供应商获取对账订单数据调用结束,返回报文:{}", orderInfoList);
|
||||
return orderInfoList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装请求报文
|
||||
*
|
||||
* @param dto 请求参数
|
||||
* @param supplier 供应商信息
|
||||
* @return 对账接口请求入参
|
||||
*/
|
||||
private HashMap<String, Object> buildReqParam(QueryReconciliationInfoDTO dto, PointsMallSupplier supplier) {
|
||||
// 每个供应商的接口地址不一致,后续判断
|
||||
String address4 = supplier.getSupplierApiUrl() + "/supplierOpenApi/pointOrder/queryReconciliationInfo";
|
||||
String bussDealMd = "P";
|
||||
String srvNo = supplier.getSroNo();
|
||||
String clientId = supplier.getClientId();
|
||||
// 参数(此处需要加密)
|
||||
String params = JSONUtil.toJsonStr(dto);
|
||||
log.info("9.2.4 对账接口-请求参数:{}", params);
|
||||
String keyHex = conf.get("sm4cbc.keyHex", "");
|
||||
String ivHex = conf.get("sm4cbc.ivHex", "");
|
||||
String encrypt;
|
||||
try {
|
||||
encrypt = MallBridgeCryptoUtil.sm4CbcEncrypt(params, keyHex, ivHex);
|
||||
} catch (Exception e) {
|
||||
log.error("9.2.4 对账接口请求参数 SM4CBC 加密出错:{}", params, e);
|
||||
throw new RuntimeException("9.2.4 对账接口请求参数 SM4CBC 加密出错");
|
||||
}
|
||||
|
||||
HashMap<String, Object> bodyMap = new HashMap<>();
|
||||
bodyMap.put("Address4", address4);
|
||||
bodyMap.put("BussDealMd", bussDealMd);
|
||||
bodyMap.put("SroNo", srvNo);
|
||||
bodyMap.put("RsrvFld1", clientId);
|
||||
bodyMap.put("AplParmObjct", encrypt);
|
||||
|
||||
return bodyMap;
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package com.budwk.app.zhgh.pointsmall.mallbridge.service;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.dto.ReconciliationResultNoticeDTO;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallInboundResult;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.util.MallBridgeCryptoUtil;
|
||||
import com.budwk.app.zhgh.pointsmall.supplier.models.PointsMallSupplier;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.impl.PropertiesProxy;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* 对账结果通知服务
|
||||
*/
|
||||
@Slf4j
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class MallReconciliationResultNoticeService {
|
||||
|
||||
private final Dao dao;
|
||||
|
||||
@Inject
|
||||
private PropertiesProxy conf;
|
||||
|
||||
public MallReconciliationResultNoticeService(Dao dao) {
|
||||
this.dao = dao;
|
||||
}
|
||||
|
||||
public MallInboundResult reconciliationResultNotice(ReconciliationResultNoticeDTO dto) {
|
||||
String clientBAB7ServerUrl = conf.get("spdb.bab7.url", "");
|
||||
String keyHex = conf.get("sm4cbc.keyHex", "");
|
||||
String ivHex = conf.get("sm4cbc.ivHex", "");
|
||||
if (StrUtil.isBlank(clientBAB7ServerUrl)) {
|
||||
throw new IllegalArgumentException("未配置BAB7服务地址");
|
||||
}
|
||||
|
||||
PointsMallSupplier supplier = dao.fetch(PointsMallSupplier.class,
|
||||
Cnd.where("supplierId", "=", dto.getSupplierId()).and("delFlag", "=", false));
|
||||
if (supplier == null || StrUtil.isBlank(supplier.getSupplierApiUrl())) {
|
||||
throw new IllegalArgumentException("未找到供应商接口地址");
|
||||
}
|
||||
|
||||
long timestamp = System.currentTimeMillis();
|
||||
dto.setTimestamp(timestamp);
|
||||
dto.setToken(MallBridgeCryptoUtil.generateSign(supplier.getSupplierId(), supplier.getClientId(), timestamp));
|
||||
String params = JSONUtil.toJsonStr(dto);
|
||||
String encrypt = MallBridgeCryptoUtil.sm4CbcEncrypt(params, keyHex, ivHex);
|
||||
|
||||
HashMap<String, Object> bodyMap = new HashMap<>();
|
||||
bodyMap.put("Address4", supplier.getSupplierApiUrl() + "/supplierOpenApi/pointOrder/reconciliationResult");
|
||||
bodyMap.put("BussDealMd", "P");
|
||||
bodyMap.put("SroNo", supplier.getSroNo());
|
||||
bodyMap.put("RsrvFld1", supplier.getClientId());
|
||||
bodyMap.put("AplParmObjct", encrypt);
|
||||
|
||||
String response = HttpUtil.createPost(clientBAB7ServerUrl)
|
||||
.contentType("application/json;charset=UTF-8")
|
||||
.body(JSONUtil.toJsonStr(bodyMap))
|
||||
.execute()
|
||||
.body();
|
||||
log.info("对账结果通知接口返回报文:{}", response);
|
||||
return JSONUtil.toBean(response, MallInboundResult.class);
|
||||
}
|
||||
}
|
||||
+69
-1
@@ -2,25 +2,36 @@ package com.budwk.app.zhgh.pointsmall.mallbridge.service;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.dto.UnReconciledMsgNoticeDTO;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallInboundResult;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.service.support.AbstractMallBridgeSupport;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.util.MallBridgeCryptoUtil;
|
||||
import com.budwk.app.zhgh.pointsmall.reconciliation.models.PointsMallReconciliationRecord;
|
||||
import com.budwk.app.zhgh.pointsmall.supplier.models.PointsMallSupplier;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.impl.PropertiesProxy;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.trans.Atom;
|
||||
import org.nutz.trans.Trans;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商城桥接对账异常通知服务。
|
||||
* 对账异常消息通知服务
|
||||
*/
|
||||
@Slf4j
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class MallUnReconciledMsgNoticeService extends AbstractMallBridgeSupport {
|
||||
|
||||
@Inject
|
||||
private PropertiesProxy conf;
|
||||
|
||||
public MallUnReconciledMsgNoticeService(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
@@ -50,4 +61,61 @@ public class MallUnReconciledMsgNoticeService extends AbstractMallBridgeSupport
|
||||
log.info("积分商城对账异常通知完成,supplierId={},orderCount={}", dto.getSupplierId(), orderIds.size());
|
||||
return MallInboundResult.success();
|
||||
}
|
||||
|
||||
public MallInboundResult unReconciledMsgNotice(UnReconciledMsgNoticeDTO dto) {
|
||||
log.info("9.3.1 对账异常通知接口调用开始:{}", dto);
|
||||
String clientBAB7ServerUrl = conf.get("spdb.bab7.url", "");
|
||||
String keyHex = conf.get("sm4cbc.keyHex", "");
|
||||
String ivHex = conf.get("sm4cbc.ivHex", "");
|
||||
if (StrUtil.isBlank(clientBAB7ServerUrl)) {
|
||||
throw new IllegalArgumentException("未配置BAB7服务地址");
|
||||
}
|
||||
|
||||
// 查询供应商信息
|
||||
PointsMallSupplier supplier = dao.fetch(PointsMallSupplier.class,
|
||||
Cnd.where("supplierId", "=", dto.getSupplierId()).and("delFlag", "=", false));
|
||||
if (supplier == null) {
|
||||
log.error("9.3.1 对账异常通知接口 未找到对应供应商信息");
|
||||
throw new IllegalArgumentException("未找到对应供应商信息");
|
||||
}
|
||||
if (StrUtil.isBlank(supplier.getSupplierApiUrl())) {
|
||||
return MallInboundResult.fail(404, "供应商地址未配置");
|
||||
}
|
||||
|
||||
// 组装请求地址
|
||||
String address4 = supplier.getSupplierApiUrl() + "/supplierOpenApi/pointOrder/unReconciledMsg";
|
||||
String bussDealMd = "P";
|
||||
String sroNo = supplier.getSroNo();
|
||||
String clientId = supplier.getClientId();
|
||||
long timestamp = System.currentTimeMillis();
|
||||
dto.setTimestamp(timestamp);
|
||||
dto.setToken(MallBridgeCryptoUtil.generateSign(supplier.getSupplierId(), clientId, timestamp));
|
||||
// 参数加密
|
||||
String params = JSONUtil.toJsonStr(dto);
|
||||
log.info("9.3.1 对账异常通知接口-请求参数:{}", params);
|
||||
String encrypt;
|
||||
try {
|
||||
encrypt = MallBridgeCryptoUtil.sm4CbcEncrypt(params, keyHex, ivHex);
|
||||
} catch (Exception e) {
|
||||
log.error("9.3.1 对账异常通知接口参数加密出错:{}", params, e);
|
||||
throw new IllegalArgumentException("参数加密失败");
|
||||
}
|
||||
|
||||
// 构建请求体
|
||||
HashMap<String, Object> bodyMap = new HashMap<>();
|
||||
bodyMap.put("Address4", address4);
|
||||
bodyMap.put("BussDealMd", bussDealMd);
|
||||
bodyMap.put("SroNo", sroNo);
|
||||
bodyMap.put("RsrvFld1", clientId);
|
||||
bodyMap.put("AplParmObjct", encrypt);
|
||||
|
||||
// 发送请求
|
||||
String response = HttpUtil.createPost(clientBAB7ServerUrl)
|
||||
.contentType("application/json;charset=UTF-8")
|
||||
.body(JSONUtil.toJsonStr(bodyMap))
|
||||
.execute()
|
||||
.body();
|
||||
log.info("9.3.1 对账异常通知接口返回报文:{}", response);
|
||||
return JSONUtil.toBean(response, MallInboundResult.class);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-6
@@ -48,15 +48,11 @@ public class PointsMallReconciliationController {
|
||||
}
|
||||
}
|
||||
|
||||
@At
|
||||
@At("/execute")
|
||||
@SLog(tag = "积分商城对账管理", msg = "执行订单对账")
|
||||
@SaCheckPermission("points.mall.reconciliation")
|
||||
public Result execute(PointsMallReconciliationParam param) {
|
||||
try {
|
||||
return Result.success(pointsMallReconciliationService.execute(param));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
return pointsMallReconciliationService.executeReconciliation(param);
|
||||
}
|
||||
|
||||
@At
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
package com.budwk.app.zhgh.pointsmall.reconciliation.service;
|
||||
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.pointsmall.reconciliation.models.PointsMallReconciliationRecord;
|
||||
import com.budwk.app.zhgh.pointsmall.reconciliation.param.PointsMallReconciliationOrderPageParam;
|
||||
@@ -18,7 +19,7 @@ public interface PointsMallReconciliationService extends BaseService<PointsMallR
|
||||
|
||||
BigDecimal pointsTotal(PointsMallReconciliationParam param);
|
||||
|
||||
String execute(PointsMallReconciliationParam param);
|
||||
Result executeReconciliation(PointsMallReconciliationParam param);
|
||||
|
||||
Pagination<Record> recordPage(PointsMallReconciliationRecordPageParam param);
|
||||
|
||||
|
||||
+387
-75
@@ -2,35 +2,65 @@ package com.budwk.app.zhgh.pointsmall.reconciliation.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.dto.OrderInfoByReconciliationDTO;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.dto.OrderProInfoDTO;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.dto.QueryReconciliationInfoDTO;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.dto.ReconciliationResultNoticeDTO;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.dto.ReconciliationResultOrderDTO;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.dto.UnReconciledMsgNoticeDTO;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.service.MallReconciliationInfoQueryService;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.service.MallReconciliationResultNoticeService;
|
||||
import com.budwk.app.zhgh.pointsmall.mallbridge.service.MallUnReconciledMsgNoticeService;
|
||||
import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderSub;
|
||||
import com.budwk.app.zhgh.pointsmall.reconciliation.models.PointsMallReconciliationOrder;
|
||||
import com.budwk.app.zhgh.pointsmall.reconciliation.models.PointsMallReconciliationRecord;
|
||||
import com.budwk.app.zhgh.pointsmall.reconciliation.param.PointsMallReconciliationOrderPageParam;
|
||||
import com.budwk.app.zhgh.pointsmall.reconciliation.param.PointsMallReconciliationParam;
|
||||
import com.budwk.app.zhgh.pointsmall.reconciliation.param.PointsMallReconciliationRecordPageParam;
|
||||
import com.budwk.app.zhgh.pointsmall.reconciliation.service.PointsMallReconciliationService;
|
||||
import com.budwk.app.zhgh.pointsmall.supplier.models.PointsMallSupplier;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.entity.Record;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 对账功能
|
||||
*/
|
||||
@Slf4j
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class PointsMallReconciliationServiceImpl extends BaseServiceImpl<PointsMallReconciliationRecord> implements PointsMallReconciliationService {
|
||||
|
||||
@Inject
|
||||
private MallReconciliationInfoQueryService mallReconciliationInfoQueryService;
|
||||
|
||||
@Inject
|
||||
private MallUnReconciledMsgNoticeService unReconciledMsgNoticeService;
|
||||
|
||||
@Inject
|
||||
private MallReconciliationResultNoticeService reconciliationResultNoticeService;
|
||||
|
||||
public PointsMallReconciliationServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
@@ -53,37 +83,145 @@ public class PointsMallReconciliationServiceImpl extends BaseServiceImpl<PointsM
|
||||
return record == null || record.get("totalPoints") == null ? BigDecimal.ZERO : new BigDecimal(record.get("totalPoints").toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行对账
|
||||
*
|
||||
* @param reconciliationBO 入参
|
||||
*/
|
||||
@Override
|
||||
public String execute(PointsMallReconciliationParam param) {
|
||||
checkReconciliationParam(param);
|
||||
List<PointsMallOrderSub> orders = dao().query(PointsMallOrderSub.class, reconciliationCnd(param, ""));
|
||||
if (CollUtil.isEmpty(orders)) {
|
||||
return "未查询到待对账订单";
|
||||
}
|
||||
|
||||
String batchNo = DateUtil.format(new Date(), "yyyyMMddHHmmss") + IdUtil.fastSimpleUUID().substring(0, 6);
|
||||
int success = 0;
|
||||
int exception = 0;
|
||||
List<PointsMallReconciliationRecord> records = new ArrayList<>();
|
||||
|
||||
for (PointsMallOrderSub order : orders) {
|
||||
PointsMallReconciliationOrder supplierOrder = dao().fetch(PointsMallReconciliationOrder.class,
|
||||
Cnd.where("orderId", "=", order.getOrderId())
|
||||
.and("supplierId", "=", order.getSupplierId())
|
||||
.and("delFlag", "=", false));
|
||||
PointsMallReconciliationRecord record = buildRecord(order, supplierOrder, batchNo);
|
||||
if (record.getDiffType() == null || record.getDiffType() == 0) {
|
||||
success++;
|
||||
dao().update(PointsMallOrderSub.class, Chain.make("reconciliationStatus", 1), Cnd.where("id", "=", order.getId()));
|
||||
} else {
|
||||
exception++;
|
||||
dao().update(PointsMallOrderSub.class, Chain.make("reconciliationStatus", 2), Cnd.where("id", "=", order.getId()));
|
||||
public Result executeReconciliation(PointsMallReconciliationParam reconciliationBO) {
|
||||
Integer reconciliationType = reconciliationBO.getReconciliationType();
|
||||
List<String> orderIdList = null;
|
||||
// 校验参数
|
||||
if (reconciliationType == 1) {
|
||||
if (StrUtil.isBlank(reconciliationBO.getStartDate())) {
|
||||
return Result.error("请选择开始日期");
|
||||
}
|
||||
records.add(record);
|
||||
} else if (reconciliationType == 2) { // 历史异常订单对账
|
||||
if (StrUtil.isBlank(reconciliationBO.getOrderId())) {
|
||||
return Result.error("订单号不能为空");
|
||||
}
|
||||
orderIdList = StrUtil.splitTrim(reconciliationBO.getOrderId(), ",");
|
||||
} else {
|
||||
return Result.error("对账类型不正确");
|
||||
}
|
||||
|
||||
dao().insert(records);
|
||||
return "对账完成,批次号:" + batchNo + ",成功:" + success + ",异常:" + exception;
|
||||
// 从浦发积分商城订单表查询对账订单
|
||||
List<PointsMallOrderSub> orderInfoList = dao().query(PointsMallOrderSub.class, reconciliationCnd(reconciliationBO, ""));
|
||||
if (CollUtil.isEmpty(orderInfoList)) {
|
||||
return Result.error("浦发积分商城没有查询到对账订单数据");
|
||||
}
|
||||
|
||||
QueryReconciliationInfoDTO queryReconciliationInfoDTO = new QueryReconciliationInfoDTO();
|
||||
queryReconciliationInfoDTO.setSupplierId(reconciliationBO.getSupplierId());
|
||||
queryReconciliationInfoDTO.setReconciliationType(reconciliationType);
|
||||
queryReconciliationInfoDTO.setOrderId(orderIdList == null ? reconciliationBO.getOrderId() : String.join(",", orderIdList));
|
||||
queryReconciliationInfoDTO.setStartDate(reconciliationBO.getStartDate());
|
||||
queryReconciliationInfoDTO.setEndDate(reconciliationBO.getEndDate());
|
||||
queryReconciliationInfoDTO.setPage(1);
|
||||
queryReconciliationInfoDTO.setPageSize(100);
|
||||
// 通过对账接口从供应商拉取对账订单数据
|
||||
List<OrderInfoByReconciliationDTO> result = mallReconciliationInfoQueryService.queryReconciliationInfo(queryReconciliationInfoDTO);
|
||||
if (CollUtil.isEmpty(result)) {
|
||||
return Result.error("供应商侧没有拉取到对账订单数据");
|
||||
}
|
||||
String supplierId = reconciliationBO.getSupplierId();
|
||||
result.forEach(o -> o.setSupplierId(supplierId));
|
||||
// 根据供应商ID + 订单ID进行分组
|
||||
Map<String, List<OrderInfoByReconciliationDTO>> supplierOrderList = result.stream()
|
||||
.collect(Collectors.groupingBy(o -> String.join("-", o.getSupplierId(), o.getOrderId())));
|
||||
|
||||
// 根据供应商ID + 订单ID进行分组
|
||||
Map<String, List<PointsMallOrderSub>> pfOrderList = orderInfoList.stream()
|
||||
.collect(Collectors.groupingBy(o -> String.join("-", o.getSupplierId(), o.getOrderId())));
|
||||
|
||||
Set<String> pfKeySet = pfOrderList.keySet();
|
||||
Set<String> supplierKeySet = supplierOrderList.keySet();
|
||||
// 浦发商城和供应商都存在的订单
|
||||
Set<String> sameKeySet = pfKeySet.stream().filter(supplierKeySet::contains).collect(Collectors.toSet());
|
||||
// 1.浦发商城和供应商两边的《供应商ID + 订单ID》可以匹配上
|
||||
List<PointsMallReconciliationRecord> reconciliationList1 = getReconciliationResult(sameKeySet, pfOrderList, supplierOrderList);
|
||||
if (CollUtil.isNotEmpty(reconciliationList1)) {
|
||||
List<PointsMallReconciliationRecord> reconciliationList0 = reconciliationList1.stream()
|
||||
.filter(o -> o.getDiffType() == 3).collect(Collectors.toList());
|
||||
if (CollUtil.isNotEmpty(reconciliationList0)) {
|
||||
UnReconciledMsgNoticeDTO noticeDTO = getUnReconciledMsgNoticeDTO(reconciliationBO, reconciliationList0);
|
||||
noticeDTO.setOrderIds(reconciliationList0.stream().map(PointsMallReconciliationRecord::getOrderId).collect(Collectors.joining(",")));
|
||||
// 更新子订单状态为对账异常
|
||||
subOrderReconciliationUpdate(reconciliationList0, 2);
|
||||
// 对账异常结果通知接口
|
||||
unReconciledMsgNoticeService.unReconciledMsgNotice(noticeDTO);
|
||||
}
|
||||
|
||||
List<PointsMallReconciliationRecord> reconciliationSuccessList = reconciliationList1.stream()
|
||||
.filter(o -> o.getDiffType() == 0).collect(Collectors.toList());
|
||||
if (CollUtil.isNotEmpty(reconciliationSuccessList)) {
|
||||
// 更新子订单状态为对账完成
|
||||
subOrderReconciliationUpdate(reconciliationSuccessList, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 2.浦发积分商城已确认收货,对账接口未返回
|
||||
List<PointsMallReconciliationRecord> reconciliationList2 = orderNotReturn(pfKeySet, supplierKeySet, pfOrderList);
|
||||
if (CollUtil.isNotEmpty(reconciliationList2)) {
|
||||
reconciliationList1.addAll(reconciliationList2);
|
||||
UnReconciledMsgNoticeDTO noticeDTO = getUnReconciledMsgNoticeDTO(reconciliationBO, reconciliationList2);
|
||||
noticeDTO.setOrderIds(reconciliationList2.stream().map(PointsMallReconciliationRecord::getOrderId).collect(Collectors.joining(",")));
|
||||
// 更新子订单状态为对账异常
|
||||
subOrderReconciliationUpdate(reconciliationList2, 2);
|
||||
// 对账异常结果通知接口
|
||||
unReconciledMsgNoticeService.unReconciledMsgNotice(noticeDTO);
|
||||
}
|
||||
|
||||
// 3.浦发积分商城不存在此订单,无法对账
|
||||
List<PointsMallReconciliationRecord> reconciliationList3 = orderNotExist(supplierKeySet, pfKeySet, supplierOrderList);
|
||||
if (CollUtil.isNotEmpty(reconciliationList3)) {
|
||||
reconciliationList1.addAll(reconciliationList3);
|
||||
UnReconciledMsgNoticeDTO noticeDTO = getUnReconciledMsgNoticeDTO(reconciliationBO, reconciliationList3);
|
||||
noticeDTO.setOrderIds(reconciliationList3.stream().map(PointsMallReconciliationRecord::getOrderId).collect(Collectors.joining(",")));
|
||||
// 更新子订单状态为对账异常
|
||||
// subOrderReconciliationUpdate(reconciliationList3, 2);
|
||||
// 对账异常结果通知接口
|
||||
unReconciledMsgNoticeService.unReconciledMsgNotice(noticeDTO);
|
||||
}
|
||||
|
||||
if (CollUtil.isNotEmpty(reconciliationList1)) {
|
||||
String startDate = reconciliationBO.getStartDate();
|
||||
String endDate = reconciliationBO.getEndDate();
|
||||
String startEndDate = StrUtil.blankToDefault(startDate, "history").replace("-", "")
|
||||
+ StrUtil.blankToDefault(endDate, "").replace("-", "");
|
||||
String loginName = StrUtil.blankToDefault(SecurityUtil.getUserId(), "console");
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
String yyyyMMddHHmm = now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmm"));
|
||||
reconciliationList1.forEach(o ->
|
||||
o.setBatchNo(String.format("%s-%s-%s", startEndDate, loginName, yyyyMMddHHmm)));
|
||||
// 把对账结果写入数据库
|
||||
dao().insert(reconciliationList1);
|
||||
|
||||
ReconciliationResultNoticeDTO resultNoticeDTO = new ReconciliationResultNoticeDTO();
|
||||
resultNoticeDTO.setSupplierId(reconciliationBO.getSupplierId());
|
||||
resultNoticeDTO.setReconciliationBatchNo(reconciliationList1.get(0).getBatchNo());
|
||||
resultNoticeDTO.setReconciliationTime(now.toString());
|
||||
resultNoticeDTO.setReconciliationResults(reconciliationList1.stream().map(o -> {
|
||||
ReconciliationResultOrderDTO resultOrderDTO = new ReconciliationResultOrderDTO();
|
||||
resultOrderDTO.setOrderId(o.getOrderId());
|
||||
resultOrderDTO.setUserId(o.getUserId());
|
||||
resultOrderDTO.setReconciliationStatus(o.getDiffType() == 0 ? 1 : 2);
|
||||
resultOrderDTO.setDiffType(o.getDiffType());
|
||||
resultOrderDTO.setDiffReason(o.getDiffReason());
|
||||
resultOrderDTO.setPlatformTotalPrice(o.getPTotalPrice());
|
||||
resultOrderDTO.setPlatformCashAmount(o.getPCashAmount());
|
||||
resultOrderDTO.setPlatformPointsPrice(o.getPPointsPrice());
|
||||
resultOrderDTO.setPlatformRefundPrice(o.getPRefund());
|
||||
resultOrderDTO.setSupplierTotalPrice(o.getSTotalPrice());
|
||||
resultOrderDTO.setSupplierCashAmount(o.getSCashAmount());
|
||||
resultOrderDTO.setSupplierPointsPrice(o.getSPointsPrice());
|
||||
resultOrderDTO.setSupplierRefundPrice(o.getSRefund());
|
||||
return resultOrderDTO;
|
||||
}).collect(Collectors.toList()));
|
||||
reconciliationResultNoticeService.reconciliationResultNotice(resultNoticeDTO);
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -192,54 +330,228 @@ public class PointsMallReconciliationServiceImpl extends BaseServiceImpl<PointsM
|
||||
}
|
||||
}
|
||||
|
||||
private PointsMallReconciliationRecord buildRecord(PointsMallOrderSub order, PointsMallReconciliationOrder supplierOrder, String batchNo) {
|
||||
PointsMallReconciliationRecord record = new PointsMallReconciliationRecord();
|
||||
record.setSupplierId(order.getSupplierId());
|
||||
record.setOrderId(order.getOrderId());
|
||||
record.setUserId(order.getUserId());
|
||||
record.setPRefund(nullToZero(order.getRefund()));
|
||||
record.setPTotalPrice(nullToZero(order.getTotalPrice()));
|
||||
record.setPCashAmount(nullToZero(order.getWPayOrAPay()));
|
||||
record.setPPointsPrice(nullToZero(order.getPointsPrice()));
|
||||
record.setBatchNo(batchNo);
|
||||
record.setNoticeStatus(0);
|
||||
record.setPushTime(0);
|
||||
|
||||
if (supplierOrder == null) {
|
||||
record.setSRefund(BigDecimal.ZERO);
|
||||
record.setSTotalPrice(record.getPTotalPrice());
|
||||
record.setSCashAmount(record.getPCashAmount());
|
||||
record.setSPointsPrice(record.getPPointsPrice());
|
||||
record.setDiffType(0);
|
||||
record.setDiffReason("未获取到供应商侧对账订单,按平台订单确认");
|
||||
return record;
|
||||
}
|
||||
|
||||
record.setSRefund(BigDecimal.ZERO);
|
||||
record.setSTotalPrice(nullToZero(supplierOrder.getTotalPrice()));
|
||||
record.setSCashAmount(BigDecimal.ZERO);
|
||||
record.setSPointsPrice(nullToZero(supplierOrder.getTotalPrice()));
|
||||
|
||||
List<String> reasons = new ArrayList<>();
|
||||
if (!amountEquals(record.getPTotalPrice(), record.getSTotalPrice())) {
|
||||
reasons.add("订单总金额不一致");
|
||||
}
|
||||
if (!amountEquals(record.getPPointsPrice(), record.getSPointsPrice())) {
|
||||
reasons.add("积分金额不一致");
|
||||
}
|
||||
if (!Objects.equals(order.getUserId(), supplierOrder.getUserId())) {
|
||||
reasons.add("用户ID不一致");
|
||||
}
|
||||
record.setDiffType(reasons.isEmpty() ? 0 : 1);
|
||||
record.setDiffReason(reasons.isEmpty() ? "对账一致" : String.join(";", reasons));
|
||||
return record;
|
||||
private void subOrderReconciliationUpdate(List<PointsMallReconciliationRecord> reconciliationList, Integer reconciliationStatus) {
|
||||
// 更新子订单状态为对账异常
|
||||
reconciliationList.forEach(o -> dao().update(PointsMallOrderSub.class,
|
||||
Chain.make("reconciliationStatus", reconciliationStatus),
|
||||
Cnd.where("orderId", "=", o.getOrderId()).and("supplierId", "=", o.getSupplierId())));
|
||||
}
|
||||
|
||||
private BigDecimal nullToZero(BigDecimal value) {
|
||||
return value == null ? BigDecimal.ZERO : value;
|
||||
private UnReconciledMsgNoticeDTO getUnReconciledMsgNoticeDTO(PointsMallReconciliationParam reconciliationBO,
|
||||
List<PointsMallReconciliationRecord> reconciliationList2) {
|
||||
UnReconciledMsgNoticeDTO noticeDTO = new UnReconciledMsgNoticeDTO();
|
||||
noticeDTO.setUniqueSeqNo("111");
|
||||
noticeDTO.setToken("token");
|
||||
noticeDTO.setSupplierId(reconciliationBO.getSupplierId());
|
||||
noticeDTO.setStartDate(reconciliationBO.getStartDate());
|
||||
noticeDTO.setEndDate(reconciliationBO.getEndDate());
|
||||
PointsMallReconciliationRecord reconciliation = reconciliationList2.get(0);
|
||||
noticeDTO.setUnReconciledType(reconciliation.getDiffType() + "");
|
||||
noticeDTO.setUnReconciledMsg(reconciliation.getDiffReason());
|
||||
return noticeDTO;
|
||||
}
|
||||
|
||||
private boolean amountEquals(BigDecimal left, BigDecimal right) {
|
||||
return nullToZero(left).compareTo(nullToZero(right)) == 0;
|
||||
/**
|
||||
* 浦发积分商城已确认收货,对账接口未返回
|
||||
*
|
||||
* @param pfKeySet 浦发key
|
||||
* @param supplierKeySet 供应商key
|
||||
* @param pfOrderList 浦发商城对账订单
|
||||
* @return 异常订单
|
||||
*/
|
||||
private List<PointsMallReconciliationRecord> orderNotReturn(Set<String> pfKeySet, Set<String> supplierKeySet,
|
||||
Map<String, List<PointsMallOrderSub>> pfOrderList) {
|
||||
List<PointsMallReconciliationRecord> reconciliationList = new ArrayList<>();
|
||||
pfKeySet.stream().filter(key -> !supplierKeySet.contains(key)).forEach(key -> {
|
||||
List<PointsMallOrderSub> pfOrders = pfOrderList.get(key);
|
||||
if (CollUtil.isNotEmpty(pfOrders)) {
|
||||
reconciliationList.add(buildReconciliationRecord(null, pfOrders.get(0), 1, "浦发积分商城已确认收货,对账接口未返回"));
|
||||
}
|
||||
});
|
||||
return reconciliationList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 浦发积分商城不存在此订单,无法对账
|
||||
*
|
||||
* @param supplierKeySet 供应商key
|
||||
* @param pfKeySet 浦发key
|
||||
* @param supplierOrderList 供应商对账订单
|
||||
* @return 异常订单
|
||||
*/
|
||||
private List<PointsMallReconciliationRecord> orderNotExist(Set<String> supplierKeySet, Set<String> pfKeySet,
|
||||
Map<String, List<OrderInfoByReconciliationDTO>> supplierOrderList) {
|
||||
List<PointsMallReconciliationRecord> reconciliationList = new ArrayList<>();
|
||||
supplierKeySet.stream().filter(key -> !pfKeySet.contains(key)).forEach(key -> {
|
||||
List<OrderInfoByReconciliationDTO> supplierOrders = supplierOrderList.get(key);
|
||||
if (CollUtil.isNotEmpty(supplierOrders)) {
|
||||
reconciliationList.add(buildReconciliationRecord(supplierOrders.get(0), null, 2, "浦发积分商城不存在此订单,无法对账"));
|
||||
}
|
||||
});
|
||||
return reconciliationList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 浦发商城和供应商两边的《供应商ID + 订单ID》可以匹配上
|
||||
*
|
||||
* @param sameKeySet 双方都存在的订单ID
|
||||
* @param pfOrderList 浦发商城的订单
|
||||
* @param supplierOrderList 供应商的订单
|
||||
* @return 对账结果
|
||||
*/
|
||||
private List<PointsMallReconciliationRecord> getReconciliationResult(Set<String> sameKeySet,
|
||||
Map<String, List<PointsMallOrderSub>> pfOrderList,
|
||||
Map<String, List<OrderInfoByReconciliationDTO>> supplierOrderList) {
|
||||
List<PointsMallReconciliationRecord> reconciliationList = new ArrayList<>();
|
||||
sameKeySet.forEach(key -> {
|
||||
List<PointsMallOrderSub> pOrderList = pfOrderList.get(key);
|
||||
List<OrderInfoByReconciliationDTO> sOrderList = supplierOrderList.get(key);
|
||||
BigDecimal pfPointSum = pOrderList.stream()
|
||||
.map(o -> (o.getPointsPrice() == null ? BigDecimal.ZERO : o.getPointsPrice())
|
||||
.subtract(o.getRefund() == null ? BigDecimal.ZERO : o.getRefund()))
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
BigDecimal supplierPointSum = sOrderList.stream()
|
||||
.map(OrderInfoByReconciliationDTO::getTotalPrice)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
// 根据供应商ID和订单ID比对积分总金额是否一致
|
||||
if (pfPointSum.compareTo(supplierPointSum) != 0) {
|
||||
reconciliationList.add(buildReconciliationRecord(sOrderList.get(0), pOrderList.get(0), 3, "订单内容不一致,订单金额不一致"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (CollUtil.isNotEmpty(pOrderList)) {
|
||||
OrderInfoByReconciliationDTO sOrder = sOrderList.get(0);
|
||||
PointsMallOrderSub pfOrder = pOrderList.get(0);
|
||||
PointsMallReconciliationRecord reconciliation = buildReconciliationRecord(sOrder, pfOrder, 0, "无差异");
|
||||
// 比对商品明细的sku,商品数量,商品价格,商品税率是否一致
|
||||
if (CollUtil.isNotEmpty(sOrderList)) {
|
||||
String productInfo = pfOrder.getExtJson();
|
||||
// 解析积分商品下的商品明细
|
||||
List<OrderProInfoDTO> pfOrderProList = JSONUtil.toList(productInfo, OrderProInfoDTO.class);
|
||||
// 处理商品名称、价格、税率的小数位(不参与比较的字段)
|
||||
handleField(pfOrderProList);
|
||||
|
||||
// 从对账接口获取的订单商品
|
||||
OrderInfoByReconciliationDTO supplierOrder = sOrderList.get(0);
|
||||
List<OrderProInfoDTO> supplierOrderProList = supplierOrder.getOrderProInfos();
|
||||
handleField(supplierOrderProList);
|
||||
|
||||
// 比较双方商品明细是否一致
|
||||
if (!compareProduct(pfOrderProList, supplierOrderProList)) {
|
||||
reconciliation.setDiffType(3);
|
||||
reconciliation.setDiffReason("订单内容不一致,商品明细不一致");
|
||||
}
|
||||
}
|
||||
reconciliationList.add(reconciliation);
|
||||
}
|
||||
});
|
||||
return reconciliationList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理商品价格和税率字段的小数位,保证对比的时候小数位一致
|
||||
*
|
||||
* @param productList 订单下的商品集合
|
||||
*/
|
||||
private void handleField(List<OrderProInfoDTO> productList) {
|
||||
// 商品名称不参与比较,价格和税率小数点位数处理
|
||||
productList.forEach(o -> {
|
||||
o.setName(null);
|
||||
if (o.getPrice() != null) {
|
||||
o.setPrice(o.getPrice().setScale(2, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (o.getTaxRate() != null) {
|
||||
o.setTaxRate(o.getTaxRate().setScale(6, RoundingMode.HALF_UP));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较两个list<bean>是否完全一致,不考虑顺序
|
||||
*
|
||||
* @param list1 集合1
|
||||
* @param list2 集合2
|
||||
* @return 是否相同
|
||||
*/
|
||||
private boolean compareProduct(List<OrderProInfoDTO> list1, List<OrderProInfoDTO> list2) {
|
||||
// 1. 如果两个列表是同一个引用,直接返回 true
|
||||
if (list1 == list2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. 如果其中有一个为 null,或者商品总数不一致,直接返回 false
|
||||
if (list1 == null || list2 == null || list1.size() != list2.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 遍历第一个订单的商品,检查是否都能在第二个订单中找到匹配的商品
|
||||
for (OrderProInfoDTO p1 : list1) {
|
||||
boolean foundMatch = false;
|
||||
for (OrderProInfoDTO p2 : list2) {
|
||||
// 通过sku+number+price+taxRate相同判定为商品信息一致
|
||||
if (Objects.equals(p1.getSku(), p2.getSku()) &&
|
||||
Objects.equals(p1.getNumber(), p2.getNumber()) &&
|
||||
compareBigDecimal(p1.getPrice(), p2.getPrice()) &&
|
||||
compareBigDecimal(p1.getTaxRate(), p2.getTaxRate())) {
|
||||
foundMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundMatch) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean compareBigDecimal(BigDecimal a, BigDecimal b) {
|
||||
// 两者都为空,视为相等
|
||||
if (a == null && b == null) {
|
||||
return true;
|
||||
}
|
||||
// 只有一个为空,视为不相等
|
||||
if (a == null || b == null) {
|
||||
return false;
|
||||
}
|
||||
// 都不为空,使用compareTo 比较数值
|
||||
return a.compareTo(b) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单积分对账数据赋值
|
||||
*
|
||||
* @param sOrder 对账接口返回的订单对账数据
|
||||
* @param pOrder 子订单表的订单数据
|
||||
* @param diffType 异常类型
|
||||
* @param diffReason 异常原因
|
||||
* @return 对账结果
|
||||
*/
|
||||
private PointsMallReconciliationRecord buildReconciliationRecord(OrderInfoByReconciliationDTO sOrder,
|
||||
PointsMallOrderSub pOrder,
|
||||
int diffType, String diffReason) {
|
||||
PointsMallReconciliationRecord reconciliation = new PointsMallReconciliationRecord();
|
||||
reconciliation.setDiffType(diffType);
|
||||
reconciliation.setDiffReason(diffReason);
|
||||
reconciliation.setNoticeStatus(0);
|
||||
reconciliation.setPushTime(0);
|
||||
if (sOrder != null) {
|
||||
// 对账接口返回数据
|
||||
reconciliation.setSupplierId(sOrder.getSupplierId());
|
||||
reconciliation.setOrderId(sOrder.getOrderId());
|
||||
reconciliation.setSTotalPrice(sOrder.getTotalPrice());
|
||||
reconciliation.setSPointsPrice(sOrder.getPointsPrice());
|
||||
reconciliation.setSCashAmount(sOrder.getWPayOrAPay());
|
||||
}
|
||||
if (pOrder != null) {
|
||||
// 订单表里数据
|
||||
reconciliation.setSupplierId(pOrder.getSupplierId());
|
||||
reconciliation.setOrderId(pOrder.getOrderId());
|
||||
reconciliation.setUserId(pOrder.getUserId());
|
||||
reconciliation.setPTotalPrice(pOrder.getTotalPrice());
|
||||
reconciliation.setPPointsPrice(pOrder.getPointsPrice());
|
||||
reconciliation.setPCashAmount(pOrder.getWPayOrAPay());
|
||||
reconciliation.setPRefund(pOrder.getRefund());
|
||||
}
|
||||
return reconciliation;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user