报表检查表

This commit is contained in:
2026-05-28 08:44:15 +08:00
parent 48c5b2a856
commit b0494ff5b6
3 changed files with 582 additions and 4 deletions

View File

@@ -220,7 +220,7 @@ public class LbGoodsServiceImpl extends ServiceImpl<LbGoodsMapper, LbGoods> impl
w.le(LbGoods::getUpdatedAt, updatedEnd);
}
w.orderByDesc(LbGoods::getUpdatedAt).orderByDesc(LbGoods::getId);
w.orderByDesc(LbGoods::getPrice).orderByDesc(LbGoods::getId);
Page<LbGoods> page = this.page(new Page<>(current, size), w);
result.put("success", true);

View File

@@ -66,7 +66,21 @@ public final class LbDailyUserTradeReportExportSupport {
private static final int RESULT_CHECK_COL_BUY_TOTAL_FEE = 20;
private static final int RESULT_CHECK_COL_SELL_DETAIL = 21;
private static final int RESULT_CHECK_COL_SELL_TOTAL = 22;
private static final int RESULT_CHECK_LAST_COL = RESULT_CHECK_COL_SELL_TOTAL;
/** 结果表检查表 Y 列Z 列订单金额对应昵称Z 列S 列多笔订单金额逐行展开。 */
private static final int RESULT_CHECK_COL_BUY_ORDER_NICKNAME = 24;
private static final int RESULT_CHECK_COL_BUY_ORDER_AMOUNT = 25;
/** 结果表检查表 AA 列:按 Y 列昵称汇总 Z 列订单金额。 */
private static final int RESULT_CHECK_COL_BUY_ORDER_YZ_SUM = 26;
/** 结果表检查表 AC 列AD 列卖出订单金额对应昵称AD 列V 列多笔卖出金额逐行展开。 */
private static final int RESULT_CHECK_COL_SELL_ORDER_NICKNAME = 28;
private static final int RESULT_CHECK_COL_SELL_ORDER_AMOUNT = 29;
/** 结果表检查表 AE 列:按 AC 列昵称汇总 AD 列卖出订单金额。 */
private static final int RESULT_CHECK_COL_SELL_ORDER_AD_SUM = 30;
/** 结果表检查表 AFAH总表与检查表买入差异核对。 */
private static final int RESULT_CHECK_COL_BUY_DIFF_SUMMARY = 31;
private static final int RESULT_CHECK_COL_BUY_DIFF_CHECK = 32;
private static final int RESULT_CHECK_COL_BUY_DIFF = 33;
private static final int RESULT_CHECK_LAST_COL = RESULT_CHECK_COL_BUY_DIFF;
private static final BigDecimal RESULT_CHECK_BUY_TOTAL_FEE_RATE = new BigDecimal("0.01");
private static final int PAYMENT_COL_NAME = 0;
@@ -140,6 +154,7 @@ public final class LbDailyUserTradeReportExportSupport {
fillResultCheckSheet(
workbook.getSheetAt(RESULT_CHECK_SHEET_INDEX),
resultSheet,
workbook.getSheetAt(SUMMARY_SHEET_INDEX),
userIdByNickname,
buyTotalByBuyerId,
buyDetailByBuyerId,
@@ -454,6 +469,7 @@ public final class LbDailyUserTradeReportExportSupport {
private static void fillResultCheckSheet(
Sheet target,
Sheet resultSource,
Sheet summarySheet,
Map<String, String> userIdByNickname,
Map<String, BigDecimal> buyTotalByBuyerId,
Map<String, String> buyDetailByBuyerId,
@@ -540,11 +556,353 @@ public final class LbDailyUserTradeReportExportSupport {
}
fillResultCheckColumnsMandNByIandKNickname(target, styles);
fillResultCheckColumnZFromColumnS(target, styles);
fillResultCheckColumnAdFromColumnV(target, styles);
fillResultCheckColumnAaSumByYNickname(target, styles);
fillResultCheckColumnAeSumByAcNickname(target, styles);
writeResultCheckColumnLAndMSum(target, styles);
writeResultCheckBuyAmountDiffRows(target, summarySheet, styles);
autoSizeColumns(target, RESULT_CHECK_LAST_COL);
shrinkResultCheckDetailColumnWidths(target);
}
/** 结果表检查表:末行追加 L、M 列数据合计。 */
/** 结果表检查表 S、V 列(订单/卖出金额明细)宽度缩小为当前 20%。 */
private static void shrinkResultCheckDetailColumnWidths(Sheet sheet) {
shrinkColumnWidthToRatio(sheet, RESULT_CHECK_COL_BUY_DETAIL, 0.2d);
shrinkColumnWidthToRatio(sheet, RESULT_CHECK_COL_SELL_DETAIL, 0.2d);
}
private static void shrinkColumnWidthToRatio(Sheet sheet, int col, double ratio) {
int currentWidth = sheet.getColumnWidth(col);
int shrunk = Math.max(256, (int) Math.round(currentWidth * ratio));
sheet.setColumnWidth(col, shrunk);
}
/**
* S 列(订单金额明细)含多笔订单时,按「+」拆分后逐行写入 Z 列Y 列写入对应昵称;仅 1 笔订单不写 Y/Z。
*/
private static void fillResultCheckColumnZFromColumnS(Sheet sheet, SheetStyles styles) {
int dataEndRow = resolveResultCheckDataEndRow(sheet);
if (dataEndRow < 1) {
return;
}
for (int rowIdx = 1; rowIdx <= dataEndRow; rowIdx++) {
Row row = sheet.getRow(rowIdx);
if (row == null || isResultMatchSumLabelRow(row)) {
continue;
}
String buyDetail = readPaymentCellText(row.getCell(RESULT_CHECK_COL_BUY_DETAIL));
if (buyDetail.isEmpty()) {
continue;
}
List<BigDecimal> amounts = parseOrderAmountDetailText(buyDetail);
if (amounts.size() <= 1) {
continue;
}
String nickname = readPaymentCellText(row.getCell(RESULT_CHECK_COL_NICKNAME));
if (nickname.isEmpty()) {
nickname = readPaymentCellText(row.getCell(RESULT_CHECK_COL_CURRENT_NICKNAME));
}
int writeRow = rowIdx;
for (BigDecimal amount : amounts) {
writeRow = findNextEmptyResultCheckColumnZ(sheet, writeRow);
Row targetRow = ensureResultCheckRow(sheet, writeRow, styles);
createPaymentActualCell(
targetRow, RESULT_CHECK_COL_BUY_ORDER_AMOUNT, amount, paymentActualStyle(writeRow, styles));
if (!nickname.isEmpty() && isResultCheckColumnYEmpty(targetRow)) {
createTextCell(targetRow, RESULT_CHECK_COL_BUY_ORDER_NICKNAME, nickname, styles.textStyle);
}
writeRow++;
}
}
}
/**
* V 列(卖出金额明细)含多笔订单时,按「+」拆分后逐行写入 AD 列AC 列写入 Q 列昵称;仅 1 笔订单不写 AC/AD。
*/
private static void fillResultCheckColumnAdFromColumnV(Sheet sheet, SheetStyles styles) {
int dataEndRow = resolveResultCheckDataEndRow(sheet);
if (dataEndRow < 1) {
return;
}
for (int rowIdx = 1; rowIdx <= dataEndRow; rowIdx++) {
Row row = sheet.getRow(rowIdx);
if (row == null || isResultMatchSumLabelRow(row)) {
continue;
}
String sellDetail = readPaymentCellText(row.getCell(RESULT_CHECK_COL_SELL_DETAIL));
if (sellDetail.isEmpty()) {
continue;
}
List<BigDecimal> amounts = parseOrderAmountDetailText(sellDetail);
if (amounts.size() <= 1) {
continue;
}
String nickname = readPaymentCellText(row.getCell(RESULT_CHECK_COL_NICKNAME));
int writeRow = rowIdx;
for (BigDecimal amount : amounts) {
writeRow = findNextEmptyResultCheckColumnAd(sheet, writeRow);
Row targetRow = ensureResultCheckRow(sheet, writeRow, styles);
createPaymentActualCell(
targetRow, RESULT_CHECK_COL_SELL_ORDER_AMOUNT, amount, paymentActualStyle(writeRow, styles));
if (!nickname.isEmpty() && isResultCheckColumnAcEmpty(targetRow)) {
createTextCell(targetRow, RESULT_CHECK_COL_SELL_ORDER_NICKNAME, nickname, styles.textStyle);
}
writeRow++;
}
}
}
/** AE 列:按 AC 列昵称汇总 AD 列卖出订单金额,连续相同昵称仅末行展示。 */
private static void fillResultCheckColumnAeSumByAcNickname(Sheet sheet, SheetStyles styles) {
int dataEndRow = resolveResultCheckDataEndRow(sheet);
if (dataEndRow < 1) {
return;
}
Map<String, BigDecimal> sumByAcNickname = new HashMap<>();
for (int rowIdx = 1; rowIdx <= dataEndRow; rowIdx++) {
Row row = sheet.getRow(rowIdx);
if (row == null || isResultMatchSumLabelRow(row)) {
continue;
}
String acName = normalizeResultCheckNickname(
readPaymentCellText(row.getCell(RESULT_CHECK_COL_SELL_ORDER_NICKNAME)));
if (acName.isEmpty() || isResultCheckColumnAdEmpty(row)) {
continue;
}
BigDecimal adValue = readNumericCellValue(row.getCell(RESULT_CHECK_COL_SELL_ORDER_AMOUNT));
sumByAcNickname.merge(acName, adValue, BigDecimal::add);
}
Set<Integer> displayRows = resolveConsecutiveLastRowsByColumnAc(sheet, dataEndRow);
for (int rowIdx = 1; rowIdx <= dataEndRow; rowIdx++) {
Row row = sheet.getRow(rowIdx);
if (row == null || isResultMatchSumLabelRow(row)) {
continue;
}
String acName = normalizeResultCheckNickname(
readPaymentCellText(row.getCell(RESULT_CHECK_COL_SELL_ORDER_NICKNAME)));
if (displayRows.contains(rowIdx)) {
BigDecimal sum = sumByAcNickname.getOrDefault(acName, BigDecimal.ZERO);
createPaymentActualCell(
row, RESULT_CHECK_COL_SELL_ORDER_AD_SUM, sum, paymentActualStyle(rowIdx, styles));
} else {
createTextCell(row, RESULT_CHECK_COL_SELL_ORDER_AD_SUM, "", styles.textStyle);
}
}
}
/** AA 列:按 Y 列昵称汇总 Z 列订单金额,连续相同昵称仅末行展示。 */
private static void fillResultCheckColumnAaSumByYNickname(Sheet sheet, SheetStyles styles) {
int dataEndRow = resolveResultCheckDataEndRow(sheet);
if (dataEndRow < 1) {
return;
}
Map<String, BigDecimal> sumByYNickname = new HashMap<>();
for (int rowIdx = 1; rowIdx <= dataEndRow; rowIdx++) {
Row row = sheet.getRow(rowIdx);
if (row == null || isResultMatchSumLabelRow(row)) {
continue;
}
String yName = normalizeResultCheckNickname(
readPaymentCellText(row.getCell(RESULT_CHECK_COL_BUY_ORDER_NICKNAME)));
if (yName.isEmpty() || isResultCheckColumnZEmpty(row)) {
continue;
}
BigDecimal zValue = readNumericCellValue(row.getCell(RESULT_CHECK_COL_BUY_ORDER_AMOUNT));
sumByYNickname.merge(yName, zValue, BigDecimal::add);
}
Set<Integer> displayRows = resolveConsecutiveLastRowsByColumnY(sheet, dataEndRow);
for (int rowIdx = 1; rowIdx <= dataEndRow; rowIdx++) {
Row row = sheet.getRow(rowIdx);
if (row == null || isResultMatchSumLabelRow(row)) {
continue;
}
String yName = normalizeResultCheckNickname(
readPaymentCellText(row.getCell(RESULT_CHECK_COL_BUY_ORDER_NICKNAME)));
if (displayRows.contains(rowIdx)) {
BigDecimal sum = sumByYNickname.getOrDefault(yName, BigDecimal.ZERO);
createPaymentActualCell(
row, RESULT_CHECK_COL_BUY_ORDER_YZ_SUM, sum, paymentActualStyle(rowIdx, styles));
} else {
createTextCell(row, RESULT_CHECK_COL_BUY_ORDER_YZ_SUM, "", styles.textStyle);
}
}
}
private static Set<Integer> resolveConsecutiveLastRowsByColumnY(Sheet sheet, int dataEndRow) {
Set<Integer> displayRows = new HashSet<>();
String groupNickname = null;
int groupLastRow = -1;
for (int rowIdx = 1; rowIdx <= dataEndRow; rowIdx++) {
Row row = sheet.getRow(rowIdx);
if (row == null || isResultMatchSumLabelRow(row)) {
flushResultCheckNicknameGroup(displayRows, groupNickname, groupLastRow);
groupNickname = null;
groupLastRow = -1;
continue;
}
String yName = normalizeResultCheckNickname(
readPaymentCellText(row.getCell(RESULT_CHECK_COL_BUY_ORDER_NICKNAME)));
if (yName.isEmpty()) {
flushResultCheckNicknameGroup(displayRows, groupNickname, groupLastRow);
groupNickname = null;
groupLastRow = -1;
continue;
}
if (!yName.equals(groupNickname)) {
flushResultCheckNicknameGroup(displayRows, groupNickname, groupLastRow);
groupNickname = yName;
}
groupLastRow = rowIdx;
}
flushResultCheckNicknameGroup(displayRows, groupNickname, groupLastRow);
return displayRows;
}
private static Set<Integer> resolveConsecutiveLastRowsByColumnAc(Sheet sheet, int dataEndRow) {
Set<Integer> displayRows = new HashSet<>();
String groupNickname = null;
int groupLastRow = -1;
for (int rowIdx = 1; rowIdx <= dataEndRow; rowIdx++) {
Row row = sheet.getRow(rowIdx);
if (row == null || isResultMatchSumLabelRow(row)) {
flushResultCheckNicknameGroup(displayRows, groupNickname, groupLastRow);
groupNickname = null;
groupLastRow = -1;
continue;
}
String acName = normalizeResultCheckNickname(
readPaymentCellText(row.getCell(RESULT_CHECK_COL_SELL_ORDER_NICKNAME)));
if (acName.isEmpty()) {
flushResultCheckNicknameGroup(displayRows, groupNickname, groupLastRow);
groupNickname = null;
groupLastRow = -1;
continue;
}
if (!acName.equals(groupNickname)) {
flushResultCheckNicknameGroup(displayRows, groupNickname, groupLastRow);
groupNickname = acName;
}
groupLastRow = rowIdx;
}
flushResultCheckNicknameGroup(displayRows, groupNickname, groupLastRow);
return displayRows;
}
private static List<BigDecimal> parseOrderAmountDetailText(String detail) {
if (detail == null || detail.isBlank()) {
return List.of();
}
List<BigDecimal> amounts = new ArrayList<>();
for (String part : detail.split("\\+")) {
String trimmed = part.trim();
if (trimmed.isEmpty()) {
continue;
}
try {
amounts.add(new BigDecimal(trimmed));
} catch (NumberFormatException ignored) {
// skip invalid segment
}
}
return amounts;
}
private static int findNextEmptyResultCheckColumnZ(Sheet sheet, int startRow) {
int rowIdx = Math.max(1, startRow);
while (true) {
Row row = sheet.getRow(rowIdx);
if (row == null || isResultCheckColumnZEmpty(row)) {
return rowIdx;
}
rowIdx++;
}
}
private static int findNextEmptyResultCheckColumnAd(Sheet sheet, int startRow) {
int rowIdx = Math.max(1, startRow);
while (true) {
Row row = sheet.getRow(rowIdx);
if (row == null || isResultCheckColumnAdEmpty(row)) {
return rowIdx;
}
rowIdx++;
}
}
private static boolean isResultCheckColumnYEmpty(Row row) {
if (row == null) {
return true;
}
Cell cell = row.getCell(RESULT_CHECK_COL_BUY_ORDER_NICKNAME);
if (cell == null || cell.getCellType() == CellType.BLANK) {
return true;
}
if (cell.getCellType() == CellType.STRING) {
String text = cell.getStringCellValue();
return text == null || text.trim().isEmpty();
}
return false;
}
private static boolean isResultCheckColumnZEmpty(Row row) {
if (row == null) {
return true;
}
Cell cell = row.getCell(RESULT_CHECK_COL_BUY_ORDER_AMOUNT);
if (cell == null || cell.getCellType() == CellType.BLANK) {
return true;
}
if (cell.getCellType() == CellType.STRING) {
String text = cell.getStringCellValue();
return text == null || text.trim().isEmpty();
}
return false;
}
private static boolean isResultCheckColumnAcEmpty(Row row) {
if (row == null) {
return true;
}
Cell cell = row.getCell(RESULT_CHECK_COL_SELL_ORDER_NICKNAME);
if (cell == null || cell.getCellType() == CellType.BLANK) {
return true;
}
if (cell.getCellType() == CellType.STRING) {
String text = cell.getStringCellValue();
return text == null || text.trim().isEmpty();
}
return false;
}
private static boolean isResultCheckColumnAdEmpty(Row row) {
if (row == null) {
return true;
}
Cell cell = row.getCell(RESULT_CHECK_COL_SELL_ORDER_AMOUNT);
if (cell == null || cell.getCellType() == CellType.BLANK) {
return true;
}
if (cell.getCellType() == CellType.STRING) {
String text = cell.getStringCellValue();
return text == null || text.trim().isEmpty();
}
return false;
}
/** 结果表检查表:末行追加 L、M、T、W、Z、AA 列数据合计。 */
private static void writeResultCheckColumnLAndMSum(Sheet sheet, SheetStyles styles) {
int lastRow = sheet.getLastRowNum();
if (lastRow < 1) {
@@ -562,6 +920,10 @@ public final class LbDailyUserTradeReportExportSupport {
BigDecimal sumL = BigDecimal.ZERO;
BigDecimal sumM = BigDecimal.ZERO;
BigDecimal sumT = BigDecimal.ZERO;
BigDecimal sumW = BigDecimal.ZERO;
BigDecimal sumZ = BigDecimal.ZERO;
BigDecimal sumAa = BigDecimal.ZERO;
for (int rowIdx = 1; rowIdx <= dataEndRow; rowIdx++) {
Row row = sheet.getRow(rowIdx);
if (row == null || isResultMatchSumLabelRow(row)) {
@@ -571,6 +933,18 @@ public final class LbDailyUserTradeReportExportSupport {
if (!isResultCheckColumnMEmpty(row)) {
sumM = sumM.add(readNumericCellValue(row.getCell(RESULT_CHECK_COL_IK_NICKNAME_L_SUM)));
}
if (!isResultCheckColumnTEmpty(row)) {
sumT = sumT.add(readNumericCellValue(row.getCell(RESULT_CHECK_COL_BUY_TOTAL)));
}
if (!isResultCheckColumnWEmpty(row)) {
sumW = sumW.add(readNumericCellValue(row.getCell(RESULT_CHECK_COL_SELL_TOTAL)));
}
if (!isResultCheckColumnZEmpty(row)) {
sumZ = sumZ.add(readNumericCellValue(row.getCell(RESULT_CHECK_COL_BUY_ORDER_AMOUNT)));
}
if (!isResultCheckColumnAaEmpty(row)) {
sumAa = sumAa.add(readNumericCellValue(row.getCell(RESULT_CHECK_COL_BUY_ORDER_YZ_SUM)));
}
}
int sumRowIdx = dataEndRow + 1;
@@ -582,6 +956,163 @@ public final class LbDailyUserTradeReportExportSupport {
createTextCell(sumRow, RESULT_MATCH_NEG_NAME, "求和", styles.summaryTextStyle);
createPaymentActualCell(sumRow, RESULT_MATCH_AMT, sumL, styles.summaryRoundedAmountStyle);
createPaymentActualCell(sumRow, RESULT_CHECK_COL_IK_NICKNAME_L_SUM, sumM, styles.summaryRoundedAmountStyle);
createDecimalCell(sumRow, RESULT_CHECK_COL_BUY_TOTAL, sumT, styles.summaryAmountStyle);
createDecimalCell(sumRow, RESULT_CHECK_COL_SELL_TOTAL, sumW, styles.summaryAmountStyle);
createPaymentActualCell(sumRow, RESULT_CHECK_COL_BUY_ORDER_AMOUNT, sumZ, styles.summaryRoundedAmountStyle);
createPaymentActualCell(sumRow, RESULT_CHECK_COL_BUY_ORDER_YZ_SUM, sumAa, styles.summaryRoundedAmountStyle);
}
/**
* 总表 D 列(当日买入)与检查表 T 列(订单买入)按昵称核对;差异写在求和行之后。
* 总表 A 列昵称 ↔ 检查表 Q 列昵称。
*/
private static void writeResultCheckBuyAmountDiffRows(
Sheet checkSheet, Sheet summarySheet, SheetStyles styles) {
if (summarySheet == null) {
return;
}
int sumRowIdx = findResultCheckSumRowIndex(checkSheet);
if (sumRowIdx < 1) {
return;
}
Map<String, BigDecimal> summaryBuyByNickname = readSummaryDailyBuyByNickname(summarySheet);
Map<String, BigDecimal> checkBuyByNickname = readCheckBuyByNickname(checkSheet, sumRowIdx - 1);
List<BuyAmountDiffItem> diffItems = buildBuyAmountDiffItems(summaryBuyByNickname, checkBuyByNickname);
BigDecimal summaryTotal = readSummarySheetDailyBuyTotal(summarySheet);
Row sumRow = checkSheet.getRow(sumRowIdx);
BigDecimal checkTotal = sumRow == null
? BigDecimal.ZERO
: readNumericCellValue(sumRow.getCell(RESULT_CHECK_COL_BUY_TOTAL));
int writeRow = sumRowIdx + 1;
Row titleRow = ensureResultCheckRow(checkSheet, writeRow++, styles);
createTextCell(titleRow, RESULT_MATCH_NEG_NAME, "【买入核对差异】", styles.summaryTextStyle);
if (summaryTotal.compareTo(checkTotal) != 0) {
Row totalDiffRow = ensureResultCheckRow(checkSheet, writeRow++, styles);
createTextCell(totalDiffRow, RESULT_MATCH_NEG_NAME, "合计差异", styles.summaryTextStyle);
createTextCell(totalDiffRow, RESULT_CHECK_COL_NICKNAME, "合计", styles.summaryTextStyle);
createDecimalCell(totalDiffRow, RESULT_CHECK_COL_BUY_DIFF_SUMMARY, summaryTotal, styles.summaryAmountStyle);
createDecimalCell(totalDiffRow, RESULT_CHECK_COL_BUY_DIFF_CHECK, checkTotal, styles.summaryAmountStyle);
createDecimalCell(
totalDiffRow,
RESULT_CHECK_COL_BUY_DIFF,
summaryTotal.subtract(checkTotal),
styles.summaryAmountStyle);
}
if (diffItems.isEmpty()) {
Row okRow = ensureResultCheckRow(checkSheet, writeRow, styles);
createTextCell(okRow, RESULT_MATCH_NEG_NAME, "无昵称级差异", styles.textStyle);
return;
}
for (BuyAmountDiffItem item : diffItems) {
Row row = ensureResultCheckRow(checkSheet, writeRow++, styles);
createTextCell(row, RESULT_MATCH_NEG_NAME, item.reason(), styles.textStyle);
createTextCell(row, RESULT_CHECK_COL_NICKNAME, item.nickname(), styles.textStyle);
if (item.summaryBuyAmt() != null) {
createDecimalCell(row, RESULT_CHECK_COL_BUY_DIFF_SUMMARY, item.summaryBuyAmt(), styles.amountStyle);
}
if (item.checkBuyAmt() != null) {
createDecimalCell(row, RESULT_CHECK_COL_BUY_DIFF_CHECK, item.checkBuyAmt(), styles.amountStyle);
}
createDecimalCell(row, RESULT_CHECK_COL_BUY_DIFF, item.diffAmt(), styles.amountStyle);
}
}
private static int findResultCheckSumRowIndex(Sheet sheet) {
for (int rowIdx = sheet.getLastRowNum(); rowIdx >= 1; rowIdx--) {
Row row = sheet.getRow(rowIdx);
if (row != null && isResultMatchSumLabelRow(row)) {
return rowIdx;
}
}
return -1;
}
private static Map<String, BigDecimal> readSummaryDailyBuyByNickname(Sheet summarySheet) {
Map<String, BigDecimal> buyByNickname = new LinkedHashMap<>();
int lastRow = summarySheet.getLastRowNum();
for (int rowIdx = 1; rowIdx <= lastRow; rowIdx++) {
Row row = summarySheet.getRow(rowIdx);
if (row == null) {
continue;
}
String nickname = normalizeResultCheckNickname(readPaymentCellText(row.getCell(COL_NICKNAME)));
if (nickname.isEmpty()) {
continue;
}
buyByNickname.put(nickname, readNumericCellValue(row.getCell(COL_DAILY_BUY)));
}
return buyByNickname;
}
private static BigDecimal readSummarySheetDailyBuyTotal(Sheet summarySheet) {
int lastRow = summarySheet.getLastRowNum();
if (lastRow < 1) {
return BigDecimal.ZERO;
}
Row lastDataRow = summarySheet.getRow(lastRow);
if (lastDataRow == null) {
return BigDecimal.ZERO;
}
return readNumericCellValue(lastDataRow.getCell(COL_DAILY_BUY));
}
private static Map<String, BigDecimal> readCheckBuyByNickname(Sheet checkSheet, int dataEndRow) {
Map<String, BigDecimal> buyByNickname = new LinkedHashMap<>();
for (int rowIdx = 1; rowIdx <= dataEndRow; rowIdx++) {
Row row = checkSheet.getRow(rowIdx);
if (row == null || isResultMatchSumLabelRow(row)) {
continue;
}
String nickname = normalizeResultCheckNickname(
readPaymentCellText(row.getCell(RESULT_CHECK_COL_NICKNAME)));
if (nickname.isEmpty() || isResultCheckColumnTEmpty(row)) {
continue;
}
buyByNickname.put(nickname, readNumericCellValue(row.getCell(RESULT_CHECK_COL_BUY_TOTAL)));
}
return buyByNickname;
}
private static List<BuyAmountDiffItem> buildBuyAmountDiffItems(
Map<String, BigDecimal> summaryBuyByNickname,
Map<String, BigDecimal> checkBuyByNickname) {
LinkedHashSet<String> allNicknames = new LinkedHashSet<>();
allNicknames.addAll(summaryBuyByNickname.keySet());
allNicknames.addAll(checkBuyByNickname.keySet());
List<BuyAmountDiffItem> diffItems = new ArrayList<>();
for (String nickname : allNicknames) {
boolean inSummary = summaryBuyByNickname.containsKey(nickname);
boolean inCheck = checkBuyByNickname.containsKey(nickname);
BigDecimal summaryAmt = summaryBuyByNickname.get(nickname);
BigDecimal checkAmt = checkBuyByNickname.get(nickname);
if (inSummary && !inCheck) {
diffItems.add(new BuyAmountDiffItem(
nickname, summaryAmt, null, "仅总表有", summaryAmt));
} else if (!inSummary && inCheck) {
diffItems.add(new BuyAmountDiffItem(
nickname, null, checkAmt, "仅检查表有", defaultZero(checkAmt).negate()));
} else if (inSummary && summaryAmt.compareTo(checkAmt) != 0) {
diffItems.add(new BuyAmountDiffItem(
nickname, summaryAmt, checkAmt, "金额不一致", summaryAmt.subtract(checkAmt)));
}
}
return diffItems;
}
private record BuyAmountDiffItem(
String nickname,
BigDecimal summaryBuyAmt,
BigDecimal checkBuyAmt,
String reason,
BigDecimal diffAmt) {
}
/**
@@ -721,6 +1252,44 @@ public final class LbDailyUserTradeReportExportSupport {
return false;
}
private static boolean isResultCheckColumnTEmpty(Row row) {
return isResultCheckNumericColumnEmpty(row, RESULT_CHECK_COL_BUY_TOTAL);
}
private static boolean isResultCheckColumnWEmpty(Row row) {
return isResultCheckNumericColumnEmpty(row, RESULT_CHECK_COL_SELL_TOTAL);
}
private static boolean isResultCheckNumericColumnEmpty(Row row, int col) {
if (row == null) {
return true;
}
Cell cell = row.getCell(col);
if (cell == null || cell.getCellType() == CellType.BLANK) {
return true;
}
if (cell.getCellType() == CellType.STRING) {
String text = cell.getStringCellValue();
return text == null || text.trim().isEmpty();
}
return false;
}
private static boolean isResultCheckColumnAaEmpty(Row row) {
if (row == null) {
return true;
}
Cell cell = row.getCell(RESULT_CHECK_COL_BUY_ORDER_YZ_SUM);
if (cell == null || cell.getCellType() == CellType.BLANK) {
return true;
}
if (cell.getCellType() == CellType.STRING) {
String text = cell.getStringCellValue();
return text == null || text.trim().isEmpty();
}
return false;
}
/** 参与 K 列汇总I、K 列昵称均非空。 */
private static boolean includeRowForColumnKSum(String iName, String kName) {
return !iName.isEmpty() && !kName.isEmpty();
@@ -865,6 +1434,15 @@ public final class LbDailyUserTradeReportExportSupport {
createHeaderCell(header, RESULT_CHECK_COL_BUY_TOTAL_FEE, "1%金额", styles.headerStyle);
createHeaderCell(header, RESULT_CHECK_COL_SELL_DETAIL, "卖出金额明细", styles.headerStyle);
createHeaderCell(header, RESULT_CHECK_COL_SELL_TOTAL, "当日卖出金额", styles.headerStyle);
createHeaderCell(header, RESULT_CHECK_COL_BUY_ORDER_NICKNAME, "订单昵称", styles.headerStyle);
createHeaderCell(header, RESULT_CHECK_COL_BUY_ORDER_AMOUNT, "订单金额", styles.headerStyle);
createHeaderCell(header, RESULT_CHECK_COL_BUY_ORDER_YZ_SUM, "Y昵称Z列合计", styles.headerStyle);
createHeaderCell(header, RESULT_CHECK_COL_SELL_ORDER_NICKNAME, "卖出订单昵称", styles.headerStyle);
createHeaderCell(header, RESULT_CHECK_COL_SELL_ORDER_AMOUNT, "卖出订单金额", styles.headerStyle);
createHeaderCell(header, RESULT_CHECK_COL_SELL_ORDER_AD_SUM, "AC昵称AD列合计", styles.headerStyle);
createHeaderCell(header, RESULT_CHECK_COL_BUY_DIFF_SUMMARY, "总表买入", styles.headerStyle);
createHeaderCell(header, RESULT_CHECK_COL_BUY_DIFF_CHECK, "检查表买入", styles.headerStyle);
createHeaderCell(header, RESULT_CHECK_COL_BUY_DIFF, "买入差异", styles.headerStyle);
}
private static void copyResultSheetContent(Sheet source, Sheet target) {

View File

@@ -23,7 +23,7 @@ hxr:
cookie: PHPSID=f3710baf6381da418aa832660ccb9d08
phpsid: "f3710baf6381da418aa832660ccb9d08"
# 货品同步 /api/order/goodsLbGoodsController#sync-from-hxr
goods-api-token: "04e2a8aa-d178-4da4-b97f-057849607824"
goods-api-token: "e176f641-4425-4930-bab3-3cfdc2a8fd2a"
goods-api-app-str: "ssniQQ3UP2Vr8mXwaugssgaOLzQo0cX5"
goods-api-origin: "https://hxrdweb.hxrdsm.cn"
goods-api-referer: "https://hxrdweb.hxrdsm.cn/"