| Line 158... |
Line 158... |
| 158 |
@Autowired
|
158 |
@Autowired
|
| 159 |
LoanRepository loanRepository;
|
159 |
LoanRepository loanRepository;
|
| 160 |
@Autowired
|
160 |
@Autowired
|
| 161 |
private LoanStatementRepository loanStatementRepository;
|
161 |
private LoanStatementRepository loanStatementRepository;
|
| 162 |
@Autowired
|
162 |
@Autowired
|
| - |
|
163 |
private ReturnOrderInfoRepository returnOrderInfoRepository;
|
| - |
|
164 |
@Autowired
|
| 163 |
SDCreditRequirementRepository sdCreditRequirementRepository;
|
165 |
SDCreditRequirementRepository sdCreditRequirementRepository;
|
| 164 |
@Autowired
|
166 |
@Autowired
|
| 165 |
LoiFormRepository loiFormRepository;
|
167 |
LoiFormRepository loiFormRepository;
|
| 166 |
@Autowired
|
168 |
@Autowired
|
| 167 |
PartnerOnBoardingPanelRepository partnerOnBoardingPanelRepository;
|
169 |
PartnerOnBoardingPanelRepository partnerOnBoardingPanelRepository;
|
| Line 884... |
Line 886... |
| 884 |
float closingBalance = walletService.getOpeningTill(fofoId, endDate);
|
886 |
float closingBalance = walletService.getOpeningTill(fofoId, endDate);
|
| 885 |
UserWallet uw = walletService.getUserWallet(fofoId);
|
887 |
UserWallet uw = walletService.getUserWallet(fofoId);
|
| 886 |
LOGGER.info("Start date - {}, end Date - {}", startDate, endDate);
|
888 |
LOGGER.info("Start date - {}, end Date - {}", startDate, endDate);
|
| 887 |
List<UserWalletHistory> history = userWalletHistoryRepository.selectPaginatedByWalletId(uw.getId(), startDate, endDate, 0, 0);
|
889 |
List<UserWalletHistory> history = userWalletHistoryRepository.selectPaginatedByWalletId(uw.getId(), startDate, endDate, 0, 0);
|
| 888 |
//LOGGER.info("Data - {}", history.stream().filter(x -> x.getReferenceType().equals(WalletReferenceType.OTHERS)).collect(Collectors.groupingBy(x -> x.getBusinessTimestamp().toLocalDate())));
|
890 |
//LOGGER.info("Data - {}", history.stream().filter(x -> x.getReferenceType().equals(WalletReferenceType.OTHERS)).collect(Collectors.groupingBy(x -> x.getBusinessTimestamp().toLocalDate())));
|
| - |
|
891 |
// Body shows genuine money movements. Exclude: PURCHASE (rebuilt via billing); the loan cash legs
|
| - |
|
892 |
// CREDIT_LIMIT/CREDIT_UTILIZED (represented by the Interest Accrued line + opening/closing loan); and the
|
| - |
|
893 |
// scheme set CN_WALLET_REFERENCES (shown instead as the month-end MARGINS credit-note line).
|
| 889 |
history = history.stream().filter(x -> !x.getReferenceType().equals(WalletReferenceType.PURCHASE))
|
894 |
history = history.stream().filter(x -> !x.getReferenceType().equals(WalletReferenceType.PURCHASE))
|
| - |
|
895 |
.filter(x -> !x.getReferenceType().equals(WalletReferenceType.CREDIT_LIMIT))
|
| - |
|
896 |
.filter(x -> !x.getReferenceType().equals(WalletReferenceType.CREDIT_UTILIZED))
|
| 890 |
.filter(x -> !WalletService.CN_WALLET_REFERENCES.contains(x.getReferenceType())).sorted(Comparator.comparing(UserWalletHistory::getId)).collect(Collectors.toList());
|
897 |
.filter(x -> !WalletService.CN_WALLET_REFERENCES.contains(x.getReferenceType()))
|
| 891 |
//LOGGER.info("Data - {}", history.stream().filter(x -> x.getReferenceType().equals(WalletReferenceType.OTHERS)).collect(Collectors.groupingBy(x -> x.getBusinessTimestamp().toLocalDate())));
|
898 |
.sorted(Comparator.comparing(UserWalletHistory::getId)).collect(Collectors.toList());
|
| 892 |
|
899 |
|
| 893 |
InputStream is = getClass().getClassLoader().getResourceAsStream("account-statement.xlsx");
|
900 |
InputStream is = getClass().getClassLoader().getResourceAsStream("account-statement.xlsx");
|
| 894 |
CustomRetailer customRetailer = retailerService.getAllFofoRetailers().get(fofoId);
|
901 |
CustomRetailer customRetailer = retailerService.getAllFofoRetailers().get(fofoId);
|
| 895 |
List<StatementDetailModel> billedStatementDetails = orderRepository.selectDetailsBetween(fofoId, startDate, endDate);
|
902 |
List<StatementDetailModel> billedStatementDetails = orderRepository.selectDetailsBetween(fofoId, startDate, endDate);
|
| - |
|
903 |
List<StatementDetailModel> returnDetails = returnOrderInfoRepository.selectReturnsBetween(fofoId, startDate, endDate);
|
| 896 |
Map<Integer, Float> openingAmountMap = transactionService.getPendingIndentValueMap(startDate, Optional.of(fofoId));
|
904 |
Map<Integer, Float> openingAmountMap = transactionService.getPendingIndentValueMap(startDate, Optional.of(fofoId));
|
| 897 |
Map<Integer, Float> closingAmountMap = transactionService.getPendingIndentValueMap(endDate, Optional.of(fofoId));
|
905 |
Map<Integer, Float> closingAmountMap = transactionService.getPendingIndentValueMap(endDate, Optional.of(fofoId));
|
| 898 |
|
906 |
|
| 899 |
float openingPendingAmount = openingAmountMap.get(fofoId) == null ? 0 : openingAmountMap.get(fofoId);
|
907 |
float openingPendingAmount = openingAmountMap.get(fofoId) == null ? 0 : openingAmountMap.get(fofoId);
|
| 900 |
float closingPendingAmount = closingAmountMap.get(fofoId) == null ? 0 : closingAmountMap.get(fofoId);
|
908 |
float closingPendingAmount = closingAmountMap.get(fofoId) == null ? 0 : closingAmountMap.get(fofoId);
|
| - |
|
909 |
float openingLoan = loanStatementRepository.getLoanPrincipalAtDate(fofoId, startDate) + loanStatementRepository.getLoanInterestAtDate(fofoId, startDate);
|
| - |
|
910 |
float closingLoan = loanStatementRepository.getLoanPrincipalAtDate(fofoId, endDate) + loanStatementRepository.getLoanInterestAtDate(fofoId, endDate);
|
| - |
|
911 |
float interestAccruedCost = loanStatementRepository.getInterestAccruedBetween(fofoId, startDate, endDate);
|
| 901 |
LOGGER.info("Opening - {}, Closing - {}", openingPendingAmount, closingPendingAmount);
|
912 |
LOGGER.info("OpeningPI - {}, ClosingPI - {}, OpeningLoan - {}, ClosingLoan - {}, InterestAccrued - {}", openingPendingAmount, closingPendingAmount, openingLoan, closingLoan, interestAccruedCost);
|
| 902 |
ByteArrayOutputStream byteArrayOutputStream = this.populateData(is, openingBalance + openingPendingAmount, closingBalance + closingPendingAmount,
|
913 |
ByteArrayOutputStream byteArrayOutputStream = this.populateData(is, openingBalance + openingPendingAmount - openingLoan, closingBalance + closingPendingAmount - closingLoan,
|
| 903 |
customRetailer, history, startDate, endDate, billedStatementDetails);
|
914 |
customRetailer, history, startDate, endDate, billedStatementDetails, returnDetails, interestAccruedCost);
|
| 904 |
|
915 |
|
| 905 |
final HttpHeaders headers = new HttpHeaders();
|
916 |
final HttpHeaders headers = new HttpHeaders();
|
| 906 |
headers.set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
917 |
headers.set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
| 907 |
headers.set("Content-disposition", "inline; filename=account-statement." + StringUtils.toHyphenatedString(startDate.toLocalDate()) + "-" + StringUtils.toHyphenatedString(endDate.toLocalDate()) + ".xlsx");
|
918 |
headers.set("Content-disposition", "inline; filename=account-statement." + StringUtils.toHyphenatedString(startDate.toLocalDate()) + "-" + StringUtils.toHyphenatedString(endDate.toLocalDate()) + ".xlsx");
|
| 908 |
headers.setContentLength(byteArrayOutputStream.toByteArray().length);
|
919 |
headers.setContentLength(byteArrayOutputStream.toByteArray().length);
|
| Line 917... |
Line 928... |
| 917 |
@Autowired
|
928 |
@Autowired
|
| 918 |
CreditNoteRepository creditNoteRepository;
|
929 |
CreditNoteRepository creditNoteRepository;
|
| 919 |
@Autowired
|
930 |
@Autowired
|
| 920 |
CreditNoteLineRepository creditNoteLineRepository;
|
931 |
CreditNoteLineRepository creditNoteLineRepository;
|
| 921 |
|
932 |
|
| - |
|
933 |
// Friendly category for a statement line, keyed on the wallet reference-type or billing sub-type string.
|
| - |
|
934 |
private String statementCategory(String type) {
|
| - |
|
935 |
if (type == null) return "Other";
|
| - |
|
936 |
switch (type) {
|
| - |
|
937 |
case "ADVANCE_AMOUNT": case "AUTOMATED_ADVANCE": return "Advance / Payment";
|
| - |
|
938 |
case "PAYMENT_GATEWAY": case "RECHARGE": return "Payment";
|
| - |
|
939 |
case "SCHEME_IN": case "SCHEME_OUT": case "ADDITIONAL_SCHEME": case "ACTIVATION_SCHEME": return "Scheme / Margin";
|
| - |
|
940 |
case "CREDIT_LIMIT": case "CREDIT_UTILIZED": return "SD Credit (Loan)";
|
| - |
|
941 |
case "PURCHASE": return "Purchase / Order Refund";
|
| - |
|
942 |
case "REFUND": return "Refund";
|
| - |
|
943 |
case "PRICE_DROP": return "Price Drop";
|
| - |
|
944 |
case "BRAND_PAYOUT": case "INVESTMENT_PAYOUT": return "Payout";
|
| - |
|
945 |
case "SPECIAL_SUPPORT": return "Special Support";
|
| - |
|
946 |
case "DAMAGE_PROTECTION": return "Damage Protection";
|
| - |
|
947 |
case "PREBOOKING_ORDER": return "Prebooking Order";
|
| - |
|
948 |
// billing sub-types from selectDetailsBetween
|
| - |
|
949 |
case "BILLED": return "Billing / Invoice";
|
| - |
|
950 |
case "RTO": return "Cancellation (RTO)";
|
| - |
|
951 |
case "RETURNED": return "Return";
|
| - |
|
952 |
case "INVOICE_CANCELLED": return "Invoice Cancelled";
|
| - |
|
953 |
case "RETURNS_CN": return "Return (Credit Note)";
|
| - |
|
954 |
default: return "Other";
|
| - |
|
955 |
}
|
| - |
|
956 |
}
|
| - |
|
957 |
|
| 922 |
private ByteArrayOutputStream populateData(InputStream is, float openingBalance, float closingBalance, CustomRetailer customRetailer, List<UserWalletHistory> history,
|
958 |
private ByteArrayOutputStream populateData(InputStream is, float openingBalance, float closingBalance, CustomRetailer customRetailer, List<UserWalletHistory> history,
|
| 923 |
LocalDateTime startLocalDateTime, LocalDateTime endLocalDateTime, List<StatementDetailModel> invoiceDetails) throws Exception {
|
959 |
LocalDateTime startLocalDateTime, LocalDateTime endLocalDateTime, List<StatementDetailModel> invoiceDetails,
|
| - |
|
960 |
List<StatementDetailModel> returnDetails, float interestAccruedCost) throws Exception {
|
| 924 |
Map<LocalDate, List<StatementDetailModel>> dateInvoiceMap = invoiceDetails.stream().collect(Collectors.groupingBy(x -> x.getOnDate().toLocalDate()));
|
961 |
Map<LocalDate, List<StatementDetailModel>> dateInvoiceMap = invoiceDetails.stream().collect(Collectors.groupingBy(x -> x.getOnDate().toLocalDate()));
|
| - |
|
962 |
Map<LocalDate, List<StatementDetailModel>> dateReturnMap = returnDetails == null ? new HashMap<>()
|
| - |
|
963 |
: returnDetails.stream().collect(Collectors.groupingBy(x -> x.getOnDate().toLocalDate()));
|
| 925 |
//LOGGER.info("dateInvoiceMap - {}", dateInvoiceMap);
|
964 |
//LOGGER.info("dateInvoiceMap - {}", dateInvoiceMap);
|
| 926 |
Map<LocalDate, List<UserWalletHistory>> dateWalletMap = history.stream().collect(Collectors.groupingBy(x -> x.getTimestamp().toLocalDate()));
|
965 |
Map<LocalDate, List<UserWalletHistory>> dateWalletMap = history.stream().collect(Collectors.groupingBy(x -> x.getTimestamp().toLocalDate()));
|
| 927 |
XSSFWorkbook workbook = new XSSFWorkbook(is);
|
966 |
XSSFWorkbook workbook = new XSSFWorkbook(is);
|
| 928 |
CreationHelper creationHelper = workbook.getCreationHelper();
|
967 |
CreationHelper creationHelper = workbook.getCreationHelper();
|
| 929 |
CellStyle dateStyle = workbook.createCellStyle();
|
968 |
CellStyle dateStyle = workbook.createCellStyle();
|
| Line 968... |
Line 1007... |
| 968 |
grandTotalDebit -= walletEntry.getAmount();
|
1007 |
grandTotalDebit -= walletEntry.getAmount();
|
| 969 |
}
|
1008 |
}
|
| 970 |
//Running balance
|
1009 |
//Running balance
|
| 971 |
currentOpening += walletEntry.getAmount();
|
1010 |
currentOpening += walletEntry.getAmount();
|
| 972 |
sheet.getRow(row).createCell(5).setCellValue(currentOpening);
|
1011 |
sheet.getRow(row).createCell(5).setCellValue(currentOpening);
|
| 973 |
//Description
|
1012 |
//Category + Description
|
| - |
|
1013 |
String wCategory = statementCategory(walletEntry.getReferenceType().toString());
|
| 974 |
sheet.getRow(row).createCell(6).setCellValue(walletEntry.getDescription());
|
1014 |
String wDesc = walletEntry.getDescription();
|
| - |
|
1015 |
sheet.getRow(row).createCell(6).setCellValue(wDesc == null || wDesc.isEmpty() ? wCategory : wCategory + " — " + wDesc);
|
| 975 |
row++;
|
1016 |
row++;
|
| 976 |
}
|
1017 |
}
|
| 977 |
}
|
1018 |
}
|
| 978 |
List<StatementDetailModel> statementDetailModels = dateInvoiceMap.get(date);
|
1019 |
List<StatementDetailModel> statementDetailModels = dateInvoiceMap.get(date);
|
| 979 |
LOGGER.info("statementDetailModels - {}", statementDetailModels);
|
1020 |
LOGGER.info("statementDetailModels - {}", statementDetailModels);
|
| 980 |
if (statementDetailModels != null) {
|
1021 |
if (statementDetailModels != null) {
|
| 981 |
for (StatementDetailModel statementDetailModel : statementDetailModels) {
|
1022 |
for (StatementDetailModel statementDetailModel : statementDetailModels) {
|
| - |
|
1023 |
// Returns are shown individually from returnorderinfo below; skip the billing query's aggregated
|
| - |
|
1024 |
// RETURNED and the RETURNS_CN (returns are not taken from credit notes).
|
| - |
|
1025 |
if ("RETURNED".equals(statementDetailModel.getReferenceType())
|
| - |
|
1026 |
|| "RETURNS_CN".equals(statementDetailModel.getReferenceType())) {
|
| - |
|
1027 |
continue;
|
| - |
|
1028 |
}
|
| 982 |
Cell dateCell = sheet.createRow(row).createCell(0);
|
1029 |
Cell dateCell = sheet.createRow(row).createCell(0);
|
| 983 |
dateCell.setCellValue(statementDetailModel.getOnDate());
|
1030 |
dateCell.setCellValue(statementDetailModel.getOnDate());
|
| 984 |
dateCell.setCellStyle(dateStyle);
|
1031 |
dateCell.setCellStyle(dateStyle);
|
| 985 |
//Transact Type
|
1032 |
//Transact Type
|
| 986 |
sheet.getRow(row).createCell(1).setCellValue("BILLING");
|
1033 |
sheet.getRow(row).createCell(1).setCellValue("BILLING");
|
| Line 998... |
Line 1045... |
| 998 |
//Running Balance
|
1045 |
//Running Balance
|
| 999 |
currentOpening -= statementDetailModel.getAmount();
|
1046 |
currentOpening -= statementDetailModel.getAmount();
|
| 1000 |
sheet.getRow(row).createCell(5).setCellValue(currentOpening);
|
1047 |
sheet.getRow(row).createCell(5).setCellValue(currentOpening);
|
| 1001 |
|
1048 |
|
| 1002 |
|
1049 |
|
| 1003 |
//Narration
|
1050 |
//Category (Narration)
|
| 1004 |
sheet.getRow(row).createCell(6).setCellValue(statementDetailModel.getReferenceType());
|
1051 |
sheet.getRow(row).createCell(6).setCellValue(statementCategory(statementDetailModel.getReferenceType()) + " (" + statementDetailModel.getReferenceType() + ")");
|
| 1005 |
|
1052 |
|
| 1006 |
row += 1;
|
1053 |
row += 1;
|
| 1007 |
}
|
1054 |
}
|
| 1008 |
}
|
1055 |
}
|
| - |
|
1056 |
// Individual returns (returnorderinfo): one credit line per return, against its invoice, on refundedAt.
|
| - |
|
1057 |
List<StatementDetailModel> dateReturns = dateReturnMap.get(date);
|
| - |
|
1058 |
if (dateReturns != null) {
|
| - |
|
1059 |
for (StatementDetailModel ret : dateReturns) {
|
| - |
|
1060 |
Cell dateCell = sheet.createRow(row).createCell(0);
|
| - |
|
1061 |
dateCell.setCellValue(ret.getOnDate());
|
| - |
|
1062 |
dateCell.setCellStyle(dateStyle);
|
| - |
|
1063 |
sheet.getRow(row).createCell(1).setCellValue("RETURN");
|
| - |
|
1064 |
sheet.getRow(row).createCell(2).setCellValue(ret.getInvoiceNumber());
|
| - |
|
1065 |
sheet.getRow(row).createCell(3).setCellValue(0);
|
| - |
|
1066 |
sheet.getRow(row).createCell(4).setCellValue(ret.getAmount());
|
| - |
|
1067 |
grandTotalCredit += ret.getAmount();
|
| - |
|
1068 |
currentOpening += ret.getAmount();
|
| - |
|
1069 |
sheet.getRow(row).createCell(5).setCellValue(currentOpening);
|
| - |
|
1070 |
sheet.getRow(row).createCell(6).setCellValue("Return (Against Invoice " + ret.getInvoiceNumber() + ")");
|
| - |
|
1071 |
row += 1;
|
| - |
|
1072 |
}
|
| - |
|
1073 |
}
|
| - |
|
1074 |
// Month-end credit notes (shown before the interest line): all CN types EXCEPT RETURNS (returns come from
|
| - |
|
1075 |
// returnorderinfo via the billing query). MARGINS = scheme/margin credit; CN_CANCELLATION = debit (reverses a
|
| - |
|
1076 |
// MARGINS CN). Any CN→raw-scheme or cross-period timing difference lands in the reconciling diff line below.
|
| 1009 |
if (YearMonth.from(date).atEndOfMonth().equals(date)) {
|
1077 |
if (YearMonth.from(date).atEndOfMonth().equals(date)) {
|
| 1010 |
List<CreditNote> creditNotes = creditNoteRepository.selectAll(customRetailer.getPartnerId(), YearMonth.from(date));
|
1078 |
List<CreditNote> creditNotes = creditNoteRepository.selectAll(customRetailer.getPartnerId(), YearMonth.from(date));
|
| 1011 |
if (creditNotes != null) {
|
1079 |
if (creditNotes != null) {
|
| 1012 |
for (CreditNote creditNote : creditNotes) {
|
1080 |
for (CreditNote creditNote : creditNotes) {
|
| - |
|
1081 |
// RETURNS are sourced from returnorderinfo (billing query), not from the CN; skip them here.
|
| - |
|
1082 |
if (creditNote.getType() == CreditNoteType.RETURNS) {
|
| - |
|
1083 |
continue;
|
| - |
|
1084 |
}
|
| 1013 |
double cnAmount = creditNoteLineRepository.selectAllByCreditNote(creditNote.getId()).stream().collect(Collectors.summingDouble(x -> x.getAmount()));
|
1085 |
double cnAmount = creditNoteLineRepository.selectAllByCreditNote(creditNote.getId()).stream().collect(Collectors.summingDouble(x -> x.getAmount()));
|
| - |
|
1086 |
// CN_CANCELLATION reverses a previously-issued MARGINS credit note; line amount is stored positive but must debit.
|
| - |
|
1087 |
if (creditNote.getType() == CreditNoteType.CN_CANCELLATION) {
|
| - |
|
1088 |
cnAmount = -cnAmount;
|
| - |
|
1089 |
}
|
| 1014 |
Cell dateCell = sheet.createRow(row).createCell(0);
|
1090 |
Cell dateCell = sheet.createRow(row).createCell(0);
|
| 1015 |
dateCell.setCellValue(new Date(date.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()));
|
1091 |
dateCell.setCellValue(new Date(date.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()));
|
| 1016 |
dateCell.setCellStyle(dateStyle);
|
1092 |
dateCell.setCellStyle(dateStyle);
|
| - |
|
1093 |
// Net -ve (e.g. negative net margin, or a cancellation) is a debit note.
|
| 1017 |
sheet.getRow(row).createCell(1).setCellValue("CREDIT NOTE");
|
1094 |
sheet.getRow(row).createCell(1).setCellValue(cnAmount >= 0 ? "CREDIT NOTE" : "DEBIT NOTE");
|
| 1018 |
sheet.getRow(row).createCell(2).setCellValue(creditNote.getCreditNoteNumber());
|
1095 |
sheet.getRow(row).createCell(2).setCellValue(creditNote.getCreditNoteNumber());
|
| 1019 |
if (cnAmount > 0) {
|
1096 |
if (cnAmount > 0) {
|
| 1020 |
sheet.getRow(row).createCell(3).setCellValue(0);
|
1097 |
sheet.getRow(row).createCell(3).setCellValue(0);
|
| 1021 |
sheet.getRow(row).createCell(4).setCellValue(cnAmount);
|
1098 |
sheet.getRow(row).createCell(4).setCellValue(cnAmount);
|
| 1022 |
grandTotalCredit += cnAmount;
|
1099 |
grandTotalCredit += cnAmount;
|
| 1023 |
} else {
|
1100 |
} else {
|
| 1024 |
sheet.getRow(row).createCell(3).setCellValue(-cnAmount);
|
1101 |
sheet.getRow(row).createCell(3).setCellValue(-cnAmount);
|
| 1025 |
sheet.getRow(row).createCell(4).setCellValue(0);
|
1102 |
sheet.getRow(row).createCell(4).setCellValue(0);
|
| 1026 |
grandTotalDebit += -cnAmount;
|
1103 |
grandTotalDebit += -cnAmount;
|
| 1027 |
}
|
1104 |
}
|
| 1028 |
//Running balance
|
- |
|
| 1029 |
currentOpening += cnAmount;
|
1105 |
currentOpening += cnAmount;
|
| 1030 |
sheet.getRow(row).createCell(5).setCellValue(currentOpening);
|
1106 |
sheet.getRow(row).createCell(5).setCellValue(currentOpening);
|
| 1031 |
//Narration
|
1107 |
sheet.getRow(row).createCell(6).setCellValue(creditNote.getType() == CreditNoteType.CN_CANCELLATION
|
| 1032 |
sheet.getRow(row).createCell(6).setCellValue("Credit Note Issued");
|
1108 |
? "Margin Cancellation" : "Scheme / Margin");
|
| 1033 |
|
- |
|
| 1034 |
row += 1;
|
1109 |
row += 1;
|
| 1035 |
}
|
1110 |
}
|
| 1036 |
}
|
1111 |
}
|
| 1037 |
}
|
1112 |
}
|
| 1038 |
}
|
1113 |
}
|
| 1039 |
|
1114 |
|
| - |
|
1115 |
// --- Reconciling lines at period end ---
|
| - |
|
1116 |
// Interest accrued (charged, non-cash) is the only standing-moving loan piece. Principal movement and interest
|
| - |
|
1117 |
// PAID are funded by wallet cash (the excluded CREDIT_LIMIT/CREDIT_UTILIZED legs) and net to ~0, so they are not
|
| - |
|
1118 |
// shown as balance lines. Accrued interest is a debit (the partner's liability grows).
|
| - |
|
1119 |
if (Math.abs(interestAccruedCost) > 0.01f) {
|
| - |
|
1120 |
Cell dateCell = sheet.createRow(row).createCell(0);
|
| - |
|
1121 |
dateCell.setCellValue(new Date(endLocalDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()));
|
| - |
|
1122 |
dateCell.setCellStyle(dateStyle);
|
| - |
|
1123 |
sheet.getRow(row).createCell(1).setCellValue("INTEREST ACCRUED");
|
| - |
|
1124 |
sheet.getRow(row).createCell(2).setCellValue("");
|
| - |
|
1125 |
sheet.getRow(row).createCell(3).setCellValue(interestAccruedCost);
|
| - |
|
1126 |
sheet.getRow(row).createCell(4).setCellValue(0);
|
| - |
|
1127 |
grandTotalDebit += (long) interestAccruedCost;
|
| - |
|
1128 |
currentOpening -= interestAccruedCost;
|
| - |
|
1129 |
sheet.getRow(row).createCell(5).setCellValue(currentOpening);
|
| - |
|
1130 |
sheet.getRow(row).createCell(6).setCellValue("SD Credit — Interest accrued (financing cost)");
|
| - |
|
1131 |
row++;
|
| - |
|
1132 |
}
|
| - |
|
1133 |
// Pending-indent + floating-diff line: lands the running balance exactly on the formula closing. For a clean
|
| - |
|
1134 |
// monthly statement this is ~float; it also absorbs legitimate cross-period residuals (scheme→CN timing, a
|
| - |
|
1135 |
// CN_CANCELLATION reversing a prior month, a return whose sale was billed earlier).
|
| - |
|
1136 |
double pendingIndentLine = closingBalance - currentOpening;
|
| - |
|
1137 |
if (Math.abs(pendingIndentLine) > 0.01) {
|
| - |
|
1138 |
Cell dateCell = sheet.createRow(row).createCell(0);
|
| - |
|
1139 |
dateCell.setCellValue(new Date(endLocalDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()));
|
| - |
|
1140 |
dateCell.setCellStyle(dateStyle);
|
| - |
|
1141 |
sheet.getRow(row).createCell(1).setCellValue("NET PENDING INDENT / DIFF");
|
| - |
|
1142 |
sheet.getRow(row).createCell(2).setCellValue("");
|
| - |
|
1143 |
if (pendingIndentLine > 0) {
|
| - |
|
1144 |
sheet.getRow(row).createCell(3).setCellValue(0);
|
| - |
|
1145 |
sheet.getRow(row).createCell(4).setCellValue(pendingIndentLine);
|
| - |
|
1146 |
grandTotalCredit += (long) pendingIndentLine;
|
| - |
|
1147 |
} else {
|
| - |
|
1148 |
sheet.getRow(row).createCell(3).setCellValue(-pendingIndentLine);
|
| - |
|
1149 |
sheet.getRow(row).createCell(4).setCellValue(0);
|
| - |
|
1150 |
grandTotalDebit += (long) -pendingIndentLine;
|
| - |
|
1151 |
}
|
| - |
|
1152 |
currentOpening += pendingIndentLine;
|
| - |
|
1153 |
sheet.getRow(row).createCell(5).setCellValue(currentOpening);
|
| - |
|
1154 |
sheet.getRow(row).createCell(6).setCellValue("Net Pending Indent + reconciling diff (cross-period / timing / float)");
|
| - |
|
1155 |
row++;
|
| - |
|
1156 |
}
|
| - |
|
1157 |
|
| 1040 |
sheet.createRow(row).createCell(2).setCellValue("Grand Total");
|
1158 |
sheet.createRow(row).createCell(2).setCellValue("Grand Total");
|
| 1041 |
sheet.getRow(row).createCell(3).setCellValue(grandTotalDebit);
|
1159 |
sheet.getRow(row).createCell(3).setCellValue(grandTotalDebit);
|
| 1042 |
sheet.getRow(row).createCell(4).setCellValue(grandTotalCredit);
|
1160 |
sheet.getRow(row).createCell(4).setCellValue(grandTotalCredit);
|
| 1043 |
/*row += 2;
|
1161 |
row += 2;
|
| 1044 |
sheet.createRow(row).createCell(0).setCellValue("Closing Balance");
|
1162 |
sheet.createRow(row).createCell(0).setCellValue("Closing Balance");
|
| 1045 |
sheet.getRow(row).createCell(3).setCellValue(closingBalance);*/
|
1163 |
sheet.getRow(row).createCell(5).setCellValue(closingBalance);
|
| 1046 |
row++;
|
1164 |
row++;
|
| - |
|
1165 |
double diff = Math.abs(currentOpening - closingBalance);
|
| 1047 |
/*
|
1166 |
if (diff > 1) {
|
| 1048 |
* sheet.createRow(row).createCell(0).setCellValue("Pending Grns");
|
1167 |
LOGGER.warn("Account statement reconciliation mismatch for {}: computed={}, expected={}, diff={}",
|
| 1049 |
* sheet.getRow(row).createCell(2).setCellValue(closingBalance); row++;
|
1168 |
customRetailer.getPartnerId(), currentOpening, closingBalance, diff);
|
| 1050 |
*/
|
1169 |
}
|
| 1051 |
try {
|
1170 |
try {
|
| 1052 |
workbook.write(bos);
|
1171 |
workbook.write(bos);
|
| 1053 |
} finally {
|
1172 |
} finally {
|
| 1054 |
workbook.close();
|
1173 |
workbook.close();
|
| 1055 |
bos.close();
|
1174 |
bos.close();
|