From d15243fb31387d4eda4c2692dffb1ba491a78287 Mon Sep 17 00:00:00 2001 From: danielales2541 Date: Tue, 25 Mar 2025 17:50:34 +0100 Subject: [PATCH] FINERACT-2202: Bulk import fix --- .../client/ClientPersonImportHandler.java | 6 ++--- .../importhandler/loan/LoanImportHandler.java | 4 +-- .../savings/SavingsImportHandler.java | 6 ++--- .../populator/AbstractWorkbookPopulator.java | 3 ++- .../populator/loan/LoanWorkbookPopulator.java | 8 +++--- .../SavingsTransactionsWorkbookPopulator.java | 16 ++++++------ .../savings/SavingsWorkbookPopulator.java | 6 ++--- .../loanaccount/data/LoanAccountData.java | 25 ++++++++++--------- ...SavingsAccountReadPlatformServiceImpl.java | 7 +++--- 9 files changed, 41 insertions(+), 40 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/client/ClientPersonImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/client/ClientPersonImportHandler.java index 8e23a9ff5..2e6ddce85 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/client/ClientPersonImportHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/client/ClientPersonImportHandler.java @@ -62,7 +62,7 @@ public class ClientPersonImportHandler implements ImportHandler { public Count process(final Workbook workbook, final String locale, final String dateFormat) { List clients = readExcelFile(workbook, locale, dateFormat); - return importEntity(workbook, clients, dateFormat); + return importEntity(workbook, clients, dateFormat, locale); } public List readExcelFile(final Workbook workbook, final String locale, final String dateFormat) { @@ -183,13 +183,13 @@ public class ClientPersonImportHandler implements ImportHandler { } - public Count importEntity(final Workbook workbook, final List clients, final String dateFormat) { + public Count importEntity(final Workbook workbook, final List clients, final String dateFormat, String locale) { Sheet clientSheet = workbook.getSheet(TemplatePopulateImportConstants.CLIENT_PERSON_SHEET_NAME); int successCount = 0; int errorCount = 0; String errorMessage; GsonBuilder gsonBuilder = GoogleGsonSerializerHelper.createGsonBuilder(); - gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat)); + gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat, locale)); for (ClientData client : clients) { try { String payload = gsonBuilder.create().toJson(client); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java index b1bc4315f..a061ce97d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java @@ -124,7 +124,6 @@ public class LoanImportHandler implements ImportHandler { if (ImportHandlerUtils.readAsLong(LoanConstants.LINK_ACCOUNT_ID, row) != null) { linkAccountId = Objects.requireNonNull(ImportHandlerUtils.readAsLong(LoanConstants.LINK_ACCOUNT_ID, row)).toString(); } - if (disbursedDate != null) { return DisbursementData.importInstance(disbursedDate, linkAccountId, row.getRowNum(), locale, dateFormat); } @@ -238,7 +237,6 @@ public class LoanImportHandler implements ImportHandler { String loanRepaymentScheduleTransactionProcessorStrategy = ImportHandlerUtils.readAsString(LoanConstants.REPAYMENT_STRATEGY_COL, row); - LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loanRepaymentScheduleTransactionProcessorFactory .determineProcessor(loanRepaymentScheduleTransactionProcessorStrategy); @@ -366,7 +364,7 @@ public class LoanImportHandler implements ImportHandler { .getIdByName(workbook.getSheet(TemplatePopulateImportConstants.GROUP_SHEET_NAME), clientOrGroupName); return LoanAccountData.importInstanceGroup(loanTypeEnumOption, groupIdforGroupLoan, productId, loanOfficerId, submittedOnDate, fundId, principal, numberOfRepayments, repaidEvery, repaidEveryFrequencyEnums, loanTerm, - loanTermFrequencyEnum, nominalInterestRate, amortizationEnumOption, interestMethodEnum, + loanTermFrequencyEnum, nominalInterestRate, submittedOnDate, amortizationEnumOption, interestMethodEnum, interestCalculationPeriodEnum, arrearsTolerance, repaymentStrategyCode, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, firstRepaymentOnDate, row.getRowNum(), externalId, linkAccountId, locale, dateFormat, null); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/savings/SavingsImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/savings/SavingsImportHandler.java index 42d16b395..d3cc0b5d3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/savings/SavingsImportHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/savings/SavingsImportHandler.java @@ -349,7 +349,7 @@ public class SavingsImportHandler implements ImportHandler { final String dateFormat) { if (activationDates.get(i) != null) { GsonBuilder gsonBuilder = GoogleGsonSerializerHelper.createGsonBuilder(); - gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat)); + gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat, activationDates.get(i).getLocale())); String payload = gsonBuilder.create().toJson(activationDates.get(i)); final CommandWrapper commandRequest = new CommandWrapperBuilder() // .savingsAccountActivation(savingsId)// @@ -364,7 +364,7 @@ public class SavingsImportHandler implements ImportHandler { final String dateFormat) { if (approvalDates.get(i) != null) { GsonBuilder gsonBuilder = GoogleGsonSerializerHelper.createGsonBuilder(); - gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat)); + gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat, approvalDates.get(i).getLocale())); String payload = gsonBuilder.create().toJson(approvalDates.get(i)); final CommandWrapper commandRequest = new CommandWrapperBuilder() // .approveSavingsAccountApplication(savingsId)// @@ -377,7 +377,7 @@ public class SavingsImportHandler implements ImportHandler { private CommandProcessingResult importSavings(final List savings, final int i, final String dateFormat) { GsonBuilder gsonBuilder = GoogleGsonSerializerHelper.createGsonBuilder(); - gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat)); + gsonBuilder.registerTypeAdapter(LocalDate.class, new DateSerializer(dateFormat, savings.get(i).getLocale())); gsonBuilder.registerTypeAdapter(EnumOptionData.class, new EnumOptionDataIdSerializer()); JsonObject savingsJsonob = gsonBuilder.create().toJsonTree(savings.get(i)).getAsJsonObject(); savingsJsonob.remove("isDormancyTrackingActive"); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/AbstractWorkbookPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/AbstractWorkbookPopulator.java index 8204feaad..8f7779b32 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/AbstractWorkbookPopulator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/AbstractWorkbookPopulator.java @@ -115,6 +115,7 @@ public abstract class AbstractWorkbookPopulator implements WorkbookPopulator { dateCellStyle.setDataFormat(df); int rowIndex = 0; DateTimeFormatter outputFormat = new DateTimeFormatterBuilder().appendPattern(dateFormat).toFormatter(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat); try { if (clients != null) { for (ClientData client : clients) { @@ -125,7 +126,7 @@ public abstract class AbstractWorkbookPopulator implements WorkbookPopulator { writeString(nameCol, row, client.getDisplayName().replaceAll("[ )(] ", "_") + "(" + client.getId() + ")"); if (client.getActivationDate() != null) { - writeDate(activationDateCol, row, outputFormat.format(client.getActivationDate()), dateCellStyle, dateFormat); + writeDate(activationDateCol, row, client.getActivationDate().format(formatter), dateCellStyle, dateFormat); } if (containsClientExtId) { if (!client.getExternalId().isEmpty()) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/loan/LoanWorkbookPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/loan/LoanWorkbookPopulator.java index a1257504d..540d37f87 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/loan/LoanWorkbookPopulator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/loan/LoanWorkbookPopulator.java @@ -166,10 +166,10 @@ public class LoanWorkbookPopulator extends AbstractWorkbookPopulator { .createFormulaListConstraint("INDIRECT(CONCATENATE(\"Staff_\",$A1))"); DataValidationConstraint submittedDateConstraint = validationHelper.createDateConstraint( DataValidationConstraint.OperatorType.BETWEEN, - "=IF(INDIRECT(CONCATENATE(\"START_DATE_\",$E1))>VLOOKUP($C1,$AR$2:$AT$" - + (clientSheetPopulator.getClientsSize() + groupSheetPopulator.getGroupsSize() + 1) - + ",3,FALSE),INDIRECT(CONCATENATE(\"START_DATE_\",$E1)),VLOOKUP($C1,$AR$2:$AT$" - + (clientSheetPopulator.getClientsSize() + groupSheetPopulator.getGroupsSize() + 1) + ",3,FALSE))", + "=IF(" + "DATEVALUE(INDIRECT(\"START_DATE_\" & $E1)) > DATEVALUE(VLOOKUP($C1, $AR$2:$AT$" + + (clientSheetPopulator.getClientsSize() + groupSheetPopulator.getGroupsSize() + 1) + ", 3, FALSE)), " + + "DATEVALUE(INDIRECT(\"START_DATE_\" & $E1)), " + "DATEVALUE(VLOOKUP($C1, $AR$2:$AT$" + + (clientSheetPopulator.getClientsSize() + groupSheetPopulator.getGroupsSize() + 1) + ", 3, FALSE)))", "=TODAY()", dateFormat); DataValidationConstraint approvalDateConstraint = validationHelper .createDateConstraint(DataValidationConstraint.OperatorType.BETWEEN, "=$G1", "=TODAY()", dateFormat); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/savings/SavingsTransactionsWorkbookPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/savings/SavingsTransactionsWorkbookPopulator.java index cec61a94f..ce47a7ac5 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/savings/SavingsTransactionsWorkbookPopulator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/savings/SavingsTransactionsWorkbookPopulator.java @@ -112,8 +112,8 @@ public class SavingsTransactionsWorkbookPopulator extends AbstractWorkbookPopula .createExplicitListConstraint(new String[] { "Withdrawal", "Deposit" }); DataValidationConstraint paymentTypeConstraint = validationHelper.createFormulaListConstraint("PaymentTypes"); DataValidationConstraint transactionDateConstraint = validationHelper.createDateConstraint( - DataValidationConstraint.OperatorType.BETWEEN, "=VLOOKUP($C1,$Q$2:$T$" + (savingsAccounts.size() + 1) + ",4,FALSE)", - "=TODAY()", dateFormat); + DataValidationConstraint.OperatorType.BETWEEN, + "=DATEVALUE(VLOOKUP($C1,$Q$2:$T$" + (savingsAccounts.size() + 1) + ",4,FALSE))", "=TODAY()", dateFormat); DataValidation officeValidation = validationHelper.createValidation(officeNameConstraint, officeNameRange); DataValidation clientValidation = validationHelper.createValidation(clientNameConstraint, clientNameRange); @@ -208,11 +208,13 @@ public class SavingsTransactionsWorkbookPopulator extends AbstractWorkbookPopula if (savingsAccount.getMinRequiredOpeningBalance() != null) { writeBigDecimal(TransactionConstants.LOOKUP_OPENING_BALANCE_COL, row, savingsAccount.getMinRequiredOpeningBalance()); } - writeDate(TransactionConstants.LOOKUP_SAVINGS_ACTIVATION_DATE_COL, row, - "" + savingsAccount.getTimeline().getActivatedOnDate().getDayOfMonth() + "/" - + savingsAccount.getTimeline().getActivatedOnDate().getMonthValue() + "/" - + savingsAccount.getTimeline().getActivatedOnDate().getYear(), - dateCellStyle, dateFormat); + if (savingsAccount.getActivatedOnDate() != null) { + writeDate(TransactionConstants.LOOKUP_SAVINGS_ACTIVATION_DATE_COL, row, + "" + savingsAccount.getTimeline().getActivatedOnDate().getDayOfMonth() + "/" + + savingsAccount.getTimeline().getActivatedOnDate().getMonthValue() + "/" + + savingsAccount.getTimeline().getActivatedOnDate().getYear(), + dateCellStyle, dateFormat); + } } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/savings/SavingsWorkbookPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/savings/SavingsWorkbookPopulator.java index 791728c99..ac7c1570d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/savings/SavingsWorkbookPopulator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/savings/SavingsWorkbookPopulator.java @@ -131,7 +131,7 @@ public class SavingsWorkbookPopulator extends AbstractWorkbookPopulator { writeString(SavingsConstants.INTEREST_CALCULATION_COL, rowHeader, "Interest Calculated*"); writeString(SavingsConstants.INTEREST_CALCULATION_DAYS_IN_YEAR_COL, rowHeader, "# Days in Year*"); writeString(SavingsConstants.MIN_OPENING_BALANCE_COL, rowHeader, "Min Opening Balance"); - writeString(SavingsConstants.LOCKIN_PERIOD_COL, rowHeader, "Locked In For"); + writeString(SavingsConstants.LOCKIN_PERIOD_COL, rowHeader, "Locked In For*"); writeString(SavingsConstants.APPLY_WITHDRAWAL_FEE_FOR_TRANSFERS, rowHeader, "Apply Withdrawal Fee For Transfers"); writeString(SavingsConstants.LOOKUP_CLIENT_NAME_COL, rowHeader, "Client Name"); @@ -234,8 +234,8 @@ public class SavingsWorkbookPopulator extends AbstractWorkbookPopulator { DataValidationConstraint fieldOfficerNameConstraint = validationHelper .createFormulaListConstraint("INDIRECT(CONCATENATE(\"Staff_\",$A1))"); DataValidationConstraint submittedDateConstraint = validationHelper.createDateConstraint( - DataValidationConstraint.OperatorType.BETWEEN, - "=VLOOKUP($C1,$AF$2:$AG$" + (clientSheetPopulator.getClientsSize() + groupSheetPopulator.getGroupsSize() + 1) + ",2,FALSE)", + DataValidationConstraint.OperatorType.BETWEEN, "=DATEVALUE(VLOOKUP($C1,$AF$2:$AG$" + + (clientSheetPopulator.getClientsSize() + groupSheetPopulator.getGroupsSize() + 1) + ",2,FALSE))", "=TODAY()", dateFormat); DataValidationConstraint approvalDateConstraint = validationHelper .createDateConstraint(DataValidationConstraint.OperatorType.BETWEEN, "=$F1", "=TODAY()", dateFormat); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java index 825293fdb..4376cf077 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java @@ -310,24 +310,25 @@ public class LoanAccountData { public static LoanAccountData importInstanceGroup(EnumOptionData loanTypeEnumOption, Long groupIdforGroupLoan, Long productId, Long loanOfficerId, LocalDate submittedOnDate, Long fundId, BigDecimal principal, Integer numberOfRepayments, Integer repaidEvery, EnumOptionData repaidEveryFrequencyEnums, Integer loanTermFrequency, - EnumOptionData loanTermFrequencyTypeEnum, BigDecimal nominalInterestRate, EnumOptionData amortizationEnumOption, - EnumOptionData interestMethodEnum, EnumOptionData interestCalculationPeriodEnum, BigDecimal arrearsTolerance, - String transactionProcessingStrategyCode, Integer graceOnPrincipalPayment, Integer graceOnInterestPayment, - Integer graceOnInterestCharged, LocalDate interestChargedFromDate, LocalDate repaymentsStartingFromDate, Integer rowIndex, - ExternalId externalId, String linkAccountId, String locale, String dateFormat, Integer fixedLength) { + EnumOptionData loanTermFrequencyTypeEnum, BigDecimal nominalInterestRate, LocalDate expectedDisbursementDate, + EnumOptionData amortizationEnumOption, EnumOptionData interestMethodEnum, EnumOptionData interestCalculationPeriodEnum, + BigDecimal arrearsTolerance, String transactionProcessingStrategyCode, Integer graceOnPrincipalPayment, + Integer graceOnInterestPayment, Integer graceOnInterestCharged, LocalDate interestChargedFromDate, + LocalDate repaymentsStartingFromDate, Integer rowIndex, ExternalId externalId, String linkAccountId, String locale, + String dateFormat, Integer fixedLength) { return new LoanAccountData().setLoanType(loanTypeEnumOption).setGroupId(groupIdforGroupLoan).setProductId(productId) .setLoanOfficerId(loanOfficerId).setSubmittedOnDate(submittedOnDate).setFundId(fundId).setPrincipal(principal) .setNumberOfRepayments(numberOfRepayments).setRepaymentEvery(repaidEvery) .setRepaymentFrequencyType(repaidEveryFrequencyEnums).setLoanTermFrequency(loanTermFrequency) .setLoanTermFrequencyType(loanTermFrequencyTypeEnum).setInterestRatePerPeriod(nominalInterestRate) - .setAmortizationTypeOptions(List.of(amortizationEnumOption)).setInterestType(interestMethodEnum) - .setInterestCalculationPeriodType(interestCalculationPeriodEnum).setInArrearsTolerance(arrearsTolerance) - .setTransactionProcessingStrategyCode(transactionProcessingStrategyCode).setGraceOnPrincipalPayment(graceOnPrincipalPayment) - .setGraceOnInterestPayment(graceOnInterestPayment).setGraceOnInterestCharged(graceOnInterestCharged) - .setInterestChargedFromDate(interestChargedFromDate).setRepaymentsStartingFromDate(repaymentsStartingFromDate) - .setRowIndex(rowIndex).setExternalId(externalId).setLinkAccountId(linkAccountId).setLocale(locale).setDateFormat(dateFormat) - .setFixedLength(fixedLength); + .setAmortizationType(amortizationEnumOption).setInterestType(interestMethodEnum) + .setExpectedDisbursementDate(expectedDisbursementDate).setInterestCalculationPeriodType(interestCalculationPeriodEnum) + .setInArrearsTolerance(arrearsTolerance).setTransactionProcessingStrategyCode(transactionProcessingStrategyCode) + .setGraceOnPrincipalPayment(graceOnPrincipalPayment).setGraceOnInterestPayment(graceOnInterestPayment) + .setGraceOnInterestCharged(graceOnInterestCharged).setInterestChargedFromDate(interestChargedFromDate) + .setRepaymentsStartingFromDate(repaymentsStartingFromDate).setRowIndex(rowIndex).setExternalId(externalId) + .setLinkAccountId(linkAccountId).setLocale(locale).setDateFormat(dateFormat).setFixedLength(fixedLength); } public LoanAccountData withClientData(final ClientData clientData) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java index 22a9298d1..f84962aff 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java @@ -164,7 +164,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead sqlBuilder.append(" join m_office o on o.id = c.office_id"); sqlBuilder.append(" where o.hierarchy like ?"); - final Object[] objectArray = new Object[2]; + final Object[] objectArray = new Object[3]; objectArray[0] = hierarchySearchString; int arrayPos = 1; if (searchParameters != null) { @@ -181,9 +181,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead arrayPos = arrayPos + 1; } if (searchParameters.getOfficeId() != null) { - sqlBuilder.append("and c.office_id =?"); - objectArray[arrayPos] = searchParameters.getOfficeId(); - arrayPos = arrayPos + 1; + sqlBuilder.append(" and c.office_id = ?"); + objectArray[arrayPos++] = searchParameters.getOfficeId(); } if (searchParameters.hasOrderBy()) { sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());