准备当日报表数据
This commit is contained in:
@@ -301,6 +301,48 @@ public class LbDailyUserTradeController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/calculate-report/by-date-and-tenant")
|
||||||
|
@Operation(summary = "按日期和租户计算报表", description = "根据报表日期和租户ID计算当天交易报表并写入 lb_daily_user_trade_report")
|
||||||
|
public ResponseEntity<Map<String, Object>> calculateReportByDateAndTenant(
|
||||||
|
@Parameter(description = "报表日期,格式:yyyy-MM-dd", required = true)
|
||||||
|
@RequestParam String reportDate,
|
||||||
|
@Parameter(description = "租户ID", required = true)
|
||||||
|
@RequestParam String tenantId) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
try {
|
||||||
|
if (tenantId == null || tenantId.trim().isEmpty()) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "tenantId不能为空");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
}
|
||||||
|
if (reportDate == null || reportDate.trim().isEmpty()) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "reportDate不能为空");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDate parsedReportDate;
|
||||||
|
try {
|
||||||
|
parsedReportDate = LocalDate.parse(reportDate.trim());
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "报表日期格式错误,请使用 yyyy-MM-dd");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> serviceResult = lbDailyUserTradeService.calculateDailyTradeReport(parsedReportDate, tenantId);
|
||||||
|
Boolean success = (Boolean) serviceResult.get("success");
|
||||||
|
if (Boolean.TRUE.equals(success)) {
|
||||||
|
return ResponseEntity.ok(serviceResult);
|
||||||
|
}
|
||||||
|
return ResponseEntity.badRequest().body(serviceResult);
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "计算异常:" + e.getMessage());
|
||||||
|
return ResponseEntity.internalServerError().body(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/import")
|
@PostMapping("/import")
|
||||||
@Operation(summary = "导入交易记录", description = "按Excel模板导入当天用户交易记录")
|
@Operation(summary = "导入交易记录", description = "按Excel模板导入当天用户交易记录")
|
||||||
public ResponseEntity<Map<String, Object>> importExcel(
|
public ResponseEntity<Map<String, Object>> importExcel(
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
|||||||
import com.rj.entity.LbDailyUserTrade;
|
import com.rj.entity.LbDailyUserTrade;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -14,4 +15,6 @@ import java.util.Map;
|
|||||||
public interface ILbDailyUserTradeService extends IService<LbDailyUserTrade> {
|
public interface ILbDailyUserTradeService extends IService<LbDailyUserTrade> {
|
||||||
|
|
||||||
Map<String, Object> importFromExcel(MultipartFile file, String defaultReportDate, String tenantId);
|
Map<String, Object> importFromExcel(MultipartFile file, String defaultReportDate, String tenantId);
|
||||||
|
|
||||||
|
Map<String, Object> calculateDailyTradeReport(LocalDate reportDate, String tenantId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package com.rj.service.impl;
|
package com.rj.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.rj.entity.LbDailyUserTrade;
|
import com.rj.entity.LbDailyUserTrade;
|
||||||
|
import com.rj.entity.LbDailyUserTradeReport;
|
||||||
import com.rj.mapper.LbDailyUserTradeMapper;
|
import com.rj.mapper.LbDailyUserTradeMapper;
|
||||||
import com.rj.service.ILbDailyUserTradeService;
|
import com.rj.service.ILbDailyUserTradeService;
|
||||||
|
import com.rj.service.ILbDailyUserTradeReportService;
|
||||||
import org.apache.poi.poifs.filesystem.FileMagic;
|
import org.apache.poi.poifs.filesystem.FileMagic;
|
||||||
import org.apache.poi.ss.usermodel.Cell;
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
import org.apache.poi.ss.usermodel.CellType;
|
import org.apache.poi.ss.usermodel.CellType;
|
||||||
@@ -16,6 +19,7 @@ import org.apache.poi.ss.usermodel.Workbook;
|
|||||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
@@ -46,6 +50,96 @@ import java.util.regex.Pattern;
|
|||||||
@Service
|
@Service
|
||||||
public class LbDailyUserTradeServiceImpl extends ServiceImpl<LbDailyUserTradeMapper, LbDailyUserTrade> implements ILbDailyUserTradeService {
|
public class LbDailyUserTradeServiceImpl extends ServiceImpl<LbDailyUserTradeMapper, LbDailyUserTrade> implements ILbDailyUserTradeService {
|
||||||
private static final Logger log = LoggerFactory.getLogger(LbDailyUserTradeServiceImpl.class);
|
private static final Logger log = LoggerFactory.getLogger(LbDailyUserTradeServiceImpl.class);
|
||||||
|
private static final BigDecimal SERVICE_RATE = new BigDecimal("0.01");
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ILbDailyUserTradeReportService lbDailyUserTradeReportService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> calculateDailyTradeReport(LocalDate reportDate, String tenantId) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
if (reportDate == null) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "reportDate不能为空");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(tenantId)) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "tenantId不能为空");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String normalizedTenantId = tenantId.trim();
|
||||||
|
LambdaQueryWrapper<LbDailyUserTrade> currentDayWrapper = new LambdaQueryWrapper<>();
|
||||||
|
currentDayWrapper.eq(LbDailyUserTrade::getTenantId, normalizedTenantId)
|
||||||
|
.eq(LbDailyUserTrade::getReportDate, reportDate)
|
||||||
|
.and(wrapper -> wrapper
|
||||||
|
.ne(LbDailyUserTrade::getDailySellAmt, BigDecimal.ZERO)
|
||||||
|
.or()
|
||||||
|
.ne(LbDailyUserTrade::getDailyBuyAmt, BigDecimal.ZERO)
|
||||||
|
.or()
|
||||||
|
.ne(LbDailyUserTrade::getDiffAmt, BigDecimal.ZERO));
|
||||||
|
|
||||||
|
List<LbDailyUserTrade> currentDayTrades = this.list(currentDayWrapper);
|
||||||
|
if (currentDayTrades.isEmpty()) {
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "未匹配到可计算数据");
|
||||||
|
result.put("insertCount", 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDate yesterday = reportDate.minusDays(1);
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
List<LbDailyUserTradeReport> reportList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (LbDailyUserTrade trade : currentDayTrades) {
|
||||||
|
BigDecimal dailySellAmt = trade.getDailySellAmt() == null ? BigDecimal.ZERO : trade.getDailySellAmt();
|
||||||
|
BigDecimal dailyBuyAmt = trade.getDailyBuyAmt() == null ? BigDecimal.ZERO : trade.getDailyBuyAmt();
|
||||||
|
BigDecimal diffAmt = trade.getDiffAmt() == null ? BigDecimal.ZERO : trade.getDiffAmt();
|
||||||
|
|
||||||
|
LambdaQueryWrapper<LbDailyUserTrade> yesterdayWrapper = new LambdaQueryWrapper<>();
|
||||||
|
yesterdayWrapper.eq(LbDailyUserTrade::getTenantId, normalizedTenantId)
|
||||||
|
.eq(LbDailyUserTrade::getReportDate, yesterday)
|
||||||
|
.eq(LbDailyUserTrade::getUserId, trade.getUserId());
|
||||||
|
if (StringUtils.isNotBlank(trade.getNickname())) {
|
||||||
|
yesterdayWrapper.eq(LbDailyUserTrade::getNickname, trade.getNickname().trim());
|
||||||
|
}
|
||||||
|
yesterdayWrapper
|
||||||
|
.orderByDesc(LbDailyUserTrade::getUpdatedAt)
|
||||||
|
.last("limit 1");
|
||||||
|
LbDailyUserTrade lastDateRecord = this.getOne(yesterdayWrapper, false);
|
||||||
|
BigDecimal yestodaySellAmt = lastDateRecord == null || lastDateRecord.getDailyBuyAmt() == null
|
||||||
|
? BigDecimal.ZERO
|
||||||
|
: lastDateRecord.getDailyBuyAmt();
|
||||||
|
|
||||||
|
LbDailyUserTradeReport report = new LbDailyUserTradeReport();
|
||||||
|
report.setId(UUID.randomUUID().toString());
|
||||||
|
report.setTenantId(normalizedTenantId);
|
||||||
|
report.setUserId(trade.getUserId());
|
||||||
|
report.setNickname(trade.getNickname());
|
||||||
|
report.setYestodaySellAmt(yestodaySellAmt);
|
||||||
|
report.setDailySellAmt(dailySellAmt);
|
||||||
|
report.setDailyBuyAmt(dailyBuyAmt);
|
||||||
|
report.setServiceAmt(dailyBuyAmt.multiply(SERVICE_RATE));
|
||||||
|
report.setDiffAmt(diffAmt);
|
||||||
|
report.setReportDate(reportDate.atStartOfDay());
|
||||||
|
report.setCreatedAt(now);
|
||||||
|
report.setUpdatedAt(now);
|
||||||
|
reportList.add(report);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean saved = lbDailyUserTradeReportService.saveBatch(reportList);
|
||||||
|
if (!saved) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "报表插入失败");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "计算并写入报表成功");
|
||||||
|
result.put("insertCount", reportList.size());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> importFromExcel(MultipartFile file, String defaultReportDate, String tenantId) {
|
public Map<String, Object> importFromExcel(MultipartFile file, String defaultReportDate, String tenantId) {
|
||||||
@@ -204,16 +298,75 @@ public class LbDailyUserTradeServiceImpl extends ServiceImpl<LbDailyUserTradeMap
|
|||||||
map.putIfAbsent(field, cell.getColumnIndex());
|
map.putIfAbsent(field, cell.getColumnIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
completeAmountColumnByOrder(map, headerRow, formatter);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void completeAmountColumnByOrder(Map<String, Integer> map, Row headerRow, DataFormatter formatter) {
|
||||||
|
if (map.containsKey("dailySellAmt") && map.containsKey("dailyBuyAmt")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Integer nicknameIndex = map.get("nickname");
|
||||||
|
Integer userIdIndex = map.get("userId");
|
||||||
|
Integer diffIndex = map.get("diffAmt");
|
||||||
|
|
||||||
|
int startIndex = -1;
|
||||||
|
if (nicknameIndex != null) {
|
||||||
|
startIndex = nicknameIndex;
|
||||||
|
} else if (userIdIndex != null) {
|
||||||
|
startIndex = userIdIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startIndex < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int candidateSellIndex = startIndex + 1;
|
||||||
|
int candidateBuyIndex = startIndex + 2;
|
||||||
|
|
||||||
|
int lastCellNum = headerRow.getLastCellNum();
|
||||||
|
if (lastCellNum < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diffIndex != null) {
|
||||||
|
if (candidateSellIndex >= diffIndex || candidateBuyIndex >= diffIndex) {
|
||||||
|
candidateSellIndex = -1;
|
||||||
|
candidateBuyIndex = -1;
|
||||||
|
for (int i = startIndex + 1; i < diffIndex; i++) {
|
||||||
|
String header = normalizeHeader(formatter.formatCellValue(headerRow.getCell(i)));
|
||||||
|
if (header.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (candidateSellIndex < 0) {
|
||||||
|
candidateSellIndex = i;
|
||||||
|
} else {
|
||||||
|
candidateBuyIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!map.containsKey("dailySellAmt")
|
||||||
|
&& candidateSellIndex >= 0
|
||||||
|
&& candidateSellIndex < lastCellNum) {
|
||||||
|
map.put("dailySellAmt", candidateSellIndex);
|
||||||
|
}
|
||||||
|
if (!map.containsKey("dailyBuyAmt")
|
||||||
|
&& candidateBuyIndex >= 0
|
||||||
|
&& candidateBuyIndex < lastCellNum) {
|
||||||
|
map.put("dailyBuyAmt", candidateBuyIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String resolveFieldByHeader(String header) {
|
private String resolveFieldByHeader(String header) {
|
||||||
Map<String, Set<String>> aliasMap = new HashMap<>();
|
Map<String, Set<String>> aliasMap = new HashMap<>();
|
||||||
aliasMap.put("tenantId", Set.of("tenantid", "tenant_id", "租户id", "租户"));
|
aliasMap.put("tenantId", Set.of("tenantid", "tenant_id", "租户id", "租户"));
|
||||||
aliasMap.put("userId", Set.of("userid", "user_id", "用户id", "用户"));
|
aliasMap.put("userId", Set.of("userid", "user_id", "用户id", "用户"));
|
||||||
aliasMap.put("nickname", Set.of("nickname", "昵称", "用户名", "客户昵称"));
|
aliasMap.put("nickname", Set.of("nickname", "昵称", "用户名", "客户昵称"));
|
||||||
aliasMap.put("dailySellAmt", Set.of("dailysellamt", "daily_sell_amt", "单日卖出金额", "卖出金额", "卖出"));
|
aliasMap.put("dailySellAmt", Set.of("dailysellamt", "daily_sell_amt", "单日卖出金额", "卖出金额", "卖出", "卖总"));
|
||||||
aliasMap.put("dailyBuyAmt", Set.of("dailybuyamt", "daily_buy_amt", "当日买入金额", "买入金额", "买入"));
|
aliasMap.put("dailyBuyAmt", Set.of("dailybuyamt", "daily_buy_amt", "当日买入金额", "买入金额", "买入", "买总"));
|
||||||
aliasMap.put("diffAmt", Set.of("diffamt", "diff_amt", "差额", "净额"));
|
aliasMap.put("diffAmt", Set.of("diffamt", "diff_amt", "差额", "净额"));
|
||||||
aliasMap.put("promoterId", Set.of("promoterid", "promoter_id", "推广人id"));
|
aliasMap.put("promoterId", Set.of("promoterid", "promoter_id", "推广人id"));
|
||||||
aliasMap.put("promoterName", Set.of("promotername", "promoter_name", "推广人", "邀请人"));
|
aliasMap.put("promoterName", Set.of("promotername", "promoter_name", "推广人", "邀请人"));
|
||||||
@@ -225,6 +378,12 @@ public class LbDailyUserTradeServiceImpl extends ServiceImpl<LbDailyUserTradeMap
|
|||||||
return entry.getKey();
|
return entry.getKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (header.contains("卖") && header.contains("总")) {
|
||||||
|
return "dailySellAmt";
|
||||||
|
}
|
||||||
|
if (header.contains("买") && header.contains("总")) {
|
||||||
|
return "dailyBuyAmt";
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user