我代码能力很差,你解释一下package com.foonsu.efenxiao.biz.handler;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.csv.CsvReadConfig;
import cn.hutool.core.text.csv.CsvReader;
import cn.hutool.core.text.csv.CsvRow;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.foonsu.efenxiao.biz.config.CidReadListener;
import com.foonsu.efenxiao.biz.feign.OrderClientWrapper;
import com.foonsu.efenxiao.biz.util.OrderUtil;
import com.foonsu.efenxiao.order.dto.CidOrder;
import com.foonsu.efenxiao.biz.vo.ImportCidAccountVO;
import com.foonsu.efenxiao.biz.vo.ProgressVo;
import com.foonsu.efenxiao.common.utils.CollectionsUtil;
import com.foonsu.efenxiao.order.dto.OrderDTO;
import com.foonsu.efenxiao.order.dto.OrderExtendDto;
import com.foonsu.efenxiao.order.dto.OrderGoodsDto;
import com.foonsu.efenxiao.order.dto.OrderTradeDto;
import com.foonsu.efenxiao.order.dubbo.CidClient;
import com.foonsu.efenxiao.order.dubbo.OrderClient;
import com.foonsu.efenxiao.order.entity.CidAccount;
import com.foonsu.efenxiao.order.entity.CidAccountingDetail;
import com.foonsu.efenxiao.order.entity.CidPlan;
import com.foonsu.efenxiao.order.entity.Order;
import com.foonsu.efenxiao.order.vo.CidAccountSearchVO;
import com.foonsu.efenxiao.order.vo.CidOrderConsumption;
import com.foonsu.efenxiao.order.vo.CidPlanSearchResp;
import com.foonsu.efenxiao.order.vo.CidPlanSearchVo;
import com.foonsu.efenxiao.order.vo.req.AdvertiserAccount;
import com.foonsu.efenxiao.order.vo.req.HistoryPushAccountReq;
import com.foonsu.efenxiao.platform.dubbo.GoodsClient;
import com.foonsu.efenxiao.platform.entity.CidGoodsPriceHistory;
import com.foonsu.efenxiao.platform.entity.PlatformGoods;
import com.foonsu.efenxiao.platform.vo.PlatformGoodsSkuVO;
import com.foonsu.efenxiao.platform.vo.PlatformGoodsVO;
import com.foonsu.efenxiao.search.dubbo.OrderSearchClient;
import com.foonsu.efenxiao.search.vo.ordersearch.*;
import com.foonsu.efenxiao.webutil.progress.impl.CidImportAccountProgress;
import com.foonsu.efenxiao.webutil.progress.impl.CidImportStatementProgress;
import com.foonsu.framework.boot.common.utils.MD5Utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Component
@Slf4j
public class CidShopBillHandler {
private static final Pattern PATTERN = Pattern.compile("\\d{6}-\\d{15}");
@Resource
@Qualifier("cidHandleThreadPoolTaskExecutor")
ThreadPoolTaskExecutor cidHandleThreadPoolTaskExecutor;
@DubboReference
private OrderClient orderClient;
@DubboReference
private CidClient cidClient;
@DubboReference
private OrderSearchClient orderSearchClient;
@DubboReference
private GoodsClient goodsClient;
@Resource
private OrderClientWrapper orderClientWrapper;
@Resource
private CidImportStatementProgress cidImportStatementProgress;
@Resource
private CidImportAccountProgress cidImportAccountProgress;
@Value("${cid.tenant-id}")
private String tenantId;
public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public CidSearchOrderResp searchOrder(SearchOrderReq req, String tenantId) {
SearchOrderBackendParam backendParam = new SearchOrderBackendParam();
backendParam.setTenantId(tenantId);
EsSearchOrderResp resp = orderSearchClient.searchCidOrder(req, backendParam);
CidSearchOrderResp cidSearchOrderResp = new CidSearchOrderResp();
if (!resp.getOrderNos().isEmpty()) {
List<String> allOrderNos = resp.getOrderNos().stream().flatMap(Collection::stream).collect(Collectors.toList());
List<Order> ordersData = orderClientWrapper.queryByOrderNos(allOrderNos);
List<CidOrderVO> cidOrderVOS = this.convertData(resp, ordersData);
cidSearchOrderResp.setData(cidOrderVOS);
}
cidSearchOrderResp.setTotal(resp.getTotalCount().intValue());
cidSearchOrderResp.setCurrent(req.getPageNo());
cidSearchOrderResp.setSize(req.getPageSize());
cidSearchOrderResp.setPages(cidSearchOrderResp.getTotal() / req.getPageSize() + (cidSearchOrderResp.getTotal() % req.getPageSize() > 0 ? 1 : 0));
return cidSearchOrderResp;
}
private List<CidOrderVO> convertData(EsSearchOrderResp esSearchOrderResp, List<Order> orders) {
List<CidOrderVO> cidOrderVOS = new ArrayList<>();
for (List<String> orderNos : esSearchOrderResp.getOrderNos()) {
List<Order> onelineOrders = orders.stream().filter(t -> orderNos.contains(t.getOrderNo())).collect(Collectors.toList());
if (!onelineOrders.isEmpty()) {
Map<String, List<Order>> tradeNoOrders = onelineOrders.stream().collect(Collectors.groupingBy(Order::getTradeNo));
for (String tradeNo : tradeNoOrders.keySet()) {
List<Order> splitOrders = tradeNoOrders.get(tradeNo);
List<OrderDTO> orderDTOS = OrderUtil.convertToDto(splitOrders);
// cid默认单商品订单
OrderDTO orderDTO = orderDTOS.get(0);
CidOrderVO cidOrderVO = new CidOrderVO();
cidOrderVO.setShopName(orderDTO.getShopName());
cidOrderVO.setJlId(orderDTO.getOrderGoodsDtoList().get(0).getBindJlId());
cidOrderVO.setTradeNo(orderDTO.getTradeNo());
cidOrderVO.setOrderNo(orderDTO.getOrderNo());
cidOrderVO.setPayAmount(orderDTO.getOrderTradeDto().getPayAmount());
CidOrderExtendVO cidOrderExtendVO = JSON.parseObject(orderDTO.getExtendInfo(), CidOrderExtendVO.class);
cidOrderVO.setCidOrderExtendVO(cidOrderExtendVO);
List<CidGoodsVo> goodsVos = JSON.parseArray(orderDTO.getGoods(), CidGoodsVo.class);
cidOrderVO.setGoods(goodsVos);
cidOrderVOS.add(cidOrderVO);
}
}
}
return cidOrderVOS;
}
public void compute(String tenantId, List<String> tradeNos) {
Map<String, List<CidAccountingDetail>> accountDetailGroupByTradeNo = cidClient.queryAllImportCidTradeNo(tenantId, null, tradeNos)
.stream().collect(Collectors.groupingBy(CidAccountingDetail::getTradeNo));
List<String> importCidTradeNos = new ArrayList<>(accountDetailGroupByTradeNo.keySet());
List<List<String>> reqsList = CollectionsUtil.splitListToThreads(importCidTradeNos, 1500, 20);
for (List<String> orders : reqsList) {
cidHandleThreadPoolTaskExecutor.submit(() -> {
for (String order : orders) {
this.handleOrder(order, tenantId, accountDetailGroupByTradeNo.get(order));
}
});
}
}
public void compute(List<CidAccountingDetail> accountingDetails) {
accountingDetails = accountingDetails.stream().sorted(Comparator.comparing(CidAccountingDetail::getTradeNo)).collect(Collectors.toList());
CollectionsUtil.batchDeal(accountingDetails, 500, accountingDetailList -> {
List<CidOrder> cidOrders = new ArrayList<>();
Set<String> tradeNos = accountingDetailList.stream().map(CidAccountingDetail::getTradeNo).collect(Collectors.toSet());
Map<String, List<LocalDateTime>> occurTimeByTradeNos = cidClient.queryOccurentTimeByTradeNos(tradeNos);
Map<String, List<CidAccountingDetail>> accountDetailGroupByTradeNo = accountingDetailList.stream().collect(Collectors.groupingBy(CidAccountingDetail::getTradeNo));
List<Order> orders = orderClient.queryOrderByTradeNos(new ArrayList<>(tradeNos));
if (CollectionsUtil.isEmpty(orders)) return;
Map<String, Order> ordergroupbyTradeNo = orders.stream().collect(Collectors.toMap(Order::getTradeNo, Function.identity()));
Map<String, String> ordersGroupByProductIdMap = orders.stream().collect(Collectors.toMap(Order::getTradeNo, order -> {
List<OrderGoodsDto> orderGoodsDtos = JSONArray.parseArray(order.getGoods(), OrderGoodsDto.class);
return orderGoodsDtos.get(0).getProductId();
}));
List<String> skuIds = orders.stream().map(order -> {
List<OrderGoodsDto> orderGoodsDtos = JSONArray.parseArray(order.getGoods(), OrderGoodsDto.class);
return orderGoodsDtos.get(0).getSkuId();
}).distinct().collect(Collectors.toList());
Map<String, List<CidGoodsPriceHistory>> cidGoodsPriceGroupBySkuIdMap = goodsClient.selectCidGoodsPriceHistory(tenantId, null, skuIds)
.stream().collect(Collectors.groupingBy(CidGoodsPriceHistory::getSkuId));
List<String> productIds = ordersGroupByProductIdMap.values().stream().distinct().collect(Collectors.toList());
Map<String, PlatformGoodsVO> goodsGroupByProductId = goodsClient.selectCidGoods(tenantId, productIds, null)
.stream().collect(Collectors.toMap(PlatformGoodsVO::getProductId, Function.identity()));
accountDetailGroupByTradeNo.forEach((tradeNo, accountDetails) -> {
if (ordergroupbyTradeNo.containsKey(tradeNo)) {
Order order = ordergroupbyTradeNo.get(tradeNo);
String productId = ordersGroupByProductIdMap.get(tradeNo);
if (goodsGroupByProductId.containsKey(productId)) {
PlatformGoodsVO platformGoodsVO = goodsGroupByProductId.get(productId);
OrderExtendDto orderExtendDto = computeGoodsProfit(platformGoodsVO, order, cidGoodsPriceGroupBySkuIdMap);
cidOrders.addAll(covertCidOrders(accountDetails, orderExtendDto, tradeNo, platformGoodsVO.getBindJlId(), occurTimeByTradeNos.get(tradeNo)));
}
}
});
if (cidOrders.isEmpty()) return;
orderSearchClient.saveCidOrders(cidOrders);
}, cidHandleThreadPoolTaskExecutor);
}
private CidOrder createEsCidOrder(String tenantId, String bindJlId, String tradeNO) {
CidOrder esCidOrder = new CidOrder();
esCidOrder.setAccountId(bindJlId);
esCidOrder.setTenantId(tenantId);
esCidOrder.setTradeNo(tradeNO);
return esCidOrder;
}
private List<CidOrder> covertCidOrders(List<CidAccountingDetail> accountDetails, OrderExtendDto orderExtendDto, String tradeNO, String bindJlId, List<LocalDateTime> occurTimes) {
List<CidOrder> esCidOrders = accountDetails.stream().map(accountingDetail -> {
CidOrder cidOrder = createEsCidOrder(tenantId, bindJlId, tradeNO);
cidOrder.setId(accountingDetail.getUniqueId());
cidOrder.setOccurrenceTime(Collections.singletonList(LocalDateTime.parse(accountingDetail.getOccurrenceTime(), DATETIME_FORMATTER)));
cidOrder.setRefundType(orderExtendDto.getRefundType());
BigDecimal incomeAmount = accountingDetail.getIncomeAmount() == null ? BigDecimal.ZERO : accountingDetail.getIncomeAmount();
BigDecimal expenditureAmount = accountingDetail.getExpenditureAmount() == null ? BigDecimal.ZERO : accountingDetail.getExpenditureAmount();
cidOrder.setOrderProfit(incomeAmount.add(expenditureAmount));
switch (accountingDetail.getAccountingType()) {
case "扣款":
cidOrder.setDeductionSum(accountingDetail.getExpenditureAmount());
switch (accountingDetail.getServiceType()) {
case "0040002":
cidOrder.setSalesCompensate(accountingDetail.getExpenditureAmount());
break;
case "0040003":
cidOrder.setExpressCompensate(accountingDetail.getExpenditureAmount());
break;
case "0040004":
cidOrder.setDelaySendGoods(accountingDetail.getExpenditureAmount());
break;
case "0040005":
cidOrder.setFalseSendGoods(accountingDetail.getExpenditureAmount());
break;
case "0040006":
cidOrder.setOutOfStock(accountingDetail.getExpenditureAmount());
}
break;
case "技术服务费":
cidOrder.setTechnologyFee(accountingDetail.getExpenditureAmount());
break;
case "多多进宝":
cidOrder.setDdjb(accountingDetail.getExpenditureAmount());
}
return cidOrder;
}).collect(Collectors.toList());
CidOrder esCidOrder = createEsCidOrder(tenantId, bindJlId, tradeNO);
esCidOrder.setOrderProfit(BigDecimal.ZERO.subtract(orderExtendDto.getPurchaseExpressFee()));
esCidOrder.setId(tradeNO);
esCidOrder.setOccurrenceTime(occurTimes.stream().distinct().collect(Collectors.toList()));
esCidOrders.add(esCidOrder);
return esCidOrders;
}
private OrderExtendDto computeGoodsProfit(PlatformGoodsVO platformGoods, Order order, Map<String, List<CidGoodsPriceHistory>> cidGoodsPriceGroupBySkuIdMap) {
OrderTradeDto orderTradeDto = JSON.parseObject(order.getTrade(), OrderTradeDto.class);
List<OrderGoodsDto> orderGoodsDtos = JSONArray.parseArray(order.getGoods(), OrderGoodsDto.class);
OrderGoodsDto orderGoodsDto = orderGoodsDtos.get(0);
OrderExtendDto orderExtendDto = new OrderExtendDto();
List<PlatformGoodsSkuVO> skuVOS = platformGoods.getGoodsSkuList().stream().filter(sku -> sku.getSkuId().equals(orderGoodsDto.getSkuId())).collect(Collectors.toList());
if (!skuVOS.isEmpty()) {
PlatformGoodsSkuVO platformGoodsSkuVO = skuVOS.get(0);
BigDecimal purchasePrice = platformGoodsSkuVO.getPurchaseUnitPrice();
BigDecimal expressFee = platformGoodsSkuVO.getExpressFee();
String skuId = platformGoodsSkuVO.getSkuId();
if (cidGoodsPriceGroupBySkuIdMap.containsKey(skuId)) {
List<CidGoodsPriceHistory> cidGoodsPriceHistories = cidGoodsPriceGroupBySkuIdMap.get(skuId);
for (CidGoodsPriceHistory cidGoodsPriceHistory : cidGoodsPriceHistories) {
if (cidGoodsPriceHistory.getType() == 2 && DateUtil.toLocalDateTime(new Date(orderTradeDto.getSourceCreateDate())).isAfter(cidGoodsPriceHistory.getUpdateTime())) {
purchasePrice = cidGoodsPriceHistory.getPrice();
}
if (cidGoodsPriceHistory.getType() == 3 && DateUtil.toLocalDateTime(new Date(orderTradeDto.getSourceCreateDate())).isAfter(cidGoodsPriceHistory.getUpdateTime())) {
expressFee = cidGoodsPriceHistory.getPrice();
}
}
}
orderExtendDto.setPurchasePrice(purchasePrice == null ? BigDecimal.ZERO : purchasePrice);
orderExtendDto.setExpressFee(expressFee == null ? BigDecimal.ZERO : expressFee);
}
if (orderGoodsDto.getRefundType() != null) {
orderExtendDto.setPurchaseExpressFee(orderExtendDto.getExpressFee());
orderExtendDto.setRefundType(orderGoodsDto.getRefundType());
} else {
if (orderExtendDto.getPurchasePrice() != null && orderExtendDto.getExpressFee() != null) {
orderExtendDto.setPurchaseExpressFee(orderExtendDto.getPurchasePrice().add(orderExtendDto.getExpressFee()));
}
}
return orderExtendDto;
}
private void handleOrder(String importCidTradeNo, String tenantId, List<CidAccountingDetail> cidAccountingDetails) {
if (StringUtil.isBlank(importCidTradeNo)) {
return;
}
List<Order> orders = orderClient.queryOrderByTradeNo(importCidTradeNo);
if (orders.isEmpty()) {
log.info("对账订单为空");
return;
}
// 默认都是单商品订单
Order order = orders.get(0);
List<CidAccountingDetail> accountingDetails = cidClient.queryAccountingDetailByTradeNo(tenantId, importCidTradeNo);
if (accountingDetails.isEmpty()) {
log.info("对账明细为空");
return;
}
OrderTradeDto orderTradeDto = JSON.parseObject(order.getTrade(), OrderTradeDto.class);
List<OrderGoodsDto> orderGoodsDtos = JSONArray.parseArray(order.getGoods(), OrderGoodsDto.class);
OrderGoodsDto orderGoodsDto = orderGoodsDtos.get(0);
List<PlatformGoodsVO> platformGoodsVOS = goodsClient.selectCidGoods(tenantId, null, null);
if (platformGoodsVOS.isEmpty()) {
return;
}
PlatformGoodsVO platformGoods = platformGoodsVOS.get(0);
OrderExtendDto orderExtendDto = StringUtils.isBlank(order.getExtendInfo()) ? new OrderExtendDto() : JSON.parseObject(order.getExtendInfo(), OrderExtendDto.class);
BigDecimal orderNum = BigDecimal.ZERO;
BigDecimal deductionSum = BigDecimal.ZERO;
BigDecimal technologyFee = BigDecimal.ZERO;
BigDecimal ddjb = BigDecimal.ZERO;
BigDecimal salesCompensate = BigDecimal.ZERO;// 售后补偿
BigDecimal expressCompensate = BigDecimal.ZERO;// 运费补偿
BigDecimal delaySendGoods = BigDecimal.ZERO;// 延迟发货
BigDecimal falseSendGoods = BigDecimal.ZERO;// 虚假发货
BigDecimal outOfStock = BigDecimal.ZERO;// 缺货
for (CidAccountingDetail accountingDetail : accountingDetails) {
orderNum = orderNum.add(accountingDetail.getIncomeAmount()).add(accountingDetail.getExpenditureAmount());
boolean serviceFlag = false;
switch (accountingDetail.getAccountingType()) {
case "扣款":
deductionSum = deductionSum.add(accountingDetail.getExpenditureAmount());
serviceFlag = true;
break;
case "技术服务费":
technologyFee = technologyFee.add(accountingDetail.getExpenditureAmount());
break;
case "多多进宝":
ddjb = ddjb.add(accountingDetail.getExpenditureAmount());
}
if (serviceFlag) {
switch (accountingDetail.getServiceType()) {
case "0040002":
salesCompensate = salesCompensate.add(accountingDetail.getExpenditureAmount());
break;
case "0040003":
expressCompensate = expressCompensate.add(accountingDetail.getExpenditureAmount());
break;
case "0040004":
delaySendGoods = delaySendGoods.add(accountingDetail.getExpenditureAmount());
break;
case "0040005":
falseSendGoods = falseSendGoods.add(accountingDetail.getExpenditureAmount());
break;
case "0040006":
outOfStock = outOfStock.add(accountingDetail.getExpenditureAmount());
}
}
}
orderExtendDto.setDeductionSum(deductionSum);
orderExtendDto.setTechnologyFee(technologyFee);
orderExtendDto.setDdjb(ddjb);
orderExtendDto.setSalesCompensate(salesCompensate);
orderExtendDto.setExpressCompensate(expressCompensate);
orderExtendDto.setDelaySendGoods(delaySendGoods);
orderExtendDto.setFalseSendGoods(falseSendGoods);
orderExtendDto.setOutOfStock(outOfStock);
orderExtendDto.setPurchasePrice(BigDecimal.ZERO);
orderExtendDto.setExpressFee(BigDecimal.ZERO);
List<PlatformGoodsSkuVO> skuVOS = platformGoods.getGoodsSkuList().stream().filter(sku -> sku.getSkuId().equals(orderGoodsDto.getSkuId())).collect(Collectors.toList());
if (!skuVOS.isEmpty()) {
PlatformGoodsSkuVO platformGoodsSkuVO = skuVOS.get(0);
BigDecimal purchasePrice = platformGoodsSkuVO.getPurchaseUnitPrice();
BigDecimal expressFee = platformGoodsSkuVO.getExpressFee();
List<CidGoodsPriceHistory> cidGoodsPriceHistories = goodsClient.selectCidGoodsPriceHistory(tenantId, null, null);
if (!cidGoodsPriceHistories.isEmpty()) {
for (CidGoodsPriceHistory cidGoodsPriceHistory : cidGoodsPriceHistories) {
if (cidGoodsPriceHistory.getType() == 2 && DateUtil.toLocalDateTime(new Date(orderTradeDto.getSourceCreateDate())).isAfter(cidGoodsPriceHistory.getUpdateTime())) {
purchasePrice = cidGoodsPriceHistory.getPrice();
}
if (cidGoodsPriceHistory.getType() == 3 && DateUtil.toLocalDateTime(new Date(orderTradeDto.getSourceCreateDate())).isAfter(cidGoodsPriceHistory.getUpdateTime())) {
expressFee = cidGoodsPriceHistory.getPrice();
}
}
}
orderExtendDto.setPurchasePrice(purchasePrice == null ? BigDecimal.ZERO : purchasePrice);
orderExtendDto.setExpressFee(expressFee == null ? BigDecimal.ZERO : expressFee);
}
if (orderGoodsDto.getRefundType() != null) {
orderExtendDto.setPurchaseExpressFee(orderExtendDto.getExpressFee());
orderExtendDto.setRefundType(orderGoodsDto.getRefundType());
} else {
if (orderExtendDto.getPurchasePrice() != null && orderExtendDto.getExpressFee() != null) {
orderExtendDto.setPurchaseExpressFee(orderExtendDto.getPurchasePrice().add(orderExtendDto.getExpressFee()));
}
}
orderExtendDto.setOrderSum(orderNum);
orderExtendDto.setOrderProfit(orderExtendDto.getOrderSum().subtract(orderExtendDto.getPurchaseExpressFee()));
orderGoodsDtos.get(0).setBindJlId(platformGoods.getBindJlId());
order.setGoods(JSON.toJSONString(orderGoodsDtos));
order.setExtendInfo(JSON.toJSONString(orderExtendDto));
orderClient.updateCidOrder(order);
orderSearchClient.saveCidOrders(orderExtendDto, tenantId, accountingDetails, platformGoods.getBindJlId(), importCidTradeNo);
}
public void importFile(MultipartFile file, String tenantId, String taskId) {
ProgressVo progressVo = new ProgressVo();
R<ProgressVo> result = R.data(progressVo);
try {
progressVo.setTotalCount(0);
progressVo.setAllHasDone(false);
cidImportStatementProgress.saveProgress(taskId, result);
CsvReader csvReader = new CsvReader(new InputStreamReader(file.getInputStream(), "GBK"), new CsvReadConfig());
List<CsvRow> rows = csvReader.read().getRows();
int size = rows.size();
log.info("文件行数:{}", size);
if (size == 0) {
log.info("文件为空");
progressVo.setTotalCount(0);
progressVo.setAllHasDone(true);
cidImportStatementProgress.saveProgress(taskId, result);
return;
}
this.handlerAccountingDetail(rows, tenantId, taskId);
} catch (IOException e) {
log.error("导入失败", e);
throw new RuntimeException(e);
}
}
private void handlerAccountingDetail(List<CsvRow> rows, String tenantId, String taskId) {
LocalDateTime importFileTime = LocalDateTime.now();
log.info("执行处理:{}", rows.size());
AtomicInteger atomicInteger = new AtomicInteger(0);
List<CidAccountingDetail> accountingDetails = new ArrayList<>();
try {
for (CsvRow row : rows) {
try {
// log.info("row:{}", row);
if (row.size() != 7) {
continue;
}
if (StringUtil.isBlank(row.get(1))) {
continue;
}
if ("商户订单号".equals(row.get(0))) {
continue;
}
atomicInteger.getAndIncrement();
CidAccountingDetail accountingDetail = new CidAccountingDetail();
accountingDetail.setTenantId(tenantId);
String tradeNo = row.get(0);
if (StringUtil.isBlank(tradeNo)) {
Matcher matcher = PATTERN.matcher(row.get(5));
if (matcher.find()) {
tradeNo = matcher.group();
} else {
continue;
}
}
accountingDetail.setTradeNo(tradeNo);
accountingDetail.setOccurrenceTime(row.get(1));
accountingDetail.setIncomeAmount(new BigDecimal(row.get(2)));
accountingDetail.setExpenditureAmount(new BigDecimal(row.get(3)));
accountingDetail.setAccountingType(row.get(4));
accountingDetail.setRemark(row.get(5));
String[] service = row.get(6).split("\\|");
accountingDetail.setServiceType(service[0]);
accountingDetail.setServiceDesc(service[1]);
accountingDetail.setCreateTime(importFileTime);
String uniqueId = MD5Utils.encryptMD5(accountingDetail.getTradeNo() + accountingDetail.getOccurrenceTime() + accountingDetail.getAccountingType());
accountingDetail.setUniqueId(uniqueId);
accountingDetails.add(accountingDetail);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
if (accountingDetails.isEmpty())
return;
CountDownLatch countDownLatch = new CountDownLatch(accountingDetails.size() / 200 + 1);
for (int j = 0; j < accountingDetails.size(); j += 200) {
List<CidAccountingDetail> cidAccountList = accountingDetails.subList(j, Math.min(j + 200, accountingDetails.size()));
cidHandleThreadPoolTaskExecutor.submit(() -> {
cidClient.batchSaveAccountingDetail(cidAccountList);
countDownLatch.countDown();
});
}
countDownLatch.await();
compute(accountingDetails);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void importAccount(MultipartFile file, String tenantId, String taskId) {
LocalDateTime importTime = LocalDateTime.now();
ProgressVo progressVo = new ProgressVo();
R<ProgressVo> result = R.data(progressVo);
try {
progressVo.setTotalCount(0);
progressVo.setAllHasDone(false);
cidImportAccountProgress.saveProgress(taskId, result);
CidReadListener cidReadListener = new CidReadListener();
cidReadListener.setTenantId(tenantId);
EasyExcel.read(file.getInputStream(), ImportCidAccountVO.class, cidReadListener).sheet().doRead();
int size = cidReadListener.getCachedDataList().size();
log.info("账户文件行数:{}", size);
if (size == 0) {
progressVo.setTotalCount(0);
progressVo.setAllHasDone(true);
cidImportAccountProgress.saveProgress(taskId, result);
log.info("文件为空");
return;
}
int threadHandlerNum = size / 5 + (size % 5 > 0 ? 1 : 0);
int fromIdx = 0;
for (int i = 0; i < 5; i++) {
List<CidAccount> cidAccounts = cidReadListener.getCachedDataList().subList(fromIdx, size - fromIdx >= threadHandlerNum ? fromIdx + threadHandlerNum : size);
cidHandleThreadPoolTaskExecutor.submit(() -> {
for (int j = 0; j < cidAccounts.size(); j += 100) {
List<CidAccount> cidAccountList = cidAccounts.subList(j, Math.min(j + 100, cidAccounts.size()));
cidClient.batchSaveCidAccount(cidAccountList);
}
log.info("处理账户完成:{}", cidAccounts.size());
return "任务完成";
});
fromIdx += cidAccounts.size();
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
log.info("处理账户完成, 调用生成报表:{}", importTime);
this.generatePlan(tenantId, taskId, importTime, size);
} catch (IOException e) {
log.error("导入报表失败:{}", e.getMessage(), e);
throw new RuntimeException(e);
}
}
public void generatePlan(String tenantId, String taskId, LocalDateTime importTime, int insertCidAccountCount) {
log.info("生成cid报表开始");
CidAccountSearchVO cidAccountSearchVO = new CidAccountSearchVO();
cidAccountSearchVO.setTenantId(tenantId);
cidAccountSearchVO.setImportTime(importTime);
Long size = 0L;
for (int i = 1; i <= 10; i++) {
size = cidClient.queryCidAccountCount(cidAccountSearchVO);
log.info("计算cidAccount中,查询数据:{}", size);
if (insertCidAccountCount == size) {
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
if (size > 0L) {
log.info("查询到{}条数据", size);
AtomicInteger num = new AtomicInteger(0);
ProgressVo progressVo = new ProgressVo();
progressVo.setTotalCount(size.intValue());
R<ProgressVo> result = R.data(progressVo);
progressVo.setSuccessCount(num.get());
cidImportAccountProgress.saveProgress(taskId, result);
Long finalSize = size;
int pages = 1;
int pageNo = 1;
do {
cidAccountSearchVO.setPageNo(pageNo);
Page<CidAccount> cidAccountPage = cidClient.queryCidAccountPage(cidAccountSearchVO);
pages = (int) cidAccountPage.getPages();
cidHandleThreadPoolTaskExecutor.submit(() -> {
log.info("处理数量:{}", cidAccountPage.getRecords().size());
this.handleGroupPlan(cidAccountPage.getRecords(), taskId, finalSize.intValue(), num);
});
pageNo++;
} while (pageNo <= pages);
}
log.info("生成cid报表完成");
}
private void handleGroupPlan(List<CidAccount> cidAccounts, String taskId, int accountListSize, AtomicInteger num) {
ProgressVo progressVo = new ProgressVo();
progressVo.setTotalCount(accountListSize);
R<ProgressVo> result = R.data(progressVo);
for (CidAccount cidAccount : cidAccounts) {
List<PlatformGoods> platformGoodsList = goodsClient.queryGoodsByAccountId(cidAccount.getTenantId(), cidAccount.getAccountId());
this.handlePlan(() -> {
CidPlan cidPlan = new CidPlan();
cidPlan.setTenantId(cidAccount.getTenantId());
cidPlan.setAccountName(cidAccount.getAccount());
cidPlan.setChannel("巨量引擎");
cidPlan.setJlId(cidAccount.getAccountId());
cidPlan.setTotalConsumption(cidAccount.getConsume());
return cidPlan;
}, platformGoodsList, null);
num.getAndIncrement();
progressVo.setSuccessCount(num.get());
cidImportAccountProgress.saveProgress(taskId, result);
}
}
private void handlePlan(Supplier<CidPlan> cidPlanSupplier, List<PlatformGoods> platformGoodsList, CidPlanSearchVo cidPlanSearchVo) {
CidPlan cidPlan = cidPlanSupplier.get();
CidPlan result = orderSearchClient.statisticsCidOrder(cidPlan, DateUtil.toLocalDateTime(cidPlanSearchVo.getStartTime()), DateUtil.toLocalDateTime(cidPlanSearchVo.getEndTime()));
BeanUtil.copyProperties(result, cidPlan);
if (CollectionUtil.isNotEmpty(platformGoodsList)) {
log.info("计划:{},没有找到商品", cidPlan.getJlId());
PlatformGoods platformGoods = platformGoodsList.get(0);
cidPlan.setSalePrice(platformGoods.getSaleUnitPrice());
cidPlan.setPurchasePrice(platformGoods.getPurchaseUnitPrice());
cidPlan.setExpressFee(platformGoods.getExpressFee());
}
}
private List<CidOrderVO> filterOrderByDate(CidPlanSearchVo cidPlanSearchVo, List<CidOrderVO> orders) {
if (cidPlanSearchVo == null)
return orders;
List<String> tradeNos = cidClient.selectOrderByTradeNoAndTime(
orders.stream().map(CidOrderVO::getTradeNo).collect(Collectors.toList()), cidPlanSearchVo);
//orderS过滤掉不包含tradeNo的订单
return orders.stream().filter(cidOrderVO -> tradeNos.contains(cidOrderVO.getTradeNo())).collect(Collectors.toList());
}
private void handleOrder(List<CidOrderVO> data, Map<String, BigDecimal> param, Map<String, BigDecimal> deductionDetail, Map<String, Integer> orderParam) {
int count = (int) data.stream().filter(cidOrderVO -> cidOrderVO.getCidOrderExtendVO().getRefundType() != null).count();
orderParam.put("refundOrderNum", orderParam.get("refundOrderNum") + count);
orderParam.put("orderNum", orderParam.get("orderNum") + data.size());
for (CidOrderVO cidOrderVO : data) {
if (cidOrderVO.getCidOrderExtendVO().getDeductionSum() != null) {
param.put("deductionSum", param.get("deductionSum").add(cidOrderVO.getCidOrderExtendVO().getDeductionSum()));
}
if (cidOrderVO.getCidOrderExtendVO().getTechnologyFee() != null) {
param.put("technologyFee", param.get("technologyFee").add(cidOrderVO.getCidOrderExtendVO().getTechnologyFee()));
}
if (cidOrderVO.getCidOrderExtendVO().getDdjb() != null) {
param.put("ddjb", param.get("ddjb").add(cidOrderVO.getCidOrderExtendVO().getDdjb()));
}
if (cidOrderVO.getCidOrderExtendVO().getOrderProfit() != null) {
param.put("profit", param.get("profit").add(cidOrderVO.getCidOrderExtendVO().getOrderProfit()));
}
if (cidOrderVO.getCidOrderExtendVO().getSalesCompensate() != null) {
deductionDetail.put("salesCompensate", deductionDetail.get("salesCompensate").add(cidOrderVO.getCidOrderExtendVO().getSalesCompensate()));
}
if (cidOrderVO.getCidOrderExtendVO().getExpressCompensate() != null) {
deductionDetail.put("expressCompensate", deductionDetail.get("expressCompensate").add(cidOrderVO.getCidOrderExtendVO().getExpressCompensate()));
}
if (cidOrderVO.getCidOrderExtendVO().getDelaySendGoods() != null) {
deductionDetail.put("delaySendGoods", deductionDetail.get("delaySendGoods").add(cidOrderVO.getCidOrderExtendVO().getDelaySendGoods()));
}
if (cidOrderVO.getCidOrderExtendVO().getFalseSendGoods() != null) {
deductionDetail.put("falseSendGoods", deductionDetail.get("falseSendGoods").add(cidOrderVO.getCidOrderExtendVO().getFalseSendGoods()));
}
if (cidOrderVO.getCidOrderExtendVO().getOutOfStock() != null) {
deductionDetail.put("outOfStock", deductionDetail.get("outOfStock").add(cidOrderVO.getCidOrderExtendVO().getOutOfStock()));
}
}
}
public CidPlanSearchResp searchPlan(CidPlanSearchVo cidPlanSearchVo) {
CidPlanSearchResp cidPlanSearchResp = new CidPlanSearchResp();
Page<CidPlan> cidPlanPage = cidClient.queryCidPlanPage(cidPlanSearchVo);
List<CidPlan> cidPlans = cidPlanPage.getRecords();
if (ObjectUtil.isAllNotEmpty(cidPlanSearchVo.getStartTime(), cidPlanSearchVo.getEndTime())) {
realTimeCompute(cidPlans, cidPlanSearchVo);
}
BigDecimal currentProfit = cidPlans.stream().map(CidPlan::getProfit).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);
cidPlanSearchResp.setCurrentProfit(currentProfit);
cidPlanSearchResp.setData(cidPlanPage);
CidPlan result = orderSearchClient.statisticsCidOrder(new CidPlan(), DateUtil.toLocalDateTime(cidPlanSearchVo.getStartTime()), DateUtil.toLocalDateTime(cidPlanSearchVo.getEndTime()));
cidPlanSearchResp.setTotalProfit(result.getProfit());
return cidPlanSearchResp;
}
private void realTimeCompute(List<CidPlan> cidPlans, CidPlanSearchVo cidPlanSearchVo) {
if (CollectionsUtil.isEmpty(cidPlans))
return;
computeCidPlan(cidPlans, cidPlanSearchVo, cidPlans.stream().map(CidPlan::getJlId).collect(Collectors.toList()));
}
private void computeCidPlan(List<CidPlan> cidPlans, CidPlanSearchVo cidPlanSearchVo, List<String> accountIds) {
Map<String, List<PlatformGoods>> goodsMapGroupByBindJlId =
goodsClient.queryGoodsByAccountIds(cidPlanSearchVo.getTenantId(), accountIds)
.stream().collect(Collectors.groupingBy(PlatformGoods::getBindJlId));
CountDownLatch countDownLatch = new CountDownLatch(cidPlans.size());
cidPlans.forEach(cidPlan -> cidHandleThreadPoolTaskExecutor.execute(() -> {
this.handlePlan(() -> cidPlan, goodsMapGroupByBindJlId.get(cidPlan.getJlId()), cidPlanSearchVo);
countDownLatch.countDown();
}));
try {
countDownLatch.await();
} catch (InterruptedException e) {
log.error("realTimeCompute error: {}", e.getMessage());
}
}
@Transactional(rollbackFor = Exception.class)
public Boolean pushAccount(List<AdvertiserAccount> data) {
List<String> accountIds = data.stream().map(AdvertiserAccount::getAdvertiserId).collect(Collectors.toList());
Map<String, List<PlatformGoods>> goodsMapGroupByBindJlId =
goodsClient.queryGoodsByAccountIds(tenantId, accountIds)
.stream().collect(Collectors.groupingBy(PlatformGoods::getBindJlId));
Map<String, CidPlan> cidPlanMap = cidClient.queryCidPlans(tenantId, accountIds).stream().collect(Collectors.toMap(CidPlan::getJlId, Function.identity()));
CopyOnWriteArrayList<CidPlan> cidPlansList = new CopyOnWriteArrayList<>();
CountDownLatch count = new CountDownLatch(accountIds.size());
List<CidAccount> cidAccounts = data.stream().map(account -> {
CidAccount cidAccount = account.mapToCidAccount(new HashMap<>(), tenantId);
cidHandleThreadPoolTaskExecutor.execute(() -> {
String accountId = cidAccount.getAccountId();
this.handlePlan(() -> dealHistoryPlan(cidAccount, cidPlanMap, cidPlansList), goodsMapGroupByBindJlId.get(accountId), null);
count.countDown();
});
return cidAccount;
}).collect(Collectors.toList());
cidClient.batchSaveCidPlan(cidPlansList);
orderSearchClient.saveCidConsumption(convertEsCidOrderConsumption(data, new Date()));
return cidClient.batchSaveCidAccount(cidAccounts);
}
private CidPlan dealHistoryPlan(CidAccount cidAccount, Map<String, CidPlan> cidPlanMap, CopyOnWriteArrayList<CidPlan> cidPlansList) {
String accountId = cidAccount.getAccountId();
List<CidPlan.HistoryTotalConsumption> historyTotalConsumptions =
cidPlanMap.containsKey(accountId) && CollectionsUtil.isNotEmpty(cidPlanMap.get(accountId).getHistoryTotalConsumptions()) ?
cidPlanMap.get(accountId).getHistoryTotalConsumptions() : new ArrayList<>();
String today = DateUtil.formatDate(new Date());
BigDecimal consume = cidAccount.getConsume();
CidPlan.HistoryTotalConsumption todayData = new CidPlan.HistoryTotalConsumption(DateUtil.parseDate(today), consume);
if (historyTotalConsumptions.isEmpty() || cidPlanMap.get(accountId).getHistoryTotalConsumptions().stream()
.noneMatch(historyTotalConsumption -> today.equals(DateUtil.formatDate(historyTotalConsumption.getDate())))) {
historyTotalConsumptions.add(todayData);
}
CidPlan cidPlan = new CidPlan();
cidPlan.setTenantId(cidAccount.getTenantId());
cidPlan.setAccountName(cidAccount.getAccount());
cidPlan.setChannel("巨量引擎");
cidPlan.setJlId(accountId);
cidPlan.setTotalConsumption(consume);
cidPlan.setHistoryTotalConsumption(JSON.toJSONString(historyTotalConsumptions));
cidPlansList.add(cidPlan);
return cidPlan;
}
@Transactional(rollbackFor = Exception.class)
public void pushHistoryData(HistoryPushAccountReq historyPushAccountReq) {
String day = historyPushAccountReq.getDate();
DateTime time = DateUtil.parseDate(day);
List<AdvertiserAccount> advertiserAccounts = historyPushAccountReq.getData();
List<String> accountIds = advertiserAccounts.stream().map(AdvertiserAccount::getAdvertiserId).collect(Collectors.toList());
Map<String, BigDecimal> historyDataMap = advertiserAccounts.stream().collect(Collectors.toMap(AdvertiserAccount::getAdvertiserId, AdvertiserAccount::getStatCost));
List<CidPlan> cidPlans = cidClient.queryCidPlans(tenantId, accountIds);
cidPlans.forEach(cidPlan -> {
BigDecimal consume = historyDataMap.get(cidPlan.getJlId());
CidPlan.HistoryTotalConsumption todayData = new CidPlan.HistoryTotalConsumption(time, consume);
List<CidPlan.HistoryTotalConsumption> historyTotalConsumptions = cidPlan.getHistoryTotalConsumptions();
if (CollectionsUtil.isNotEmpty(historyTotalConsumptions)) {
if (historyTotalConsumptions.stream()
.noneMatch(consumption -> day.equals(DateUtil.formatDate(consumption.getDate())))) {
historyTotalConsumptions.add(todayData);
historyTotalConsumptions.sort(Comparator.comparing(CidPlan.HistoryTotalConsumption::getDate));
cidPlan.setHistoryTotalConsumption(JSON.toJSONString(historyTotalConsumptions));
}
} else {
cidPlan.setHistoryTotalConsumption(JSON.toJSONString(Collections.singleton(todayData)));
}
});
if (!cidPlans.isEmpty()) {
cidClient.batchSaveCidPlan(cidPlans);
orderSearchClient.saveCidConsumption(convertEsCidOrderConsumption(advertiserAccounts, time));
}
}
private List<CidOrderConsumption> convertEsCidOrderConsumption(List<AdvertiserAccount> advertiserAccounts, Date time) {
return advertiserAccounts.stream().map(advertiserAccount -> new CidOrderConsumption(advertiserAccount, time.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate())).collect(Collectors.toList());
}
public void syncData(String accountId) {
CollectionsUtil.batchDealWholeData(pageNo -> {
Page<CidPlan> cidPlanPage = cidClient.queryCidPlanPage(new CidPlanSearchVo(pageNo, 1000, tenantId, accountId));
List<CidPlan> cidPlans = cidPlanPage.getRecords();
log.info("cidPlans:{}", JSON.toJSONString(cidPlans));
List<CidOrderConsumption> cidOrderConsumptions = cidPlans.stream().flatMap(cidPlan ->
cidPlan.getHistoryTotalConsumptions().stream()
.filter(historyTotalConsumption -> BigDecimal.ZERO.compareTo(historyTotalConsumption.getTotalConsumption()) < 0)
.map(historyTotalConsumption -> new CidOrderConsumption(cidPlan.getJlId(), historyTotalConsumption))
).collect(Collectors.toList());
log.info("cidOrderConsumptions:{}", JSON.toJSONString(cidOrderConsumptions));
if (CollectionUtil.isNotEmpty(cidOrderConsumptions)) {
orderSearchClient.saveCidConsumption(cidOrderConsumptions);
}
return cidPlans;
});
}
}
并且告诉我每一行为什么这样写
最新发布