报表检查表
This commit is contained in:
@@ -220,7 +220,7 @@ public class LbGoodsServiceImpl extends ServiceImpl<LbGoodsMapper, LbGoods> impl
|
|||||||
w.le(LbGoods::getUpdatedAt, updatedEnd);
|
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);
|
Page<LbGoods> page = this.page(new Page<>(current, size), w);
|
||||||
result.put("success", true);
|
result.put("success", true);
|
||||||
|
|||||||
@@ -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_BUY_TOTAL_FEE = 20;
|
||||||
private static final int RESULT_CHECK_COL_SELL_DETAIL = 21;
|
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_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;
|
||||||
|
/** 结果表检查表 AF~AH:总表与检查表买入差异核对。 */
|
||||||
|
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 BigDecimal RESULT_CHECK_BUY_TOTAL_FEE_RATE = new BigDecimal("0.01");
|
||||||
|
|
||||||
private static final int PAYMENT_COL_NAME = 0;
|
private static final int PAYMENT_COL_NAME = 0;
|
||||||
@@ -140,6 +154,7 @@ public final class LbDailyUserTradeReportExportSupport {
|
|||||||
fillResultCheckSheet(
|
fillResultCheckSheet(
|
||||||
workbook.getSheetAt(RESULT_CHECK_SHEET_INDEX),
|
workbook.getSheetAt(RESULT_CHECK_SHEET_INDEX),
|
||||||
resultSheet,
|
resultSheet,
|
||||||
|
workbook.getSheetAt(SUMMARY_SHEET_INDEX),
|
||||||
userIdByNickname,
|
userIdByNickname,
|
||||||
buyTotalByBuyerId,
|
buyTotalByBuyerId,
|
||||||
buyDetailByBuyerId,
|
buyDetailByBuyerId,
|
||||||
@@ -454,6 +469,7 @@ public final class LbDailyUserTradeReportExportSupport {
|
|||||||
private static void fillResultCheckSheet(
|
private static void fillResultCheckSheet(
|
||||||
Sheet target,
|
Sheet target,
|
||||||
Sheet resultSource,
|
Sheet resultSource,
|
||||||
|
Sheet summarySheet,
|
||||||
Map<String, String> userIdByNickname,
|
Map<String, String> userIdByNickname,
|
||||||
Map<String, BigDecimal> buyTotalByBuyerId,
|
Map<String, BigDecimal> buyTotalByBuyerId,
|
||||||
Map<String, String> buyDetailByBuyerId,
|
Map<String, String> buyDetailByBuyerId,
|
||||||
@@ -540,11 +556,353 @@ public final class LbDailyUserTradeReportExportSupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fillResultCheckColumnsMandNByIandKNickname(target, styles);
|
fillResultCheckColumnsMandNByIandKNickname(target, styles);
|
||||||
|
fillResultCheckColumnZFromColumnS(target, styles);
|
||||||
|
fillResultCheckColumnAdFromColumnV(target, styles);
|
||||||
|
fillResultCheckColumnAaSumByYNickname(target, styles);
|
||||||
|
fillResultCheckColumnAeSumByAcNickname(target, styles);
|
||||||
writeResultCheckColumnLAndMSum(target, styles);
|
writeResultCheckColumnLAndMSum(target, styles);
|
||||||
|
writeResultCheckBuyAmountDiffRows(target, summarySheet, styles);
|
||||||
autoSizeColumns(target, RESULT_CHECK_LAST_COL);
|
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) {
|
private static void writeResultCheckColumnLAndMSum(Sheet sheet, SheetStyles styles) {
|
||||||
int lastRow = sheet.getLastRowNum();
|
int lastRow = sheet.getLastRowNum();
|
||||||
if (lastRow < 1) {
|
if (lastRow < 1) {
|
||||||
@@ -562,6 +920,10 @@ public final class LbDailyUserTradeReportExportSupport {
|
|||||||
|
|
||||||
BigDecimal sumL = BigDecimal.ZERO;
|
BigDecimal sumL = BigDecimal.ZERO;
|
||||||
BigDecimal sumM = 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++) {
|
for (int rowIdx = 1; rowIdx <= dataEndRow; rowIdx++) {
|
||||||
Row row = sheet.getRow(rowIdx);
|
Row row = sheet.getRow(rowIdx);
|
||||||
if (row == null || isResultMatchSumLabelRow(row)) {
|
if (row == null || isResultMatchSumLabelRow(row)) {
|
||||||
@@ -571,6 +933,18 @@ public final class LbDailyUserTradeReportExportSupport {
|
|||||||
if (!isResultCheckColumnMEmpty(row)) {
|
if (!isResultCheckColumnMEmpty(row)) {
|
||||||
sumM = sumM.add(readNumericCellValue(row.getCell(RESULT_CHECK_COL_IK_NICKNAME_L_SUM)));
|
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;
|
int sumRowIdx = dataEndRow + 1;
|
||||||
@@ -582,6 +956,163 @@ public final class LbDailyUserTradeReportExportSupport {
|
|||||||
createTextCell(sumRow, RESULT_MATCH_NEG_NAME, "求和", styles.summaryTextStyle);
|
createTextCell(sumRow, RESULT_MATCH_NEG_NAME, "求和", styles.summaryTextStyle);
|
||||||
createPaymentActualCell(sumRow, RESULT_MATCH_AMT, sumL, styles.summaryRoundedAmountStyle);
|
createPaymentActualCell(sumRow, RESULT_MATCH_AMT, sumL, styles.summaryRoundedAmountStyle);
|
||||||
createPaymentActualCell(sumRow, RESULT_CHECK_COL_IK_NICKNAME_L_SUM, sumM, 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;
|
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 列昵称均非空。 */
|
/** 参与 K 列汇总:I、K 列昵称均非空。 */
|
||||||
private static boolean includeRowForColumnKSum(String iName, String kName) {
|
private static boolean includeRowForColumnKSum(String iName, String kName) {
|
||||||
return !iName.isEmpty() && !kName.isEmpty();
|
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_BUY_TOTAL_FEE, "1%金额", styles.headerStyle);
|
||||||
createHeaderCell(header, RESULT_CHECK_COL_SELL_DETAIL, "卖出金额明细", 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_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) {
|
private static void copyResultSheetContent(Sheet source, Sheet target) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ hxr:
|
|||||||
cookie: PHPSID=f3710baf6381da418aa832660ccb9d08
|
cookie: PHPSID=f3710baf6381da418aa832660ccb9d08
|
||||||
phpsid: "f3710baf6381da418aa832660ccb9d08"
|
phpsid: "f3710baf6381da418aa832660ccb9d08"
|
||||||
# 货品同步 /api/order/goods(LbGoodsController#sync-from-hxr)
|
# 货品同步 /api/order/goods(LbGoodsController#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-app-str: "ssniQQ3UP2Vr8mXwaugssgaOLzQo0cX5"
|
||||||
goods-api-origin: "https://hxrdweb.hxrdsm.cn"
|
goods-api-origin: "https://hxrdweb.hxrdsm.cn"
|
||||||
goods-api-referer: "https://hxrdweb.hxrdsm.cn/"
|
goods-api-referer: "https://hxrdweb.hxrdsm.cn/"
|
||||||
|
|||||||
Reference in New Issue
Block a user