From 3d3e8c408378ec42ce2ca47a8a0c7b288510fda6 Mon Sep 17 00:00:00 2001 From: Jose Hernandez Date: Tue, 12 Apr 2022 17:23:21 -0500 Subject: [PATCH] Fixes integration tests FINERACT-1557: Fixes for integration tests FINERACT-1557: Fixes for integration tests Fixes integration tests --- .../GLAccountReadPlatformServiceImpl.java | 24 ++--- .../core/service/DateUtils.java | 26 +++++- .../DatabaseSpecificSQLGenerator.java | 10 +++ .../dataqueries/api/DataTableApiConstant.java | 21 +++++ .../ReadWriteNonCoreDataServiceImpl.java | 68 ++++++++++---- .../service/StaffReadPlatformServiceImpl.java | 2 +- .../account/data/PortfolioAccountDTO.java | 4 + ...rtfolioAccountReadPlatformServiceImpl.java | 11 +-- .../loanaccount/api/LoansApiResource.java | 83 ++++++++++------- .../loanaccount/data/CollectionData.java | 90 +++++++++++++++++++ .../loanaccount/data/LoanAccountData.java | 51 ++++++----- .../service/LoanReadPlatformService.java | 2 + .../service/LoanReadPlatformServiceImpl.java | 55 ++++++++++++ .../src/main/resources/logback-spring.xml | 2 +- .../src/test/resources/logback.xml | 2 +- .../ClientLoanIntegrationTest.java | 27 +++--- .../ClientSavingsIntegrationTest.java | 10 +-- .../DisbursalAndRepaymentScheduleTest.java | 3 +- ...oanDisbursementDetailsIntegrationTest.java | 3 +- .../LoanReschedulingWithinCenterTest.java | 7 +- .../RepaymentWithPostDatedChecksTest.java | 5 +- .../SchedulerJobsTestResults.java | 20 +++-- .../client/ClientEntityImportHandlerTest.java | 3 +- .../loan/LoanImportHandlerTest.java | 3 +- .../office/OfficeImportHandlerTest.java | 3 +- .../savings/SavingsImportHandlerTest.java | 3 +- .../common/ClientChargesTest.java | 3 +- .../common/ProvisioningIntegrationTest.java | 3 +- .../common/loans/LoanTransactionHelper.java | 10 ++- .../provisioning/ProvisioningHelper.java | 7 +- .../shares/ShareAccountIntegrationTests.java | 12 +-- .../common/shares/ShareProductHelper.java | 3 +- ...bleInstallmentsDecliningBalanceHelper.java | 3 +- .../VariableInstallmentsFlatHelper.java | 3 +- 34 files changed, 425 insertions(+), 157 deletions(-) create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/CollectionData.java diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/service/GLAccountReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/service/GLAccountReadPlatformServiceImpl.java index d6382454a..8b471a723 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/service/GLAccountReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/glaccount/service/GLAccountReadPlatformServiceImpl.java @@ -131,7 +131,7 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe + "group by t2.account_id desc) t1)"; } } - final Object[] paramaterArray = new Object[3]; + final Object[] parameterArray = new Object[3]; int arrayPos = 0; boolean filtersPresent = false; if ((accountClassification != null) || StringUtils.isNotBlank(searchParam) || (usage != null) || (manualTransactionsAllowed != null) @@ -143,8 +143,8 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe if (filtersPresent) { boolean firstWhereConditionAdded = false; if (accountClassification != null) { - sql += " classification_enum like ?"; - paramaterArray[arrayPos] = accountClassification; + sql += " classification_enum = ?"; + parameterArray[arrayPos] = accountClassification.shortValue(); arrayPos = arrayPos + 1; firstWhereConditionAdded = true; } @@ -153,9 +153,9 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe sql += " and "; } sql += " ( name like %?% or gl_code like %?% )"; - paramaterArray[arrayPos] = searchParam; + parameterArray[arrayPos] = searchParam; arrayPos = arrayPos + 1; - paramaterArray[arrayPos] = searchParam; + parameterArray[arrayPos] = searchParam; arrayPos = arrayPos + 1; firstWhereConditionAdded = true; } @@ -175,11 +175,7 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe sql += " and "; } - if (manualTransactionsAllowed) { - sql += " manual_journal_entries_allowed = 1"; - } else { - sql += " manual_journal_entries_allowed = 0"; - } + sql += " manual_journal_entries_allowed = " + manualTransactionsAllowed; firstWhereConditionAdded = true; } if (disabled != null) { @@ -187,18 +183,14 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe sql += " and "; } - if (disabled) { - sql += " disabled = 1"; - } else { - sql += " disabled = 0"; - } + sql += " disabled = " + disabled; firstWhereConditionAdded = true; } } sql += " ORDER BY gl_code ASC"; - final Object[] finalObjectArray = Arrays.copyOf(paramaterArray, arrayPos); + final Object[] finalObjectArray = Arrays.copyOf(parameterArray, arrayPos); return this.jdbcTemplate.query(sql, rm, finalObjectArray); // NOSONAR } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java index bd08a6c76..93e48d63f 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java @@ -27,6 +27,7 @@ import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.ArrayList; +import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.TimeZone; @@ -40,6 +41,10 @@ public final class DateUtils { } + public static ZoneId getSystemZoneId() { + return ZoneId.systemDefault(); + } + public static ZoneId getDateTimeZoneOfTenant() { final FineractPlatformTenant tenant = ThreadLocalContextUtil.getTenant(); ZoneId zone = ZoneId.systemDefault(); @@ -59,13 +64,28 @@ public final class DateUtils { } public static Date getDateOfTenant() { - return Date.from(getLocalDateOfTenant().atStartOfDay(getDateTimeZoneOfTenant()).toInstant()); + return convertLocalDateToDate(getLocalDateOfTenant()); + } + + public static Date convertLocalDateToDate(LocalDate localDate) { + return createDate(localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth()); + } + + public static Date createDate(int year, int month, int day) { + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.YEAR, year); + cal.set(Calendar.MONTH, month - 1); + cal.set(Calendar.DAY_OF_MONTH, day); + return cal.getTime(); } public static LocalDate getLocalDateOfTenant() { final ZoneId zone = getDateTimeZoneOfTenant(); - LocalDate today = LocalDate.now(zone); - return today; + return LocalDate.now(zone); + } + + public static LocalDate getLocalDateOfTenant(final ZoneId zone) { + return LocalDate.now(zone); } public static LocalDateTime getLocalDateTimeOfTenant() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/database/DatabaseSpecificSQLGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/database/DatabaseSpecificSQLGenerator.java index 9c3a20f84..707f7ef5c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/database/DatabaseSpecificSQLGenerator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/database/DatabaseSpecificSQLGenerator.java @@ -97,6 +97,16 @@ public class DatabaseSpecificSQLGenerator { } } + public String currentDateTime() { + if (databaseTypeResolver.isMySQL()) { + return "CURRENT_TIMESTAMP()"; + } else if (databaseTypeResolver.isPostgreSQL()) { + return "CURRENT_TIMESTAMP"; + } else { + throw new IllegalStateException("Database type is not supported for current date " + databaseTypeResolver.databaseType()); + } + } + public String subDate(String date, String multiplier, String unit) { if (databaseTypeResolver.isMySQL()) { return format("DATE_SUB(%s, INTERVAL %s %s)", date, multiplier, unit); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/api/DataTableApiConstant.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/api/DataTableApiConstant.java index 39e0b4be6..76ca161e1 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/api/DataTableApiConstant.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/api/DataTableApiConstant.java @@ -34,4 +34,25 @@ public final class DataTableApiConstant { public static final String localParamName = "locale"; public static final String DATATABLE_RESOURCE_NAME = "dataTables"; + public static final String CREATEDAT_FIELD_NAME = "created_at"; + public static final String UPDATEDAT_FIELD_NAME = "updated_at"; + + // Field Types + public static final String DATETIME_FIELD_TYPE = "DateTime"; + + // associationParameters + public static final String allAssociateParamName = "all"; + public static final String repaymentScheduleAssociateParamName = "repaymentSchedule"; + public static final String originalScheduleAssociateParamName = "originalSchedule"; + public static final String transactionsAssociateParamName = "transactions"; + public static final String chargesAssociateParamName = "charges"; + public static final String guarantorsAssociateParamName = "guarantors"; + public static final String collateralAssociateParamName = "collateral"; + public static final String notesAssociateParamName = "notes"; + public static final String linkedAccountAssociateParamName = "linkedAccount"; + public static final String multiDisburseDetailsAssociateParamName = "multiDisburseDetails"; + public static final String futureScheduleAssociateParamName = "futureSchedule"; + public static final String meetingAssociateParamName = "meeting"; + public static final String emiAmountVariationsAssociateParamName = "emiAmountVariations"; + public static final String collectionAssociateParamName = "collection"; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java index b2a4bb8f9..2582e0f79 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java @@ -329,6 +329,17 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ return category.equals(DataTableApiConstant.CATEGORY_PPI); } + private JsonElement addColumn(final String name, final String dataType, final boolean isMandatory, final Integer length) { + JsonObject column = new JsonObject(); + column.addProperty("name", name); + column.addProperty("type", dataType); + if (dataType.equalsIgnoreCase("string")) { + column.addProperty("length", length); + } + column.addProperty("mandatory", (isMandatory ? "true" : "false")); + return column; + } + @Override public String getDataTableName(String url) { @@ -491,7 +502,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ private void assertDataTableExists(final String datatableName) { final String sql = "select (CASE WHEN exists (select 1 from information_schema.tables where table_schema = " + sqlGenerator.currentSchema() + " and table_name = ?) THEN 'true' ELSE 'false' END)"; - final String dataTableExistsString = this.jdbcTemplate.queryForObject(sql, String.class, new Object[] { datatableName }); // NOSONAR + final String dataTableExistsString = this.jdbcTemplate.queryForObject(sql, String.class, new Object[] { datatableName }); final boolean dataTableExists = Boolean.valueOf(dataTableExistsString); if (!dataTableExists) { throw new PlatformDataIntegrityException("error.msg.invalid.datatable", "Invalid Data Table: " + datatableName, "name", @@ -559,7 +570,9 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ } else if (type.equalsIgnoreCase("Decimal")) { sqlBuilder = sqlBuilder.append("(19,6)"); } else if (type.equalsIgnoreCase("Dropdown")) { - sqlBuilder = sqlBuilder.append("(11)"); + if (databaseTypeResolver.isMySQL()) { + sqlBuilder = sqlBuilder.append("(11)"); + } } } @@ -613,12 +626,20 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ sqlBuilder = sqlBuilder.append("CREATE TABLE " + sqlGenerator.escape(datatableName) + " ("); if (multiRow) { - sqlBuilder = sqlBuilder.append("id BIGINT NOT NULL AUTO_INCREMENT, ") - .append(sqlGenerator.escape(fkColumnName) + " BIGINT NOT NULL, "); - } else { - sqlBuilder = sqlBuilder.append(sqlGenerator.escape(fkColumnName) + " BIGINT NOT NULL, "); + if (databaseTypeResolver.isMySQL()) { + sqlBuilder = sqlBuilder.append("id BIGINT NOT NULL AUTO_INCREMENT, "); + } else if (databaseTypeResolver.isPostgreSQL()) { + sqlBuilder = sqlBuilder.append( + "id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ), "); + } else { + throw new IllegalStateException("Current database is not supported"); + } } + sqlBuilder = sqlBuilder.append(sqlGenerator.escape(fkColumnName) + " BIGINT NOT NULL, "); + // Add Created At and Updated At + columns.add(addColumn(DataTableApiConstant.CREATEDAT_FIELD_NAME, DataTableApiConstant.DATETIME_FIELD_TYPE, false, null)); + columns.add(addColumn(DataTableApiConstant.UPDATEDAT_FIELD_NAME, DataTableApiConstant.DATETIME_FIELD_TYPE, false, null)); for (final JsonElement column : columns) { parseDatatableColumnObjectForCreate(column.getAsJsonObject(), sqlBuilder, constrainBuilder, dataTableNameAlias, codeMappings, isConstraintApproach); @@ -629,10 +650,12 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ String fullFkName = "fk_" + fkName; if (multiRow) { - sqlBuilder = sqlBuilder.append(", PRIMARY KEY (id)") - .append(", KEY " + sqlGenerator.escape("fk_" + apptableName.substring(2) + "_id") + " (" - + sqlGenerator.escape(fkColumnName) + ")") - .append(", CONSTRAINT " + sqlGenerator.escape(fullFkName) + " ") + sqlBuilder = sqlBuilder.append(", PRIMARY KEY (id)"); + if (databaseTypeResolver.isMySQL()) { + sqlBuilder = sqlBuilder.append(", KEY " + sqlGenerator.escape("fk_" + apptableName.substring(2) + "_id") + " (" + + sqlGenerator.escape(fkColumnName) + ")"); + } + sqlBuilder = sqlBuilder.append(", CONSTRAINT " + sqlGenerator.escape(fullFkName) + " ") .append("FOREIGN KEY (" + sqlGenerator.escape(fkColumnName) + ") ") .append("REFERENCES " + sqlGenerator.escape(actualAppTableName) + " (id)"); } else { @@ -647,6 +670,8 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ if (databaseTypeResolver.isMySQL()) { sqlBuilder.append(" ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4;"); } + LOG.debug("SQL:: {}", sqlBuilder.toString()); + this.jdbcTemplate.execute(sqlBuilder.toString()); registerDatatable(datatableName, apptableName, entitySubType); @@ -938,9 +963,9 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ final boolean isConstraintApproach = this.configurationDomainService.isConstraintApproachEnabledForDatatables(); if (!StringUtils.isBlank(entitySubType)) { - final String updateLegalFormSQL = "update x_registered_table SET entity_subtype='" + entitySubType + String updateLegalFormSQL = "update x_registered_table SET entity_subtype='" + entitySubType + "' WHERE registered_table_name = '" + datatableName + "'"; - this.jdbcTemplate.execute(updateLegalFormSQL); // NOSONAR + this.jdbcTemplate.execute(updateLegalFormSQL); } if (!StringUtils.isBlank(apptableName)) { @@ -1154,7 +1179,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ private int getRowCount(final String datatableName) { final String sql = "select count(*) from " + sqlGenerator.escape(datatableName); - return this.jdbcTemplate.queryForObject(sql, Integer.class); // NOSONAR + return this.jdbcTemplate.queryForObject(sql, Integer.class); } @Transactional @@ -1476,7 +1501,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ SQLInjectionValidator.validateSQLInput(datatable); final String sql = "SELECT application_table_name FROM x_registered_table where registered_table_name = ?"; - String applicationTableName; + String applicationTableName = ""; final SqlRowSet rowSet = jdbcTemplate.queryForRowSet(sql, new Object[] { datatable }); // NOSONAR if (rowSet.next()) { @@ -1524,6 +1549,13 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ columnName = sqlGenerator.escape(key); insertColumns += ", " + columnName; selectColumns += "," + pValueWrite + " as " + columnName; + } else { + if (key.equalsIgnoreCase(DataTableApiConstant.CREATEDAT_FIELD_NAME) + || key.equalsIgnoreCase(DataTableApiConstant.UPDATEDAT_FIELD_NAME)) { + columnName = sqlGenerator.escape(key); + insertColumns += ", " + columnName; + selectColumns += "," + sqlGenerator.currentDateTime() + " as " + columnName; + } } } @@ -1626,6 +1658,10 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ } } sql += sqlGenerator.escape(key) + " = " + pValueWrite; + } else { + if (key.equalsIgnoreCase(DataTableApiConstant.UPDATEDAT_FIELD_NAME)) { + sql += ", " + sqlGenerator.escape(key) + " = " + sqlGenerator.currentDateTime(); + } } } @@ -1879,8 +1915,8 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ public Long countDatatableEntries(final String datatableName, final Long appTableId, String foreignKeyColumn) { final String sqlString = "SELECT COUNT(" + sqlGenerator.escape(foreignKeyColumn) + ") FROM " + sqlGenerator.escape(datatableName) - + " WHERE " + sqlGenerator.escape(foreignKeyColumn) + "=?"; - final Long count = this.jdbcTemplate.queryForObject(sqlString, Long.class, new Object[] { appTableId }); // NOSONAR + + " WHERE " + sqlGenerator.escape(foreignKeyColumn) + "=" + appTableId; + final Long count = this.jdbcTemplate.queryForObject(sqlString, Long.class); return count; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/staff/service/StaffReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/staff/service/StaffReadPlatformServiceImpl.java index d97988a13..6041fe211 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/staff/service/StaffReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/staff/service/StaffReadPlatformServiceImpl.java @@ -160,7 +160,7 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService { public Collection retrieveAllLoanOfficersInOfficeById(final Long officeId) { SQLBuilder extraCriteria = new SQLBuilder(); extraCriteria.addCriteria(" office_id = ", officeId); - extraCriteria.addCriteria(" is_loan_officer = ", 1); + extraCriteria.addCriteria(" is_loan_officer = ", true); return retrieveAllStaff(extraCriteria); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/data/PortfolioAccountDTO.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/data/PortfolioAccountDTO.java index acdada4dd..a402173a9 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/data/PortfolioAccountDTO.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/data/PortfolioAccountDTO.java @@ -73,6 +73,10 @@ public class PortfolioAccountDTO { return this.accountStatus; } + public long getFirstAccountStatus() { + return this.accountStatus[0]; + } + public Integer getDepositType() { return this.depositType; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/PortfolioAccountReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/PortfolioAccountReadPlatformServiceImpl.java index 77b50317e..810814d3f 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/PortfolioAccountReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/PortfolioAccountReadPlatformServiceImpl.java @@ -105,12 +105,9 @@ public class PortfolioAccountReadPlatformServiceImpl implements PortfolioAccount // sqlParams.add(portfolioAccountDTO.getClientId()); Collection accounts = null; String sql = null; - String defaultAccountStatus = "300"; + long defaultAccountStatus = 300; // Active Status if (portfolioAccountDTO.getAccountStatus() != null) { - for (final long status : portfolioAccountDTO.getAccountStatus()) { - defaultAccountStatus += ", " + status; - } - defaultAccountStatus = defaultAccountStatus.substring(defaultAccountStatus.indexOf(",") + 1); + defaultAccountStatus = portfolioAccountDTO.getFirstAccountStatus(); } final PortfolioAccountType accountType = PortfolioAccountType.fromInt(portfolioAccountDTO.getAccountTypeId()); switch (accountType) { @@ -150,11 +147,11 @@ public class PortfolioAccountReadPlatformServiceImpl implements PortfolioAccount if (portfolioAccountDTO.getDepositType() != null) { sql += " and sa.deposit_type_enum = ?"; - sqlParams.add(portfolioAccountDTO.getDepositType()); + sqlParams.add(portfolioAccountDTO.getDepositType().shortValue()); } if (portfolioAccountDTO.isExcludeOverDraftAccounts()) { - sql += " and sa.allow_overdraft = 0"; + sql += " and sa.allow_overdraft = false"; } if (portfolioAccountDTO.getClientId() == null && portfolioAccountDTO.getGroupId() != null) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java index 50fc8dc0d..702cb56cb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java @@ -74,6 +74,7 @@ import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; import org.apache.fineract.infrastructure.core.service.Page; import org.apache.fineract.infrastructure.core.service.SearchParameters; +import org.apache.fineract.infrastructure.dataqueries.api.DataTableApiConstant; import org.apache.fineract.infrastructure.dataqueries.data.DatatableData; import org.apache.fineract.infrastructure.dataqueries.data.EntityTables; import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum; @@ -104,6 +105,7 @@ import org.apache.fineract.portfolio.fund.data.FundData; import org.apache.fineract.portfolio.fund.service.FundReadPlatformService; import org.apache.fineract.portfolio.group.data.GroupGeneralData; import org.apache.fineract.portfolio.group.service.GroupReadPlatformService; +import org.apache.fineract.portfolio.loanaccount.data.CollectionData; import org.apache.fineract.portfolio.loanaccount.data.DisbursementData; import org.apache.fineract.portfolio.loanaccount.data.GlimRepaymentTemplate; import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData; @@ -494,7 +496,6 @@ public class LoansApiResource { public String retrieveLoan(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId, @DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") @Parameter(description = "staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly, @Context final UriInfo uriInfo) { - long start = System.currentTimeMillis(); this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions); LoanAccountData loanBasicDetails = this.loanReadPlatformService.retrieveOne(loanId); @@ -542,75 +543,83 @@ public class LoansApiResource { Collection emiAmountVariations = null; Collection loanCollateralManagements = null; Collection loanCollateralManagementData = new ArrayList<>(); + CollectionData collectionData = CollectionData.template(); final Set mandatoryResponseParameters = new HashSet<>(); final Set associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters()); if (!associationParameters.isEmpty()) { - if (associationParameters.contains("all")) { - associationParameters.addAll(Arrays.asList("repaymentSchedule", "futureSchedule", "originalSchedule", "transactions", - "charges", "guarantors", "collateral", "notes", "linkedAccount", "multiDisburseDetails")); + if (associationParameters.contains(DataTableApiConstant.allAssociateParamName)) { + associationParameters.addAll(Arrays.asList(DataTableApiConstant.repaymentScheduleAssociateParamName, + DataTableApiConstant.futureScheduleAssociateParamName, DataTableApiConstant.originalScheduleAssociateParamName, + DataTableApiConstant.transactionsAssociateParamName, DataTableApiConstant.chargesAssociateParamName, + DataTableApiConstant.guarantorsAssociateParamName, DataTableApiConstant.collateralAssociateParamName, + DataTableApiConstant.notesAssociateParamName, DataTableApiConstant.linkedAccountAssociateParamName, + DataTableApiConstant.multiDisburseDetailsAssociateParamName, DataTableApiConstant.collectionAssociateParamName)); } ApiParameterHelper.excludeAssociationsForResponseIfProvided(uriInfo.getQueryParameters(), associationParameters); - if (associationParameters.contains("guarantors")) { - mandatoryResponseParameters.add("guarantors"); + if (associationParameters.contains(DataTableApiConstant.guarantorsAssociateParamName)) { + mandatoryResponseParameters.add(DataTableApiConstant.guarantorsAssociateParamName); guarantors = this.guarantorReadPlatformService.retrieveGuarantorsForLoan(loanId); if (CollectionUtils.isEmpty(guarantors)) { guarantors = null; } } - if (associationParameters.contains("transactions")) { - mandatoryResponseParameters.add("transactions"); + if (associationParameters.contains(DataTableApiConstant.transactionsAssociateParamName)) { + mandatoryResponseParameters.add(DataTableApiConstant.transactionsAssociateParamName); final Collection currentLoanRepayments = this.loanReadPlatformService.retrieveLoanTransactions(loanId); if (!CollectionUtils.isEmpty(currentLoanRepayments)) { loanRepayments = currentLoanRepayments; } } - if (associationParameters.contains("multiDisburseDetails") || associationParameters.contains("repaymentSchedule")) { - mandatoryResponseParameters.add("multiDisburseDetails"); + if (associationParameters.contains(DataTableApiConstant.multiDisburseDetailsAssociateParamName) + || associationParameters.contains(DataTableApiConstant.repaymentScheduleAssociateParamName)) { + mandatoryResponseParameters.add(DataTableApiConstant.multiDisburseDetailsAssociateParamName); disbursementData = this.loanReadPlatformService.retrieveLoanDisbursementDetails(loanId); } - if (associationParameters.contains("emiAmountVariations") || associationParameters.contains("repaymentSchedule")) { - mandatoryResponseParameters.add("emiAmountVariations"); + if (associationParameters.contains(DataTableApiConstant.emiAmountVariationsAssociateParamName) + || associationParameters.contains(DataTableApiConstant.repaymentScheduleAssociateParamName)) { + mandatoryResponseParameters.add(DataTableApiConstant.emiAmountVariationsAssociateParamName); emiAmountVariations = this.loanReadPlatformService.retrieveLoanTermVariations(loanId, LoanTermVariationType.EMI_AMOUNT.getValue()); } - if (associationParameters.contains("repaymentSchedule")) { - mandatoryResponseParameters.add("repaymentSchedule"); + if (associationParameters.contains(DataTableApiConstant.repaymentScheduleAssociateParamName)) { + mandatoryResponseParameters.add(DataTableApiConstant.repaymentScheduleAssociateParamName); final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData = loanBasicDetails.repaymentScheduleRelatedData(); repaymentSchedule = this.loanReadPlatformService.retrieveRepaymentSchedule(loanId, repaymentScheduleRelatedData, disbursementData, loanBasicDetails.isInterestRecalculationEnabled(), loanBasicDetails.getTotalPaidFeeCharges()); - if (associationParameters.contains("futureSchedule") && loanBasicDetails.isInterestRecalculationEnabled()) { - mandatoryResponseParameters.add("futureSchedule"); + if (associationParameters.contains(DataTableApiConstant.futureScheduleAssociateParamName) + && loanBasicDetails.isInterestRecalculationEnabled()) { + mandatoryResponseParameters.add(DataTableApiConstant.futureScheduleAssociateParamName); this.calculationPlatformService.updateFutureSchedule(repaymentSchedule, loanId); } - if (associationParameters.contains("originalSchedule") && loanBasicDetails.isInterestRecalculationEnabled() - && loanBasicDetails.isActive()) { - mandatoryResponseParameters.add("originalSchedule"); + if (associationParameters.contains(DataTableApiConstant.originalScheduleAssociateParamName) + && loanBasicDetails.isInterestRecalculationEnabled() && loanBasicDetails.isActive()) { + mandatoryResponseParameters.add(DataTableApiConstant.originalScheduleAssociateParamName); LoanScheduleData loanScheduleData = this.loanScheduleHistoryReadPlatformService.retrieveRepaymentArchiveSchedule(loanId, repaymentScheduleRelatedData, disbursementData); loanBasicDetails = LoanAccountData.withOriginalSchedule(loanBasicDetails, loanScheduleData); } } - if (associationParameters.contains("charges")) { - mandatoryResponseParameters.add("charges"); + if (associationParameters.contains(DataTableApiConstant.chargesAssociateParamName)) { + mandatoryResponseParameters.add(DataTableApiConstant.chargesAssociateParamName); charges = this.loanChargeReadPlatformService.retrieveLoanCharges(loanId); if (CollectionUtils.isEmpty(charges)) { charges = null; } } - if (associationParameters.contains("collateral")) { - mandatoryResponseParameters.add("collateral"); + if (associationParameters.contains(DataTableApiConstant.collateralAssociateParamName)) { + mandatoryResponseParameters.add(DataTableApiConstant.collateralAssociateParamName); loanCollateralManagements = this.loanCollateralManagementReadPlatformService.getLoanCollateralResponseDataList(loanId); for (LoanCollateralResponseData loanCollateralManagement : loanCollateralManagements) { loanCollateralManagementData.add(loanCollateralManagement.toCommand()); @@ -620,24 +629,30 @@ public class LoansApiResource { } } - if (associationParameters.contains("meeting")) { - mandatoryResponseParameters.add("meeting"); + if (associationParameters.contains(DataTableApiConstant.meetingAssociateParamName)) { + mandatoryResponseParameters.add(DataTableApiConstant.meetingAssociateParamName); meeting = this.calendarReadPlatformService.retrieveLoanCalendar(loanId); } - if (associationParameters.contains("notes")) { - mandatoryResponseParameters.add("notes"); + if (associationParameters.contains(DataTableApiConstant.notesAssociateParamName)) { + mandatoryResponseParameters.add(DataTableApiConstant.notesAssociateParamName); notes = this.noteReadPlatformService.retrieveNotesByResource(loanId, NoteType.LOAN.getValue()); if (CollectionUtils.isEmpty(notes)) { notes = null; } } - if (associationParameters.contains("linkedAccount")) { - mandatoryResponseParameters.add("linkedAccount"); + if (associationParameters.contains(DataTableApiConstant.linkedAccountAssociateParamName)) { + mandatoryResponseParameters.add(DataTableApiConstant.linkedAccountAssociateParamName); linkedAccount = this.accountAssociationsReadPlatformService.retriveLoanLinkedAssociation(loanId); } + if (associationParameters.contains(DataTableApiConstant.collectionAssociateParamName)) { + mandatoryResponseParameters.add(DataTableApiConstant.collectionAssociateParamName); + if (loanBasicDetails.isActive()) { + collectionData = this.loanReadPlatformService.retrieveLoanCollectionData(loanId); + } + } } Collection productOptions = null; @@ -707,8 +722,8 @@ public class LoansApiResource { loanBasicDetails.clientId(), currencyCode, accountStatus, DepositAccountType.SAVINGS_DEPOSIT.getValue()); accountLinkingOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO); - if (!associationParameters.contains("linkedAccount")) { - mandatoryResponseParameters.add("linkedAccount"); + if (!associationParameters.contains(DataTableApiConstant.linkedAccountAssociateParamName)) { + mandatoryResponseParameters.add(DataTableApiConstant.linkedAccountAssociateParamName); linkedAccount = this.accountAssociationsReadPlatformService.retriveLoanLinkedAssociation(loanId); } if (loanBasicDetails.groupId() != null) { @@ -740,12 +755,12 @@ public class LoansApiResource { repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, allowedLoanOfficers, loanPurposeOptions, loanCollateralOptions, calendarOptions, notes, accountLinkingOptions, linkedAccount, disbursementData, emiAmountVariations, - overdueCharges, paidInAdvanceTemplate, interestRatesPeriods, clientActiveLoanOptions, rates, isRatesEnabled); + overdueCharges, paidInAdvanceTemplate, interestRatesPeriods, clientActiveLoanOptions, rates, isRatesEnabled, + collectionData); final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters(), mandatoryResponseParameters); - String toReturn = this.toApiJsonSerializer.serialize(settings, loanAccount, this.loanDataParameters); - return toReturn; + return this.toApiJsonSerializer.serialize(settings, loanAccount, this.loanDataParameters); } @GET diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/CollectionData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/CollectionData.java new file mode 100644 index 000000000..35c685311 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/CollectionData.java @@ -0,0 +1,90 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.loanaccount.data; + +import java.math.BigDecimal; +import java.time.LocalDate; + +public final class CollectionData { + + private final BigDecimal availableDisbursementAmount; + private final int pastDueDays; + private final LocalDate nextPaymentDueDate; + private final int delinquentDays; + private final LocalDate delinquentDate; + private final BigDecimal delinquentAmount; + private final LocalDate lastPaymentDate; + private final BigDecimal lastPaymentAmount; + + private CollectionData(BigDecimal availableDisbursementAmount, int pastDueDays, LocalDate nextPaymentDueDate, int delinquentDays, + LocalDate delinquentDate, BigDecimal delinquentAmount, LocalDate lastPaymentDate, BigDecimal lastPaymentAmount) { + this.availableDisbursementAmount = availableDisbursementAmount; + this.pastDueDays = pastDueDays; + this.nextPaymentDueDate = nextPaymentDueDate; + this.delinquentDays = delinquentDays; + this.delinquentDate = delinquentDate; + this.delinquentAmount = delinquentAmount; + this.lastPaymentDate = lastPaymentDate; + this.lastPaymentAmount = lastPaymentAmount; + } + + public static CollectionData instance(BigDecimal availableDisbursementAmount, int pastDueDays, LocalDate nextPaymentDueDate, + int delinquentDays, LocalDate delinquentDate, BigDecimal delinquentAmount, LocalDate lastPaymentDate, + BigDecimal lastPaymentAmount) { + return new CollectionData(availableDisbursementAmount, pastDueDays, nextPaymentDueDate, delinquentDays, delinquentDate, + delinquentAmount, lastPaymentDate, lastPaymentAmount); + } + + public static CollectionData template() { + final BigDecimal zero = BigDecimal.ZERO; + return new CollectionData(zero, 0, null, 0, null, zero, null, zero); + } + + public BigDecimal getAvailableDisbursementAmount() { + return availableDisbursementAmount; + } + + public int getPastDueDays() { + return pastDueDays; + } + + public LocalDate getNextPaymentDueDate() { + return nextPaymentDueDate; + } + + public int getDelinquentDays() { + return delinquentDays; + } + + public LocalDate getDelinquentDate() { + return delinquentDate; + } + + public BigDecimal getDelinquentAmount() { + return delinquentAmount; + } + + public LocalDate getLastPaymentDate() { + return lastPaymentDate; + } + + public BigDecimal getLastPaymentAmount() { + return lastPaymentAmount; + } +} 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 61accd2d9..4bc706a62 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 @@ -238,6 +238,8 @@ public final class LoanAccountData { private Long groupId; private LocalDate expectedDisbursementDate; + private final CollectionData delinquent; + public static LoanAccountData importInstanceIndividual(EnumOptionData loanTypeEnumOption, Long clientId, Long productId, Long loanOfficerId, LocalDate submittedOnDate, Long fundId, BigDecimal principal, Integer numberOfRepayments, Integer repaymentEvery, EnumOptionData repaidEveryFrequencyEnums, Integer loanTermFrequency, @@ -423,6 +425,7 @@ public final class LoanAccountData { this.isEqualAmortization = null; this.isRatesEnabled = false; this.fixedPrincipalPercentagePerInstallment = null; + this.delinquent = null; } public Integer getRowIndex() { @@ -588,6 +591,7 @@ public final class LoanAccountData { final List rates = null; final Boolean isRatesEnabled = false; final BigDecimal fixedPrincipalPercentagePerInstallment = null; + final CollectionData delinquent = CollectionData.template(); return new LoanAccountData(id, accountNo, status, externalId, clientId, clientAccountNo, clientName, clientOfficeId, group, loanType, loanProductId, loanProductName, loanProductDescription, isLoanProductLinkedToFloatingRate, fundId, fundName, @@ -609,8 +613,7 @@ public final class LoanAccountData { interestRecalculationData, originalSchedule, createStandingInstructionAtDisbursement, paidInAdvance, interestRatesPeriods, isVariableInstallmentsAllowed, minimumGap, maximumGap, subStatus, canUseForTopup, clientActiveLoanOptions, isTopup, closureLoanId, closureLoanAccountNo, topupAmount, isEqualAmortization, rates, isRatesEnabled, - fixedPrincipalPercentagePerInstallment); - + fixedPrincipalPercentagePerInstallment, delinquent); } /** @@ -734,6 +737,7 @@ public final class LoanAccountData { final List rates = null; final Boolean isRatesEnabled = false; final BigDecimal fixedPrincipalPercentagePerInstallment = null; + final CollectionData delinquent = CollectionData.template(); return new LoanAccountData(id, accountNo, status, externalId, clientId, clientAccountNo, clientName, clientOfficeId, group, loanType, loanProductId, loanProductName, loanProductDescription, isLoanProductLinkedToFloatingRate, fundId, fundName, @@ -755,8 +759,7 @@ public final class LoanAccountData { originalSchedule, createStandingInstructionAtDisbursement, paidInAdvance, interestRatesPeriods, isVariableInstallmentsAllowed, minimumGap, maximumGap, subStatus, canUseForTopup, clientActiveLoanOptions, isTopup, closureLoanId, closureLoanAccountNo, topupAmount, isEqualAmortization, rates, isRatesEnabled, - fixedPrincipalPercentagePerInstallment); - + fixedPrincipalPercentagePerInstallment, delinquent); } public static LoanAccountData populateClientDefaults(final LoanAccountData acc, final LoanAccountData clientAcc) { @@ -787,7 +790,7 @@ public final class LoanAccountData { acc.createStandingInstructionAtDisbursement, acc.paidInAdvance, acc.interestRatesPeriods, acc.isVariableInstallmentsAllowed, acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled, - acc.fixedPrincipalPercentagePerInstallment); + acc.fixedPrincipalPercentagePerInstallment, acc.delinquent); } /** @@ -913,6 +916,7 @@ public final class LoanAccountData { final List rates = null; final Boolean isRatesEnabled = false; final BigDecimal fixedPrincipalPercentagePerInstallment = null; + final CollectionData delinquent = CollectionData.template(); return new LoanAccountData(id, accountNo, status, externalId, clientId, clientAccountNo, clientName, clientOfficeId, group, loanType, loanProductId, loanProductName, loanProductDescription, isLoanProductLinkedToFloatingRate, fundId, fundName, @@ -934,8 +938,7 @@ public final class LoanAccountData { originalSchedule, createStandingInstructionAtDisbursement, paidInAdvance, interestRatesPeriods, isVariableInstallmentsAllowed, minimumGap, maximumGap, subStatus, canUseForTopup, clientActiveLoanOptions, isTopup, closureLoanId, closureLoanAccountNo, topupAmount, isEqualAmortization, rates, isRatesEnabled, - fixedPrincipalPercentagePerInstallment); - + fixedPrincipalPercentagePerInstallment, delinquent); } public static LoanAccountData populateGroupDefaults(final LoanAccountData acc, final LoanAccountData groupAcc) { @@ -965,8 +968,7 @@ public final class LoanAccountData { acc.createStandingInstructionAtDisbursement, acc.paidInAdvance, acc.interestRatesPeriods, acc.isVariableInstallmentsAllowed, acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled, - acc.fixedPrincipalPercentagePerInstallment); - + acc.fixedPrincipalPercentagePerInstallment, acc.delinquent); } public static LoanAccountData loanProductWithTemplateDefaults(final LoanProductData product, @@ -1107,6 +1109,7 @@ public final class LoanAccountData { final BigDecimal topupAmount = null; final List rates = null; final Boolean isRatesEnabled = false; + final CollectionData delinquent = CollectionData.template(); return new LoanAccountData(id, accountNo, status, externalId, clientId, clientAccountNo, clientName, clientOfficeId, group, loanType, product.getId(), product.getName(), product.getDescription(), product.isLinkedToFloatingInterestRates(), @@ -1133,7 +1136,7 @@ public final class LoanAccountData { product.isVariableInstallmentsAllowed(), product.getMinimumGapBetweenInstallments(), product.getMaximumGapBetweenInstallments(), subStatus, canUseForTopup, clientActiveLoanOptions, isTopup, closureLoanId, closureLoanAccountNo, topupAmount, product.isEqualAmortization(), rates, isRatesEnabled, - product.getFixedPrincipalPercentagePerInstallment()); + product.getFixedPrincipalPercentagePerInstallment(), delinquent); } public static LoanAccountData populateLoanProductDefaults(final LoanAccountData acc, final LoanProductData product) { @@ -1175,6 +1178,7 @@ public final class LoanAccountData { netDisbursalAmount = netDisbursalAmount.subtract(charge.getAmount()); } } + final CollectionData delinquent = CollectionData.template(); return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientAccountNo, acc.clientName, acc.clientOfficeId, acc.group, acc.loanType, product.getId(), product.getName(), product.getDescription(), @@ -1202,8 +1206,7 @@ public final class LoanAccountData { product.isVariableInstallmentsAllowed(), product.getMinimumGapBetweenInstallments(), product.getMaximumGapBetweenInstallments(), acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, product.isEqualAmortization(), acc.rates, acc.isRatesEnabled, - product.getFixedPrincipalPercentagePerInstallment()); - + product.getFixedPrincipalPercentagePerInstallment(), delinquent); } /* @@ -1273,6 +1276,7 @@ public final class LoanAccountData { final Collection clientActiveLoanOptions = null; final List rates = null; final Boolean isRatesEnabled = false; + final CollectionData delinquent = CollectionData.template(); return new LoanAccountData(id, accountNo, status, externalId, clientId, clientAccountNo, clientName, clientOfficeId, group, loanType, loanProductId, loanProductName, loanProductDescription, isLoanProductLinkedToFloatingRate, fundId, fundName, @@ -1293,7 +1297,7 @@ public final class LoanAccountData { isNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, interestRecalculationData, originalSchedule, createStandingInstructionAtDisbursement, paidInAdvance, interestRatesPeriods, isVariableInstallmentsAllowed, minimumGap, maximumGap, subStatus, canUseForTopup, clientActiveLoanOptions, isTopup, closureLoanId, closureLoanAccountNo, topupAmount, - isEqualAmortization, rates, isRatesEnabled, fixedPrincipalPercentagePerInstallment); + isEqualAmortization, rates, isRatesEnabled, fixedPrincipalPercentagePerInstallment, delinquent); } /* @@ -1316,7 +1320,8 @@ public final class LoanAccountData { final PortfolioAccountData linkedAccount, final Collection disbursementDetails, final Collection emiAmountVariations, final Collection overdueCharges, final PaidInAdvanceData paidInAdvance, Collection interestRatesPeriods, - final Collection clientActiveLoanOptions, final List rates, final Boolean isRatesEnabled) { + final Collection clientActiveLoanOptions, final List rates, final Boolean isRatesEnabled, + final CollectionData delinquent) { LoanProductConfigurableAttributes loanProductConfigurableAttributes = null; if (acc.product != null) { loanProductConfigurableAttributes = acc.product.getloanProductConfigurableAttributes(); @@ -1346,7 +1351,7 @@ public final class LoanAccountData { acc.createStandingInstructionAtDisbursement, paidInAdvance, interestRatesPeriods, acc.isVariableInstallmentsAllowed, acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, rates, isRatesEnabled, - acc.fixedPrincipalPercentagePerInstallment); + acc.fixedPrincipalPercentagePerInstallment, delinquent); } public static LoanAccountData associationsAndTemplate(final LoanAccountData acc, final Collection productOptions, @@ -1359,7 +1364,7 @@ public final class LoanAccountData { acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null, allowedLoanOfficers, acc.loanPurposeOptions, acc.loanCollateralOptions, calendarOptions, acc.notes, accountLinkingOptions, acc.linkedAccount, acc.disbursementDetails, acc.emiAmountVariations, acc.overdueCharges, acc.paidInAdvance, - acc.interestRatesPeriods, acc.clientActiveLoanOptions, acc.rates, isRatesEnabled); + acc.interestRatesPeriods, acc.clientActiveLoanOptions, acc.rates, isRatesEnabled, acc.delinquent); } public static LoanAccountData associateGroup(final LoanAccountData acc, final GroupGeneralData group) { @@ -1389,7 +1394,7 @@ public final class LoanAccountData { acc.createStandingInstructionAtDisbursement, acc.paidInAdvance, acc.interestRatesPeriods, acc.isVariableInstallmentsAllowed, acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled, - acc.fixedPrincipalPercentagePerInstallment); + acc.fixedPrincipalPercentagePerInstallment, acc.delinquent); } public static LoanAccountData associateMemberVariations(final LoanAccountData acc, final Map memberLoanCycle) { @@ -1455,8 +1460,7 @@ public final class LoanAccountData { acc.createStandingInstructionAtDisbursement, acc.paidInAdvance, acc.interestRatesPeriods, acc.isVariableInstallmentsAllowed, acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled, - acc.fixedPrincipalPercentagePerInstallment); - + acc.fixedPrincipalPercentagePerInstallment, acc.delinquent); } public static LoanAccountData withInterestRecalculationCalendarData(final LoanAccountData acc, final CalendarData calendarData, @@ -1490,7 +1494,7 @@ public final class LoanAccountData { acc.createStandingInstructionAtDisbursement, acc.paidInAdvance, acc.interestRatesPeriods, acc.isVariableInstallmentsAllowed, acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled, - acc.fixedPrincipalPercentagePerInstallment); + acc.fixedPrincipalPercentagePerInstallment, acc.delinquent); } public static LoanAccountData withLoanCalendarData(final LoanAccountData acc, final CalendarData calendarData) { @@ -1519,7 +1523,7 @@ public final class LoanAccountData { acc.createStandingInstructionAtDisbursement, acc.paidInAdvance, acc.interestRatesPeriods, acc.isVariableInstallmentsAllowed, acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled, - acc.fixedPrincipalPercentagePerInstallment); + acc.fixedPrincipalPercentagePerInstallment, acc.delinquent); } public static LoanAccountData withOriginalSchedule(final LoanAccountData acc, final LoanScheduleData originalSchedule) { @@ -1549,7 +1553,7 @@ public final class LoanAccountData { acc.createStandingInstructionAtDisbursement, acc.paidInAdvance, acc.interestRatesPeriods, acc.isVariableInstallmentsAllowed, acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled, - acc.fixedPrincipalPercentagePerInstallment); + acc.fixedPrincipalPercentagePerInstallment, acc.delinquent); } private LoanAccountData(final Long id, // @@ -1602,7 +1606,7 @@ public final class LoanAccountData { final Integer minimumGap, final Integer maximumGap, final EnumOptionData subStatus, final Boolean canUseForTopup, final Collection clientActiveLoanOptions, final boolean isTopup, final Long closureLoanId, final String closureLoanAccountNo, final BigDecimal topupAmount, final boolean isEqualAmortization, final List rates, - final Boolean isRatesEnabled, final BigDecimal fixedPrincipalPercentagePerInstallment) { + final Boolean isRatesEnabled, final BigDecimal fixedPrincipalPercentagePerInstallment, final CollectionData delinquent) { this.id = id; this.accountNo = accountNo; @@ -1789,6 +1793,7 @@ public final class LoanAccountData { this.isEqualAmortization = isEqualAmortization; this.rates = rates; this.fixedPrincipalPercentagePerInstallment = fixedPrincipalPercentagePerInstallment; + this.delinquent = delinquent; } public RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java index 3ad197ea3..151793467 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java @@ -28,6 +28,7 @@ import org.apache.fineract.infrastructure.core.service.SearchParameters; import org.apache.fineract.organisation.staff.data.StaffData; import org.apache.fineract.portfolio.calendar.data.CalendarData; import org.apache.fineract.portfolio.floatingrates.data.InterestRatePeriodData; +import org.apache.fineract.portfolio.loanaccount.data.CollectionData; import org.apache.fineract.portfolio.loanaccount.data.DisbursementData; import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData; import org.apache.fineract.portfolio.loanaccount.data.LoanApprovalData; @@ -147,4 +148,5 @@ public interface LoanReadPlatformService { List getRepaymentDataResponse(Long loanId); + CollectionData retrieveLoanCollectionData(Long loanId); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index 686540c38..0d8e30566 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -81,6 +81,7 @@ import org.apache.fineract.portfolio.group.data.GroupGeneralData; import org.apache.fineract.portfolio.group.data.GroupRoleData; import org.apache.fineract.portfolio.group.service.GroupReadPlatformService; import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants; +import org.apache.fineract.portfolio.loanaccount.data.CollectionData; import org.apache.fineract.portfolio.loanaccount.data.DisbursementData; import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData; import org.apache.fineract.portfolio.loanaccount.data.LoanApplicationTimelineData; @@ -2349,4 +2350,58 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { final String sql = "select count(*) from m_loan"; return this.jdbcTemplate.queryForObject(sql, Integer.class); } + + @Override + public CollectionData retrieveLoanCollectionData(Long loanId) { + final CollectionDataMapper mapper = new CollectionDataMapper(sqlGenerator); + String sql = "select " + mapper.schema(); + CollectionData collectionData = this.jdbcTemplate.queryForObject(sql, mapper, new Object[] { loanId }); + return collectionData; + } + + private static final class CollectionDataMapper implements RowMapper { + + private final DatabaseSpecificSQLGenerator sqlGenerator; + + CollectionDataMapper(DatabaseSpecificSQLGenerator sqlGenerator) { + this.sqlGenerator = sqlGenerator; + } + + public String schema() { + StringBuilder sqlBuilder = new StringBuilder(); + + sqlBuilder.append( + "l.id as loanId, coalesce((l.approved_principal - l.principal_disbursed_derived), 0) as availableDisbursementAmount, "); + sqlBuilder.append(sqlGenerator.dateDiff(sqlGenerator.currentDate(), "laa.overdue_since_date_derived") + " as pastDueDays, "); + sqlBuilder.append( + "(select coalesce(min(lrs.duedate), null) as duedate from m_loan_repayment_schedule lrs where lrs.loan_id=l.id and lrs.completed_derived is false and lrs.duedate >= " + + sqlGenerator.currentDate() + ") as nextPaymentDueDate, "); + sqlBuilder.append(sqlGenerator.dateDiff(sqlGenerator.currentDate(), "laa.overdue_since_date_derived") + " as delinquentDays, "); + sqlBuilder.append( + sqlGenerator.currentDate() + " as delinquentDate, coalesce(laa.total_overdue_derived, 0) as delinquentAmount, "); + sqlBuilder.append("lre.transactionDate as lastPaymentDate, coalesce(lre.amount, 0) as lastPaymentAmount "); + sqlBuilder.append("from m_loan l inner join m_loan_arrears_aging laa on laa.loan_id = l.id "); + sqlBuilder.append( + "left join (select lt.loan_id, lt.transaction_date as transactionDate, lt.amount as amount from m_loan_transaction lt "); + sqlBuilder.append( + "where lt.is_reversed = false and lt.transaction_type_enum=2 order by lt.transaction_date desc limit 1) lre on lre.loan_id = l.id "); + sqlBuilder.append("where l.id=? "); + return sqlBuilder.toString(); + } + + @Override + public CollectionData mapRow(ResultSet rs, int rowNum) throws SQLException { + final LocalDate nextPaymentDueDate = JdbcSupport.getLocalDate(rs, "nextPaymentDueDate"); + final LocalDate delinquentDate = JdbcSupport.getLocalDate(rs, "delinquentDate"); + final LocalDate lastPaymentDate = JdbcSupport.getLocalDate(rs, "lastPaymentDate"); + final BigDecimal availableDisbursementAmount = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "availableDisbursementAmount"); + final BigDecimal delinquentAmount = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "delinquentAmount"); + final BigDecimal lastPaymentAmount = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "lastPaymentAmount"); + final int pastDueDays = rs.getInt("pastDueDays"); + final int delinquentDays = rs.getInt("delinquentDays"); + + return CollectionData.instance(availableDisbursementAmount, pastDueDays, nextPaymentDueDate, delinquentDays, delinquentDate, + delinquentAmount, lastPaymentDate, lastPaymentAmount); + } + } } diff --git a/fineract-provider/src/main/resources/logback-spring.xml b/fineract-provider/src/main/resources/logback-spring.xml index 98ae105f0..a24143495 100644 --- a/fineract-provider/src/main/resources/logback-spring.xml +++ b/fineract-provider/src/main/resources/logback-spring.xml @@ -32,7 +32,7 @@ - + diff --git a/fineract-provider/src/test/resources/logback.xml b/fineract-provider/src/test/resources/logback.xml index c2e891871..30cf96640 100644 --- a/fineract-provider/src/test/resources/logback.xml +++ b/fineract-provider/src/test/resources/logback.xml @@ -24,7 +24,7 @@ false - + true %green(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%thread] %highlight(%-5level) %cyan(%logger{36}) - %msg%n diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java index 861c47ba8..06f48f9ac 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java @@ -40,6 +40,7 @@ import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.integrationtests.common.ClientHelper; @@ -3399,7 +3400,7 @@ public class ClientLoanIntegrationTest { public void testLoanScheduleWithInterestRecalculation_WITH_REST_SAME_AS_REPAYMENT_INTEREST_COMPOUND_NONE_STRATEGY_REDUCE_EMI() { this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); Calendar todaysDate = Calendar.getInstance(Utils.getTimeZoneOfTenant()); @@ -3509,7 +3510,7 @@ public class ClientLoanIntegrationTest { private void testLoanScheduleWithInterestRecalculation_WITH_REST_SAME_AS_REPAYMENT_INTEREST_COMPOUND_NONE_STRATEGY_REDUCE_EMI_PRE_CLOSE_INTEREST( String preCloseInterestStrategy, String preCloseAmount) { this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); Calendar todaysDate = Calendar.getInstance(Utils.getTimeZoneOfTenant()); @@ -3590,7 +3591,7 @@ public class ClientLoanIntegrationTest { public void testLoanScheduleWithInterestRecalculation_WITH_REST_SAME_AS_REPAYMENT_INTEREST_COMPOUND_NONE_STRATEGY_REDUCE_EMI_WITH_INSTALLMENT_CHARGE() { this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); Calendar todaysDate = Calendar.getInstance(Utils.getTimeZoneOfTenant()); @@ -3688,7 +3689,7 @@ public class ClientLoanIntegrationTest { public void testLoanScheduleWithInterestRecalculation_WITH_REST_DAILY_INTEREST_COMPOUND_INTEREST_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS() { this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); Calendar todaysDate = Calendar.getInstance(Utils.getTimeZoneOfTenant()); @@ -3802,7 +3803,7 @@ public class ClientLoanIntegrationTest { public void testLoanScheduleWithInterestRecalculation_WITH_REST_WEEKLY_INTEREST_COMPOUND_INTEREST_FEE_STRATEGY_REDUCE_NEXT_INSTALLMENTS() { this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); Calendar todaysDate = Calendar.getInstance(Utils.getTimeZoneOfTenant()); @@ -3939,7 +3940,7 @@ public class ClientLoanIntegrationTest { String preCloseInterestStrategy, String preCloseAmount) { this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); Calendar todaysDate = Calendar.getInstance(Utils.getTimeZoneOfTenant()); @@ -4041,7 +4042,7 @@ public class ClientLoanIntegrationTest { throws InterruptedException { this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); Calendar todaysDate = Calendar.getInstance(Utils.getTimeZoneOfTenant()); @@ -4157,7 +4158,7 @@ public class ClientLoanIntegrationTest { this.periodicAccrualAccountingHelper = new PeriodicAccrualAccountingHelper(this.requestSpec, this.responseSpec); this.journalEntryHelper = new JournalEntryHelper(this.requestSpec, this.responseSpec); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); final Account assetAccount = this.accountHelper.createAssetAccount(); @@ -4263,7 +4264,7 @@ public class ClientLoanIntegrationTest { public void testLoanScheduleWithInterestRecalculation_WITH_CURRENT_REPAYMENT_BASED_ARREARS_AGEING() { this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); Calendar todaysDate = Calendar.getInstance(Utils.getTimeZoneOfTenant()); @@ -4345,7 +4346,7 @@ public class ClientLoanIntegrationTest { public void testLoanScheduleWithInterestRecalculation_WITH_ORIGINAL_REPAYMENT_BASED_ARREARS_AGEING() { this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); Calendar todaysDate = Calendar.getInstance(Utils.getTimeZoneOfTenant()); @@ -4440,7 +4441,7 @@ public class ClientLoanIntegrationTest { final String preCloseAmount) { this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); Calendar todaysDate = Calendar.getInstance(Utils.getTimeZoneOfTenant()); @@ -5390,7 +5391,7 @@ public class ClientLoanIntegrationTest { public void testLoanScheduleWithInterestRecalculation_WITH_INTEREST_FIRST_STRATEGY_AND_REST_DAILY_INTEREST_COMPOUND_INTEREST_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS() { this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); Calendar todaysDate = Calendar.getInstance(Utils.getTimeZoneOfTenant()); @@ -5505,7 +5506,7 @@ public class ClientLoanIntegrationTest { public void testLoanScheduleWithInterestRecalculation_WITH_INTEREST_FIRST_STRATEGY_AND_REST_DAILY_INTEREST_COMPOUND_INTEREST_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS_EARLY_REPAYMENT() { this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); Calendar todaysDate = Calendar.getInstance(Utils.getTimeZoneOfTenant()); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java index 6f711320b..fe87fb36d 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java @@ -374,7 +374,7 @@ public class ClientSavingsIntegrationTest { balance -= chargeAmt; assertEquals(balance, summary.get("accountBalance"), "Verifying opening Balance"); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); Calendar todaysDate = Calendar.getInstance(); final String TRANSACTION_DATE = dateFormat.format(todaysDate.getTime()); final String withdrawAmt = "800"; @@ -2284,7 +2284,7 @@ public class ClientSavingsIntegrationTest { assertEquals(balance, summary.get("availableBalance"), "Verifying available Balance is -1000"); Integer depositTransactionId = (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, "1200", SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); Calendar todaysDate = Calendar.getInstance(); final String TRANSACTION_DATE = dateFormat.format(todaysDate.getTime()); @@ -2348,7 +2348,7 @@ public class ClientSavingsIntegrationTest { Integer depositTransactionId = (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, "1200", SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); Calendar todaysDate = Calendar.getInstance(); final String TRANSACTION_DATE = dateFormat.format(todaysDate.getTime()); @@ -2412,7 +2412,7 @@ public class ClientSavingsIntegrationTest { Integer depositTransactionId = (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, "1100", SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); Calendar todaysDate = Calendar.getInstance(); final String TRANSACTION_DATE = dateFormat.format(todaysDate.getTime()); @@ -2488,7 +2488,7 @@ public class ClientSavingsIntegrationTest { // hold SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); Calendar todaysDate = Calendar.getInstance(); final String TRANSACTION_DATE = dateFormat.format(todaysDate.getTime()); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/DisbursalAndRepaymentScheduleTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/DisbursalAndRepaymentScheduleTest.java index 43ee8e61c..54e2d4e66 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/DisbursalAndRepaymentScheduleTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/DisbursalAndRepaymentScheduleTest.java @@ -31,6 +31,7 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; +import java.util.Locale; import org.apache.fineract.integrationtests.common.CalendarHelper; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.GroupHelper; @@ -69,7 +70,7 @@ public class DisbursalAndRepaymentScheduleTest { private final String numberOfRepayments = "12"; private final String interestRatePerPeriod = "18"; - private final SimpleDateFormat dateFormatterStandard = new SimpleDateFormat("dd MMMM yyyy"); + private final SimpleDateFormat dateFormatterStandard = new SimpleDateFormat("dd MMMM yyyy", Locale.US); @BeforeEach public void setup() { diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDisbursementDetailsIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDisbursementDetailsIntegrationTest.java index 6f651c598..a2c3d5de0 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDisbursementDetailsIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDisbursementDetailsIntegrationTest.java @@ -31,6 +31,7 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Locale; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.Utils; @@ -436,7 +437,7 @@ public class LoanDisbursementDetailsIntegrationTest { private String formatExpectedDisbursementDate(String expectedDisbursementDate) throws ParseException { SimpleDateFormat source = new SimpleDateFormat("[yyyy, MM, dd]"); - SimpleDateFormat target = new SimpleDateFormat("dd MMMM yyyy"); + SimpleDateFormat target = new SimpleDateFormat("dd MMMM yyyy", Locale.US); String date = target.format(source.parse(expectedDisbursementDate)); return date; diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java index b51c47ce4..05b9161af 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java @@ -36,6 +36,7 @@ import java.util.Arrays; import java.util.Calendar; import java.util.HashMap; import java.util.List; +import java.util.Locale; import org.apache.fineract.integrationtests.common.CalendarHelper; import org.apache.fineract.integrationtests.common.CenterDomain; import org.apache.fineract.integrationtests.common.CenterHelper; @@ -103,7 +104,7 @@ public class LoanReschedulingWithinCenterTest { associateClientsToGroup(groupId, clientId); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); Calendar today = Calendar.getInstance(Utils.getTimeZoneOfTenant()); today.add(Calendar.DAY_OF_MONTH, -14); @@ -193,7 +194,7 @@ public class LoanReschedulingWithinCenterTest { } private Integer createCalendarMeeting(Integer centerId) { - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); Calendar today = Calendar.getInstance(Utils.getTimeZoneOfTenant()); final String startDate = dateFormat.format(today.getTime()); @@ -236,7 +237,7 @@ public class LoanReschedulingWithinCenterTest { associateClientsToGroup(groupId, clientId); // CREATE A LOAN PRODUCT - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); Calendar today = Calendar.getInstance(Utils.getTimeZoneOfTenant()); today.add(Calendar.DAY_OF_MONTH, -14); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/RepaymentWithPostDatedChecksTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/RepaymentWithPostDatedChecksTest.java index 3e392a746..0c33d2bde 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/RepaymentWithPostDatedChecksTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/RepaymentWithPostDatedChecksTest.java @@ -33,6 +33,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.List; +import java.util.Locale; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.PaymentTypeDomain; @@ -50,7 +51,7 @@ public class RepaymentWithPostDatedChecksTest { private ResponseSpecification responseSpec; private RequestSpecification requestSpec; - private final SimpleDateFormat dateFormatterStandard = new SimpleDateFormat("dd MMMM yyyy"); + private final SimpleDateFormat dateFormatterStandard = new SimpleDateFormat("dd MMMM yyyy", Locale.US); private LoanTransactionHelper loanTransactionHelper; @BeforeEach @@ -95,7 +96,7 @@ public class RepaymentWithPostDatedChecksTest { List postDatedChecks = new ArrayList<>(); Gson gson = new Gson(); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); // Get the first installment date diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java index 44f41622e..27211eb63 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java @@ -509,7 +509,8 @@ public class SchedulerJobsTestResults { "Verifying Loan Repayment in Advance after Running Update Loan Paid in Advance Scheduler Job"); } - // Invalid test case as it won't affect summary (Loan summary is properly updated before running this job) + // Invalid test case as it won't affect summary (Loan summary is properly + // updated before running this job) @Disabled @Test public void testUpdateLoanSummaryJobOutcome() throws InterruptedException { @@ -575,11 +576,12 @@ public class SchedulerJobsTestResults { DateFormat monthDayFormat = new SimpleDateFormat("dd MMMM", Locale.US); Calendar todaysDate = Calendar.getInstance(); - todaysDate.add(Calendar.WEEK_OF_YEAR, -1); - final String VALID_FROM = dateFormat.format(todaysDate.getTime()); final String MONTH_DAY = monthDayFormat.format(todaysDate.getTime()); + todaysDate.add(Calendar.WEEK_OF_YEAR, -1); + final String VALID_FROM = dateFormat.format(todaysDate.getTime()); + todaysDate.add(Calendar.YEAR, 1); final String VALID_TO = dateFormat.format(todaysDate.getTime()); @@ -880,7 +882,8 @@ public class SchedulerJobsTestResults { private Integer createSavingsProduct(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String minOpenningBalance) { - // system.out.println("------------------------------CREATING NEW SAVINGS PRODUCT + // system.out.println("------------------------------CREATING NEW SAVINGS + // PRODUCT // ---------------------------------------"); SavingsProductHelper savingsProductHelper = new SavingsProductHelper(); final String savingsProductJSON = savingsProductHelper // @@ -892,7 +895,8 @@ public class SchedulerJobsTestResults { } private Integer createSavingsProduct(final String minOpenningBalance, final Account... accounts) { - // system.out.println("------------------------------CREATING NEW SAVINGS PRODUCT + // system.out.println("------------------------------CREATING NEW SAVINGS + // PRODUCT // ---------------------------------------"); final String savingsProductJSON = new SavingsProductHelper().withInterestCompoundingPeriodTypeAsDaily() // .withInterestPostingPeriodTypeAsQuarterly() // @@ -958,7 +962,8 @@ public class SchedulerJobsTestResults { } private Integer createFixedDepositProduct(final String validFrom, final String validTo) { - // system.out.println("------------------------------CREATING NEW FIXED DEPOSIT PRODUCT + // system.out.println("------------------------------CREATING NEW FIXED DEPOSIT + // PRODUCT // ---------------------------------------"); FixedDepositProductHelper fixedDepositProductHelper = new FixedDepositProductHelper(requestSpec, responseSpec); final String fixedDepositProductJSON = fixedDepositProductHelper // @@ -970,7 +975,8 @@ public class SchedulerJobsTestResults { private Integer applyForFixedDepositApplication(final String clientID, final String productID, final String submittedOnDate, final String penalInterestType, String savingsId) { - // system.out.println("--------------------------------APPLYING FOR FIXED DEPOSIT ACCOUNT + // system.out.println("--------------------------------APPLYING FOR FIXED + // DEPOSIT ACCOUNT // --------------------------------"); final String fixedDepositApplicationJSON = new FixedDepositAccountHelper(requestSpec, responseSpec) .withSubmittedOnDate(submittedOnDate).withSavings(savingsId).transferInterest(true) diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/client/ClientEntityImportHandlerTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/client/ClientEntityImportHandlerTest.java index 3bbb957be..28f01a5b8 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/client/ClientEntityImportHandlerTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/client/ClientEntityImportHandlerTest.java @@ -31,6 +31,7 @@ import java.io.OutputStream; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Locale; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import org.apache.fineract.infrastructure.bulkimport.constants.ClientEntityConstants; @@ -105,7 +106,7 @@ public class ClientEntityImportHandlerTest { Sheet staffSheet = workbook.getSheet(TemplatePopulateImportConstants.STAFF_SHEET_NAME); firstClientRow.createCell(ClientEntityConstants.OFFICE_NAME_COL).setCellValue(staffSheet.getRow(1).getCell(0).getStringCellValue()); firstClientRow.createCell(ClientEntityConstants.STAFF_NAME_COL).setCellValue(staffSheet.getRow(1).getCell(1).getStringCellValue()); - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd MMMM yyyy"); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); Date incoporationDate = simpleDateFormat.parse("14 May 2001"); firstClientRow.createCell(ClientEntityConstants.INCOPORATION_DATE_COL).setCellValue(incoporationDate); Date validTill = simpleDateFormat.parse("14 May 2019"); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java index cd3a962aa..7ac2b98d8 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java @@ -36,6 +36,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; @@ -178,7 +179,7 @@ public class LoanImportHandlerTest { firstLoanRow.createCell(LoanConstants.CLIENT_EXTERNAL_ID).setCellValue(externalId); firstLoanRow.createCell(LoanConstants.PRODUCT_COL).setCellValue(loanProductJson.getString("name")); firstLoanRow.createCell(LoanConstants.LOAN_OFFICER_NAME_COL).setCellValue((String) staffMap.get("displayName")); - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd MMMM yyyy"); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); Date date = simpleDateFormat.parse("13 May 2017"); firstLoanRow.createCell(LoanConstants.SUBMITTED_ON_DATE_COL).setCellValue(date); firstLoanRow.createCell(LoanConstants.APPROVED_DATE_COL).setCellValue(date); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/office/OfficeImportHandlerTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/office/OfficeImportHandlerTest.java index 671e7d9db..e8cfd013b 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/office/OfficeImportHandlerTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/office/OfficeImportHandlerTest.java @@ -30,6 +30,7 @@ import java.io.OutputStream; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Locale; import org.apache.fineract.infrastructure.bulkimport.constants.OfficeConstants; import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants; import org.apache.fineract.integrationtests.common.OfficeHelper; @@ -72,7 +73,7 @@ public class OfficeImportHandlerTest { .setCellValue(firstOfficeRow.getCell(OfficeConstants.LOOKUP_OFFICE_COL).getStringCellValue()); firstOfficeRow.createCell(OfficeConstants.PARENT_OFFICE_ID_COL) .setCellValue(firstOfficeRow.getCell(OfficeConstants.LOOKUP_OFFICE_ID_COL).getNumericCellValue()); - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd MMMM yyyy"); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); Date date = simpleDateFormat.parse("14 May 2001"); firstOfficeRow.createCell(OfficeConstants.OPENED_ON_COL).setCellValue(date); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/savings/SavingsImportHandlerTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/savings/SavingsImportHandlerTest.java index c0391670f..95a28dea0 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/savings/SavingsImportHandlerTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/savings/SavingsImportHandlerTest.java @@ -33,6 +33,7 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; @@ -134,7 +135,7 @@ public class SavingsImportHandlerTest { firstSavingsRow.createCell(SavingsConstants.PRODUCT_COL) .setCellValue(savingsProductSheet.getRow(1).getCell(1).getStringCellValue()); firstSavingsRow.createCell(SavingsConstants.FIELD_OFFICER_NAME_COL).setCellValue((String) staffMap.get("displayName")); - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd MMMM yyyy"); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); Date date = simpleDateFormat.parse("13 May 2017"); firstSavingsRow.createCell(SavingsConstants.SUBMITTED_ON_DATE_COL).setCellValue(date); firstSavingsRow.createCell(SavingsConstants.APPROVED_DATE_COL).setCellValue(date); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ClientChargesTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ClientChargesTest.java index 89c769cd6..d92577abf 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ClientChargesTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ClientChargesTest.java @@ -26,6 +26,7 @@ import io.restassured.specification.ResponseSpecification; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; +import java.util.Locale; import org.apache.fineract.integrationtests.common.charges.ChargesHelper; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -102,7 +103,7 @@ public class ClientChargesTest { * Now pay client charge for 20 USD and ensure the outstanding amount is updated properly */ ResponseSpecification responseSpecFailure = new ResponseSpecBuilder().expectStatusCode(400).build(); - DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); dateFormat.setTimeZone(Utils.getTimeZoneOfTenant()); Calendar today = Calendar.getInstance(Utils.getTimeZoneOfTenant()); today.add(Calendar.DAY_OF_MONTH, 2); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ProvisioningIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ProvisioningIntegrationTest.java index d2ee8af26..b87f7d590 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ProvisioningIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ProvisioningIntegrationTest.java @@ -33,6 +33,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.integrationtests.common.accounting.Account; @@ -258,7 +259,7 @@ public class ProvisioningIntegrationTest { String date = (String) item.get("createdDate"); DateFormat formatter = new SimpleDateFormat("MMM dd, yyyy"); Date date1 = formatter.parse(date); - DateFormat simple = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat simple = new SimpleDateFormat("dd MMMM yyyy", Locale.US); String formattedString = simple .format(Date.from(Utils.getLocalDateOfTenant().atStartOfDay(DateUtils.getDateTimeZoneOfTenant()).toInstant())); Date currentDate = simple.parse(formattedString); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java index 3f40da00a..f45ddc6d7 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java @@ -124,6 +124,12 @@ public class LoanTransactionHelper { return (ArrayList) Utils.performServerGet(requestSpec, responseSpec, URL, "charges"); } + public ArrayList getLoanTransactions(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final Integer loanID) { + final String URL = "/fineract-provider/api/v1/loans/" + loanID + "?associations=transactions&" + Utils.TENANT_IDENTIFIER; + return (ArrayList) Utils.performServerGet(requestSpec, responseSpec, URL, "transactions"); + } + public ArrayList getLoanFutureRepaymentSchedule(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final Integer loanID) { final String URL = "/fineract-provider/api/v1/loans/" + loanID + "?associations=repaymentSchedule,futureSchedule&" @@ -133,7 +139,7 @@ public class LoanTransactionHelper { } public HashMap getLoanSummary(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final Integer loanID) { - final String URL = "/fineract-provider/api/v1/loans/" + loanID + "?associations=all&" + Utils.TENANT_IDENTIFIER; + final String URL = "/fineract-provider/api/v1/loans/" + loanID + "?" + Utils.TENANT_IDENTIFIER; final HashMap response = Utils.performServerGet(requestSpec, responseSpec, URL, "summary"); return response; } @@ -731,7 +737,7 @@ public class LoanTransactionHelper { public void checkAccrualTransactionForRepayment(final LocalDate transactionDate, final Float interestPortion, final Float feePortion, final Float penaltyPortion, final Integer loanID) { - ArrayList transactions = (ArrayList) getLoanDetail(this.requestSpec, this.responseSpec, loanID, "transactions"); + ArrayList transactions = (ArrayList) getLoanTransactions(this.requestSpec, this.responseSpec, loanID); boolean isTransactionFound = false; for (int i = 0; i < transactions.size(); i++) { HashMap transactionType = (HashMap) transactions.get(i).get("type"); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/provisioning/ProvisioningHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/provisioning/ProvisioningHelper.java index 931d0b2b6..fceb9fdef 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/provisioning/ProvisioningHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/provisioning/ProvisioningHelper.java @@ -26,6 +26,7 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.integrationtests.common.Utils; @@ -46,7 +47,7 @@ public final class ProvisioningHelper { final HashMap map = new HashMap<>(); map.put("loanProducts", addLoanProducts(loanProducts)); map.put("definitions", addProvisioningCategories(categories, liability, expense)); - DateFormat simple = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat simple = new SimpleDateFormat("dd MMMM yyyy", Locale.US); String formattedString = simple .format(Date.from(Utils.getLocalDateOfTenant().atStartOfDay(DateUtils.getDateTimeZoneOfTenant()).toInstant())); @@ -61,7 +62,7 @@ public final class ProvisioningHelper { map.put("createjournalentries", Boolean.FALSE); map.put("locale", "en"); map.put("dateFormat", "dd MMMM yyyy"); - DateFormat simple = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat simple = new SimpleDateFormat("dd MMMM yyyy", Locale.US); map.put("date", simple.format(Date.from(Utils.getLocalDateOfTenant().atStartOfDay(DateUtils.getDateTimeZoneOfTenant()).toInstant()))); String provisioningEntryCreateJson = new Gson().toJson(map); @@ -73,7 +74,7 @@ public final class ProvisioningHelper { map.put("createjournalentries", Boolean.TRUE); map.put("locale", "en"); map.put("dateFormat", "dd MMMM yyyy"); - DateFormat simple = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat simple = new SimpleDateFormat("dd MMMM yyyy", Locale.US); map.put("date", simple.format(Date.from(Utils.getLocalDateOfTenant().atStartOfDay(DateUtils.getDateTimeZoneOfTenant()).toInstant()))); String provisioningEntryCreateJson = new Gson().toJson(map); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/shares/ShareAccountIntegrationTests.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/shares/ShareAccountIntegrationTests.java index 6291292ec..d8e7fcc4c 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/shares/ShareAccountIntegrationTests.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/shares/ShareAccountIntegrationTests.java @@ -250,12 +250,8 @@ public class ShareAccountIntegrationTests { Assertions.assertEquals("shareAccountStatusType.rejected", String.valueOf(statusMap.get("code"))); Map timelineMap = (Map) shareAccountData.get("timeline"); List dateList = (List) timelineMap.get("rejectedDate"); - Calendar cal = Calendar.getInstance(); - cal.set(dateList.get(0), dateList.get(1) - 1, dateList.get(2)); - Date rejectedDate = cal.getTime(); - Assertions.assertEquals( - simple.format(Date.from(Utils.getLocalDateOfTenant().atStartOfDay(DateUtils.getDateTimeZoneOfTenant()).toInstant())), - simple.format(rejectedDate)); + Date rejectedDate = DateUtils.createDate(dateList.get(0), dateList.get(1), dateList.get(2)); + Assertions.assertEquals(simple.format(DateUtils.convertLocalDateToDate(Utils.getLocalDateOfTenant())), simple.format(rejectedDate)); List> transactions = (List>) shareAccountData.get("purchasedShares"); Assertions.assertNotNull(transactions); @@ -264,9 +260,7 @@ public class ShareAccountIntegrationTests { Map transaction = transactions.get(i); Map transactionTypeMap = (Map) transaction.get("type"); dateList = (List) transaction.get("purchasedDate"); - cal = Calendar.getInstance(); - cal.set(dateList.get(0), dateList.get(1) - 1, dateList.get(2)); - Date date = cal.getTime(); + Date date = DateUtils.createDate(dateList.get(0), dateList.get(1), dateList.get(2)); String transactionType = (String) transactionTypeMap.get("code"); if (transactionType.equals("purchasedSharesType.purchased")) { Assertions.assertEquals("25", String.valueOf(transaction.get("numberOfShares"))); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/shares/ShareProductHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/shares/ShareProductHelper.java index 659fb6a05..97913bea4 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/shares/ShareProductHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/shares/ShareProductHelper.java @@ -25,6 +25,7 @@ import java.time.LocalDate; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.integrationtests.common.Utils; @@ -107,7 +108,7 @@ public class ShareProductHelper { this.marketPrices = new ArrayList<>(); LocalDate currentDate = DateUtils.getLocalDateOfTenant(); String[] prices = { "3.0", "4.0", "5.0", "6.0", "7.0" }; - DateFormat simple = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat simple = new SimpleDateFormat("dd MMMM yyyy", Locale.US); for (int i = 0; i < prices.length; i++) { currentDate = currentDate.plusMonths(2); Map marketPrice = new HashMap<>(); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsDecliningBalanceHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsDecliningBalanceHelper.java index ba813b69f..4362e59e3 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsDecliningBalanceHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsDecliningBalanceHelper.java @@ -26,6 +26,7 @@ import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import org.apache.fineract.integrationtests.common.accounting.Account; import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; @@ -297,7 +298,7 @@ public class VariableInstallmentsDecliningBalanceHelper { cal.set(Calendar.MONTH, (int) list.get(1) - 1); cal.set(Calendar.DAY_OF_MONTH, (int) list.get(2)); Date date = cal.getTime(); - DateFormat requiredFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat requiredFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); return requiredFormat.format(date); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsFlatHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsFlatHelper.java index 3d9b3b65a..6c9c1dc3b 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsFlatHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsFlatHelper.java @@ -26,6 +26,7 @@ import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import org.apache.fineract.integrationtests.common.accounting.Account; import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; @@ -208,7 +209,7 @@ public class VariableInstallmentsFlatHelper { cal.set(Calendar.MONTH, (int) list.get(1) - 1); cal.set(Calendar.DAY_OF_MONTH, (int) list.get(2)); Date date = cal.getTime(); - DateFormat requiredFormat = new SimpleDateFormat("dd MMMM yyyy"); + DateFormat requiredFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); return requiredFormat.format(date); }