FINERACT-1946: Change the loan transaction ordering

This commit is contained in:
Adam Saghy
2023-07-25 14:46:08 +02:00
parent b66a0a012f
commit d11ca18cb2
23 changed files with 6796 additions and 6395 deletions
@@ -143,7 +143,7 @@ public class CommandSource extends AbstractPersistableCustom {
this.subResourceId = subResourceId;
this.commandAsJson = commandSerializedAsJson;
this.maker = maker;
this.madeOnDate = DateUtils.getOffsetDateTimeOfTenant();
this.madeOnDate = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
this.status = status;
this.idempotencyKey = idempotencyKey;
}
@@ -170,13 +170,13 @@ public class CommandSource extends AbstractPersistableCustom {
public void markAsChecked(final AppUser checker) {
this.checker = checker;
this.checkedOnDate = DateUtils.getOffsetDateTimeOfTenant();
this.checkedOnDate = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
this.status = CommandProcessingResultType.PROCESSED.getValue();
}
public void markAsRejected(final AppUser checker) {
this.checker = checker;
this.checkedOnDate = DateUtils.getOffsetDateTimeOfTenant();
this.checkedOnDate = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
this.status = CommandProcessingResultType.REJECTED.getValue();
}
@@ -32,4 +32,5 @@
<include relativeToChangelogFile="true" file="parts/0008_add_mappings.xml"/>
<include relativeToChangelogFile="true" file="parts/0009_add_loan_ownership_transfer_events.xml"/>
<include relativeToChangelogFile="true" file="parts/0010_external_transafer_status_external_transfer_id_constraints.xml"/>
<include relativeToChangelogFile="true" file="parts/0011_set_datetime_precision.xml"/>
</databaseChangeLog>
@@ -22,7 +22,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
<changeSet author="fineract" id="1">
<changeSet author="fineract" id="1" context="mysql">
<addUniqueConstraint tableName="m_external_asset_owner_transfer" columnNames="status, external_id" constraintName="external_transfer_status_external_id"/>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
<changeSet author="fineract" id="1" context="mysql">
<modifyDataType tableName="m_external_asset_owner" columnName="created_on_utc" newDataType="datetime(6)"/>
<modifyDataType tableName="m_external_asset_owner" columnName="last_modified_on_utc" newDataType="datetime(6)"/>
<modifyDataType tableName="m_external_asset_owner_journal_entry_mapping" columnName="created_on_utc" newDataType="datetime(6)"/>
<modifyDataType tableName="m_external_asset_owner_journal_entry_mapping" columnName="last_modified_on_utc" newDataType="datetime(6)"/>
<modifyDataType tableName="m_external_asset_owner_transfer" columnName="created_on_utc" newDataType="datetime(6)"/>
<modifyDataType tableName="m_external_asset_owner_transfer" columnName="last_modified_on_utc" newDataType="datetime(6)"/>
<modifyDataType tableName="m_external_asset_owner_transfer_details" columnName="created_on_utc" newDataType="datetime(6)"/>
<modifyDataType tableName="m_external_asset_owner_transfer_details" columnName="last_modified_on_utc" newDataType="datetime(6)"/>
<modifyDataType tableName="m_external_asset_owner_transfer_journal_entry_mapping" columnName="created_on_utc" newDataType="datetime(6)"/>
<modifyDataType tableName="m_external_asset_owner_transfer_journal_entry_mapping" columnName="last_modified_on_utc" newDataType="datetime(6)"/>
<modifyDataType tableName="m_external_asset_owner_transfer_loan_mapping" columnName="created_on_utc" newDataType="datetime(6)"/>
<modifyDataType tableName="m_external_asset_owner_transfer_loan_mapping" columnName="last_modified_on_utc" newDataType="datetime(6)"/>
</changeSet>
</databaseChangeLog>
@@ -345,7 +345,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = true, fetch = FetchType.LAZY)
private List<LoanRepaymentScheduleInstallment> repaymentScheduleInstallments = new ArrayList<>();
@OrderBy(value = "dateOf, id")
@OrderBy(value = "dateOf, createdDate, id")
@OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = true, fetch = FetchType.LAZY)
private List<LoanTransaction> loanTransactions = new ArrayList<>();
@@ -841,7 +841,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
}
public OffsetDateTime getCreatedDateTime() {
return (this.getCreatedDate().isPresent() ? this.getCreatedDate().get() : DateUtils.getOffsetDateTimeOfTenant());
return (this.getCreatedDate().isPresent() ? this.getCreatedDate().get() : DateUtils.getOffsetDateTimeOfTenantWithMostPrecision());
}
public boolean isLastTransaction(final LoanTransaction loanTransaction) {
@@ -175,7 +175,8 @@ public class JournalEntryRunningBalanceUpdateServiceImpl implements JournalEntry
BigDecimal runningBalance = calculateRunningBalance(entryData, runningBalanceMap);
params.add(new Object[] { Boolean.TRUE, runningBalance, officeRunningBalance,
platformSecurityContext.authenticatedUser().getId(), DateUtils.getOffsetDateTimeOfTenant(), entryData.getId() });
platformSecurityContext.authenticatedUser().getId(), DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(),
entryData.getId() });
batchIndex++;
if (batchIndex == batchUpdateSize || index == entryDataList.size() - 1) {
this.jdbcTemplate.batchUpdate(sql, params);
@@ -212,7 +213,7 @@ public class JournalEntryRunningBalanceUpdateServiceImpl implements JournalEntry
for (JournalEntryData entryData : entryDataList) {
BigDecimal runningBalance = calculateRunningBalance(entryData, runningBalanceMap);
params.add(new Object[] { runningBalance, platformSecurityContext.authenticatedUser().getId(),
DateUtils.getOffsetDateTimeOfTenant(), entryData.getId() });
DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(), entryData.getId() });
}
this.jdbcTemplate.batchUpdate(sql, params);
}
@@ -64,7 +64,7 @@ public class LoanAccountLock {
public LoanAccountLock(Long loanId, LockOwner lockOwner, LocalDate lockPlacedOnCobBusinessDate) {
this.loanId = loanId;
this.lockOwner = lockOwner;
this.lockPlacedOn = DateUtils.getOffsetDateTimeOfTenant();
this.lockPlacedOn = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
this.lockPlacedOnCobBusinessDate = lockPlacedOnCobBusinessDate;
}
@@ -75,6 +75,6 @@ public class LoanAccountLock {
public void setNewLockOwner(LockOwner newLockOwner) {
this.lockOwner = newLockOwner;
this.lockPlacedOn = DateUtils.getOffsetDateTimeOfTenant();
this.lockPlacedOn = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
}
}
@@ -67,7 +67,7 @@ public class LoanLockingServiceImpl implements LoanLockingService {
UPDATE m_loan_account_locks SET version= version + 1, lock_owner = ?, lock_placed_on = ? WHERE loan_id = ?
""", accountsToLock, getInClauseParameterSizeLimit(), (ps, id) -> {
ps.setString(1, lockOwner.name());
ps.setObject(2, DateUtils.getOffsetDateTimeOfTenant());
ps.setObject(2, DateUtils.getOffsetDateTimeOfTenantWithMostPrecision());
ps.setLong(3, id);
});
}
@@ -97,7 +97,7 @@ public class LoanLockingServiceImpl implements LoanLockingService {
ps.setLong(1, loanId);
ps.setLong(2, 1);
ps.setString(3, lockOwner.name());
ps.setObject(4, DateUtils.getOffsetDateTimeOfTenant());
ps.setObject(4, DateUtils.getOffsetDateTimeOfTenantWithMostPrecision());
ps.setObject(5, cobBusinessDate);
});
}
@@ -63,7 +63,7 @@ public class UpdateNpaTasklet implements Tasklet {
resetNPASqlBuilder.append("set is_npa = false").append(", last_modified_by = ?, last_modified_on_utc = ? ").append(" FROM ")
.append(fromPart).append(wherePart);
}
jdbcTemplate.update(resetNPASqlBuilder.toString(), user.getId(), DateUtils.getOffsetDateTimeOfTenant());
jdbcTemplate.update(resetNPASqlBuilder.toString(), user.getId(), DateUtils.getOffsetDateTimeOfTenantWithMostPrecision());
final StringBuilder updateSqlBuilder = new StringBuilder(900);
@@ -82,7 +82,8 @@ public class UpdateNpaTasklet implements Tasklet {
.append(fromPart).append(wherePart);
}
final int result = jdbcTemplate.update(updateSqlBuilder.toString(), user.getId(), DateUtils.getOffsetDateTimeOfTenant());
final int result = jdbcTemplate.update(updateSqlBuilder.toString(), user.getId(),
DateUtils.getOffsetDateTimeOfTenantWithMostPrecision());
log.debug("{}: Records affected by updateNPA: {}", ThreadLocalContextUtil.getTenant().getName(), result);
return RepeatStatus.FINISHED;
@@ -73,7 +73,7 @@ public class LoanScheduleHistoryWritePlatformServiceImpl implements LoanSchedule
final BigDecimal penaltyCharges = repaymentScheduleInstallment.getPenaltyChargesCharged(currency).getAmount();
Map<String, Object> oldDates = null;
OffsetDateTime createdOnDate = DateUtils.getOffsetDateTimeOfTenant();
OffsetDateTime createdOnDate = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
LocalDateTime oldCreatedOnDate = null;
LocalDateTime oldLastModifiedOnDate = null;
if (repaymentScheduleInstallment.getCreatedDate().isPresent()) {
@@ -89,7 +89,7 @@ public class LoanScheduleHistoryWritePlatformServiceImpl implements LoanSchedule
final Long lastModifiedByUser = repaymentScheduleInstallment.getLastModifiedBy()
.orElse(platformSecurityContext.authenticatedUser().getId());
OffsetDateTime lastModifiedOnDate = DateUtils.getOffsetDateTimeOfTenant();
OffsetDateTime lastModifiedOnDate = DateUtils.getOffsetDateTimeOfTenantWithMostPrecision();
if (repaymentScheduleInstallment.getLastModifiedDate().isPresent()) {
lastModifiedOnDate = repaymentScheduleInstallment.getLastModifiedDate().get();
} else if (repaymentScheduleInstallment.getId() != null && oldDates == null) {
@@ -318,7 +318,7 @@ public final class LoanApplicationCommandFromApiJsonHelper {
baseDataValidator.reset().parameter(LoanApiConstants.amortizationTypeParameterName).value(amortizationType).notNull()
.inMinMaxRange(0, 1);
if (!amortizationType.equals(AmortizationMethod.EQUAL_PRINCIPAL.getValue()) && fixedPrincipalPercentagePerInstallment != null) {
if (!AmortizationMethod.EQUAL_PRINCIPAL.getValue().equals(amortizationType) && fixedPrincipalPercentagePerInstallment != null) {
baseDataValidator.reset().parameter(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName).failWithCode(
"not.supported.principal.fixing.not.allowed.with.equal.installments",
"Principal fixing cannot be done with equal installment amortization");
@@ -271,7 +271,7 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
this.jdbcTemplate.update(transactionSql, scheduleAccrualData.getLoanId(), scheduleAccrualData.getOfficeId(),
externalIdFactory.create().getValue(), LoanTransactionType.ACCRUAL.getValue(), accruedTill, amount, interestPortion,
feePortion, penaltyPortion, DateUtils.getBusinessLocalDate(), user.getId(), user.getId(),
DateUtils.getOffsetDateTimeOfTenant(), DateUtils.getOffsetDateTimeOfTenant());
DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(), DateUtils.getOffsetDateTimeOfTenantWithMostPrecision());
final Long transactionId = this.jdbcTemplate.queryForObject("SELECT " + sqlGenerator.lastInsertId(), Long.class); // NOSONAR
Map<LoanChargeData, BigDecimal> applicableCharges = scheduleAccrualData.getApplicableCharges();
@@ -291,7 +291,7 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
scheduleAccrualData.getRepaymentScheduleId());
String updateLoan = "UPDATE m_loan SET accrued_till=?, last_modified_by=?, last_modified_on_utc=? WHERE id=?";
this.jdbcTemplate.update(updateLoan, accruedTill, user.getId(), DateUtils.getOffsetDateTimeOfTenant(),
this.jdbcTemplate.update(updateLoan, accruedTill, user.getId(), DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(),
scheduleAccrualData.getLoanId());
Optional<LoanTransaction> loanAccrualTransaction = loanTransactionRepository.findByIdAndLoanId(transactionId,
@@ -280,7 +280,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
* TODO Vishwas: Remove references to "Contra" from the codebase
***/
final String sql = "select " + rm.loanPaymentsSchema() + " where tr.loan_id = ? and tr.transaction_type_enum not in (0, 3) "
+ " and (tr.is_reversed=false or tr.manually_adjusted_or_reversed = true) order by tr.transaction_date ASC,id ";
+ " and (tr.is_reversed=false or tr.manually_adjusted_or_reversed = true) order by tr.transaction_date, tr.created_on_utc, tr.id ";
Collection<LoanTransactionData> loanTransactionData = this.jdbcTemplate.query(sql, rm, loanId); // NOSONAR
// TODO: would worth to rework in the future. It is not nice to fetch relations one by one... might worth to
// give a try to get rid of native queries
@@ -2140,7 +2140,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
final LoanTransactionDerivedComponentMapper rm = new LoanTransactionDerivedComponentMapper(sqlGenerator);
final String sql = "select " + rm.schema()
+ " where tr.loan_id = ? and tr.transaction_type_enum = ? and tr.is_reversed=false order by tr.transaction_date ASC,id ";
+ " where tr.loan_id = ? and tr.transaction_type_enum = ? and tr.is_reversed=false order by tr.transaction_date, tr.created_on_utc, tr.id ";
return this.jdbcTemplate.query(sql, rm, loanId, LoanTransactionType.WAIVE_INTEREST.getValue()); // NOSONAR
} catch (final EmptyResultDataAccessException e) {
return null;
@@ -493,8 +493,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
AppUser user = context.authenticatedUser();
jdbcTemplate.update(transactionSql, loanId, loan.getOfficeId(), externalIdFactory.create().getValue(),
LoanTransactionType.ACCRUAL.getValue(), actualDisbursementDate, loanCharge.amount(), loanCharge.amount(),
DateUtils.getBusinessLocalDate(), user.getId(), user.getId(), DateUtils.getOffsetDateTimeOfTenant(),
DateUtils.getOffsetDateTimeOfTenant());
DateUtils.getBusinessLocalDate(), user.getId(), user.getId(),
DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(), DateUtils.getOffsetDateTimeOfTenantWithMostPrecision());
}
}
@@ -120,8 +120,8 @@ public class SavingsSchedularInterestPoster {
savingsAccountTransactionData.getId(), null, false, null, false,
savingsAccountTransactionData.getTransactionDate(), JournalEntryType.CREDIT.getValue().longValue(),
savingsAccountTransactionData.getAmount(), null, JournalEntryType.CREDIT.getValue().longValue(),
savingsAccountData.getId(), DateUtils.getOffsetDateTimeOfTenant(),
DateUtils.getOffsetDateTimeOfTenant(), false, BigDecimal.ZERO, BigDecimal.ZERO, null,
savingsAccountData.getId(), DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(),
DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(), false, BigDecimal.ZERO, BigDecimal.ZERO, null,
savingsAccountTransactionData.getTransactionDate(), null, userId, userId,
DateUtils.getBusinessLocalDate() });
@@ -131,8 +131,8 @@ public class SavingsSchedularInterestPoster {
savingsAccountTransactionData.getId(), null, false, null, false,
savingsAccountTransactionData.getTransactionDate(), JournalEntryType.DEBIT.getValue().longValue(),
savingsAccountTransactionData.getAmount(), null, JournalEntryType.DEBIT.getValue().longValue(),
savingsAccountData.getId(), DateUtils.getOffsetDateTimeOfTenant(),
DateUtils.getOffsetDateTimeOfTenant(), false, BigDecimal.ZERO, BigDecimal.ZERO, null,
savingsAccountData.getId(), DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(),
DateUtils.getOffsetDateTimeOfTenantWithMostPrecision(), false, BigDecimal.ZERO, BigDecimal.ZERO, null,
savingsAccountTransactionData.getTransactionDate(), null, userId, userId,
DateUtils.getBusinessLocalDate() });
}
@@ -30,4 +30,5 @@
<include file="parts/0007_x_extend_tenant_ro_passwords.xml" relativeToChangelogFile="true"/>
<include file="parts/0008_encrypt_existing_ro_tenant_passwords.xml" relativeToChangelogFile="true"/>
<include file="parts/0009_set_and_encrypt_ro_if_not_exists.xml" relativeToChangelogFile="true"/>
<include file="parts/0010_set_datetime_precision.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
<changeSet author="fineract" id="1" context="tenant_store_db">
<modifyDataType tableName="tenants" columnName="created_date" newDataType="datetime(6)"/>
<modifyDataType tableName="tenants" columnName="lastmodified_date" newDataType="datetime(6)"/>
</changeSet>
</databaseChangeLog>
@@ -136,4 +136,5 @@
<include file="parts/0114_create_cob_indices.xml" relativeToChangelogFile="true" />
<include file="parts/0115_create_index_from_loan_transaction_id.xml" relativeToChangelogFile="true" />
<include file="parts/0116_add_configuration_asset_externalization_of_non_active_loans.xml" relativeToChangelogFile="true" />
<include file="parts/0117_set_datetime_precision.xml" relativeToChangelogFile="true" />
</databaseChangeLog>
@@ -0,0 +1,152 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
<changeSet author="fineract" id="1" context="mysql">
<modifyDataType tableName="acc_gl_closure" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="acc_gl_closure" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="acc_gl_journal_entry" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="acc_gl_journal_entry" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="acc_gl_journal_entry" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="acc_gl_journal_entry" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="client_device_registration" columnName="updatedon_date" newDataType="datetime(6)" />
<modifyDataType tableName="interop_identifier" columnName="created_on" newDataType="timestamp(6)" />
<modifyDataType tableName="interop_identifier" columnName="modified_on" newDataType="timestamp(6)" />
<modifyDataType tableName="job" columnName="create_time" newDataType="datetime(6)" />
<modifyDataType tableName="job" columnName="previous_run_start_time" newDataType="datetime(6)" />
<modifyDataType tableName="job" columnName="next_run_time" newDataType="datetime(6)" />
<modifyDataType tableName="job_run_history" columnName="start_time" newDataType="datetime(6)" />
<modifyDataType tableName="job_run_history" columnName="end_time" newDataType="datetime(6)" />
<modifyDataType tableName="m_account_transfer_standing_instructions_history" columnName="execution_time" newDataType="datetime(6)" />
<modifyDataType tableName="m_adhoc" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_adhoc" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_adhoc" columnName="last_run" newDataType="timestamp(6)" />
<modifyDataType tableName="m_business_date" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_business_date" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_business_date" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_business_date" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_calendar" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_calendar" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_calendar" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_calendar" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_cashier_transactions" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_client" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_client" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_client_identifier" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_client_identifier" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_client_identifier" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_client_identifier" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_client_transaction" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_client_transaction" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_client_transaction" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_delinquency_bucket" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_delinquency_bucket" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_delinquency_bucket_mappings" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_delinquency_bucket_mappings" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_delinquency_range" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_delinquency_range" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_deposit_account_on_hold_transaction" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_floating_rates" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_floating_rates" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_floating_rates" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_floating_rates" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_floating_rates_periods" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_floating_rates_periods" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_floating_rates_periods" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_floating_rates_periods" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_hook" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_hook" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_import_document" columnName="import_time" newDataType="datetime(6)" />
<modifyDataType tableName="m_import_document" columnName="end_time" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_account_locks" columnName="lock_placed_on" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_delinquency_tag_history" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_delinquency_tag_history" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_officer_assignment_history" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_officer_assignment_history" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_repayment_schedule" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_repayment_schedule" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_repayment_schedule" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_repayment_schedule" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_repayment_schedule_history" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_repayment_schedule_history" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_repayment_schedule_history" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_repayment_schedule_history" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_transaction" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_transaction" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_transaction" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_transaction_relation" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_loan_transaction_relation" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_mandatory_savings_schedule" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_mandatory_savings_schedule" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_note" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_note" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_note" columnName="created_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_note" columnName="last_modified_on_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_portfolio_command_source" columnName="made_on_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_portfolio_command_source" columnName="checked_on_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_portfolio_command_source" columnName="made_on_date_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_portfolio_command_source" columnName="checked_on_date_utc" newDataType="datetime(6)" />
<modifyDataType tableName="m_provisioning_criteria" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_provisioning_criteria" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_rate" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_rate" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_report_mailing_job" columnName="start_datetime" newDataType="datetime(6)" />
<modifyDataType tableName="m_report_mailing_job" columnName="previous_run_datetime" newDataType="datetime(6)" />
<modifyDataType tableName="m_report_mailing_job" columnName="next_run_datetime" newDataType="datetime(6)" />
<modifyDataType tableName="m_report_mailing_job_run_history" columnName="start_datetime" newDataType="datetime(6)" />
<modifyDataType tableName="m_report_mailing_job_run_history" columnName="end_datetime" newDataType="datetime(6)" />
<modifyDataType tableName="m_savings_officer_assignment_history" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_savings_officer_assignment_history" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_share_account" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_share_account" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_share_product" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_share_product" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_share_product_dividend_pay_out" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_share_product_dividend_pay_out" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_staff_assignment_history" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_staff_assignment_history" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_survey_scorecards" columnName="created_on" newDataType="datetime(6)" />
<modifyDataType tableName="m_tax_component" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_tax_component" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_tax_component_history" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_tax_component_history" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_tax_group" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_tax_group" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_tax_group_mappings" columnName="created_date" newDataType="datetime(6)" />
<modifyDataType tableName="m_tax_group_mappings" columnName="lastmodified_date" newDataType="datetime(6)" />
<modifyDataType tableName="mix_taxonomy_mapping" columnName="last_update_date" newDataType="datetime(6)" />
<modifyDataType tableName="notification_generator" columnName="created_at" newDataType="datetime(6)" />
<modifyDataType tableName="notification_mapper" columnName="created_at" newDataType="datetime(6)" />
<modifyDataType tableName="scheduled_email_campaign" columnName="next_trigger_date" newDataType="datetime(6)" />
<modifyDataType tableName="scheduled_email_campaign" columnName="last_trigger_date" newDataType="datetime(6)" />
<modifyDataType tableName="scheduled_email_campaign" columnName="recurrence_start_date" newDataType="datetime(6)" />
<modifyDataType tableName="sms_campaign" columnName="next_trigger_date" newDataType="datetime(6)" />
<modifyDataType tableName="sms_campaign" columnName="last_trigger_date" newDataType="datetime(6)" />
<modifyDataType tableName="sms_campaign" columnName="recurrence_start_date" newDataType="datetime(6)" />
<modifyDataType tableName="sms_messages_outbound" columnName="delivered_on_date" newDataType="datetime(6)" />
<modifyDataType tableName="twofactor_access_token" columnName="valid_from" newDataType="datetime(6)" />
<modifyDataType tableName="twofactor_access_token" columnName="valid_to" newDataType="datetime(6)" />
</changeSet>
</databaseChangeLog>
@@ -56,7 +56,6 @@ import org.apache.fineract.client.models.JournalEntryTransactionItem;
import org.apache.fineract.client.models.PostClientsResponse;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
import org.apache.fineract.client.models.PutJobsJobIDRequest;
import org.apache.fineract.client.util.CallFailedRuntimeException;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
import org.apache.fineract.integrationtests.common.ClientHelper;
@@ -656,62 +655,68 @@ public class SchedulerJobsTestResults {
@Test
public void testLoanCOBJobOutcome() {
this.savingsAccountHelper = new SavingsAccountHelper(requestSpec, responseSpec);
this.loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec);
try {
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE);
this.savingsAccountHelper = new SavingsAccountHelper(requestSpec, responseSpec);
this.loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec);
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec);
Assertions.assertNotNull(clientID);
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec);
Assertions.assertNotNull(clientID);
Integer overdueFeeChargeId = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanOverdueFeeJSONWithCalculationTypePercentage("1"));
Assertions.assertNotNull(overdueFeeChargeId);
Integer overdueFeeChargeId = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanOverdueFeeJSONWithCalculationTypePercentage("1"));
Assertions.assertNotNull(overdueFeeChargeId);
Integer fee = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "10", false));
Assertions.assertNotNull(fee);
Integer fee = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "10", false));
Assertions.assertNotNull(fee);
final Integer loanProductID = createLoanProduct(overdueFeeChargeId.toString());
Assertions.assertNotNull(loanProductID);
List<Integer> loanIDs = new ArrayList<>();
HashMap loanStatusHashMap;
for (int i = 0; i < 3; i++) {
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), null, "10 January 2020");
final Integer loanProductID = createLoanProduct(overdueFeeChargeId.toString());
Assertions.assertNotNull(loanProductID);
List<Integer> loanIDs = new ArrayList<>();
HashMap loanStatusHashMap;
for (int i = 0; i < 3; i++) {
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), null, "10 January 2020");
Assertions.assertNotNull(loanID);
Assertions.assertNotNull(loanID);
loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
loanStatusHashMap = this.loanTransactionHelper.approveLoan("01 March 2020", loanID);
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
loanStatusHashMap = this.loanTransactionHelper.approveLoan("01 March 2020", loanID);
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
String loanDetails = this.loanTransactionHelper.getLoanDetails(requestSpec, responseSpec, loanID);
loanStatusHashMap = this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount("02 March 2020", loanID,
JsonPath.from(loanDetails).get("netDisbursalAmount").toString());
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
loanIDs.add(loanID);
String loanDetails = this.loanTransactionHelper.getLoanDetails(requestSpec, responseSpec, loanID);
loanStatusHashMap = this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount("02 March 2020", loanID,
JsonPath.from(loanDetails).get("netDisbursalAmount").toString());
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
loanIDs.add(loanID);
this.loanTransactionHelper.addChargesForLoan(loanID,
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(fee), "02 March 2020", "10", null));
}
this.loanTransactionHelper.addChargesForLoan(loanID,
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(fee), "02 March 2020", "10", null));
}
String jobName = "Loan COB";
this.schedulerJobHelper.executeAndAwaitJob(jobName);
for (Integer loanId : loanIDs) {
List<HashMap> repaymentScheduleDataAfter = this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec,
loanId);
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.COB_DATE, LocalDate.of(2020, 9, 2));
String jobName = "Loan COB";
this.schedulerJobHelper.executeAndAwaitJob(jobName);
for (Integer loanId : loanIDs) {
List<HashMap> repaymentScheduleDataAfter = this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec,
loanId);
Assertions.assertEquals(10.00f, (Float) repaymentScheduleDataAfter.get(1).get("feeChargesDue"),
"Verifying From Fee Charges due for first Repayment after Successful completion of Scheduler Job");
Assertions.assertEquals(39.39f, (Float) repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
"Verifying From Penalty Charges due for first Repayment after Successful completion of Scheduler Job");
Assertions.assertEquals(39.39f, (Float) repaymentScheduleDataAfter.get(2).get("penaltyChargesDue"),
"Verifying From Penalty Charges due for first Repayment after Successful completion of Scheduler Job");
Assertions.assertEquals(39.39f, (Float) repaymentScheduleDataAfter.get(3).get("penaltyChargesDue"),
"Verifying From Penalty Charges due for first Repayment after Successful completion of Scheduler Job");
Assertions.assertEquals(39.39f, (Float) repaymentScheduleDataAfter.get(4).get("penaltyChargesDue"),
"Verifying From Penalty Charges due for first Repayment after Successful completion of Scheduler Job");
Assertions.assertEquals(10.00f, (Float) repaymentScheduleDataAfter.get(1).get("feeChargesDue"),
"Verifying From Fee Charges due for first Repayment after Successful completion of Scheduler Job");
Assertions.assertEquals(39.39f, (Float) repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
"Verifying From Penalty Charges due for first Repayment after Successful completion of Scheduler Job");
Assertions.assertEquals(39.39f, (Float) repaymentScheduleDataAfter.get(2).get("penaltyChargesDue"),
"Verifying From Penalty Charges due for first Repayment after Successful completion of Scheduler Job");
Assertions.assertEquals(39.39f, (Float) repaymentScheduleDataAfter.get(3).get("penaltyChargesDue"),
"Verifying From Penalty Charges due for first Repayment after Successful completion of Scheduler Job");
Assertions.assertEquals(39.39f, (Float) repaymentScheduleDataAfter.get(4).get("penaltyChargesDue"),
"Verifying From Penalty Charges due for first Repayment after Successful completion of Scheduler Job");
}
} finally {
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.FALSE);
}
}
@@ -720,7 +725,7 @@ public class SchedulerJobsTestResults {
try {
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE);
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.COB_DATE, LocalDate.of(2020, 3, 2));
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.COB_DATE, LocalDate.of(2020, 6, 2));
this.savingsAccountHelper = new SavingsAccountHelper(requestSpec, responseSpec);
this.loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec);
@@ -741,16 +746,16 @@ public class SchedulerJobsTestResults {
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
loanStatusHashMap = this.loanTransactionHelper.approveLoan("01 March 2020", loanID);
loanStatusHashMap = this.loanTransactionHelper.approveLoan("01 June 2020", loanID);
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
String loanDetails = this.loanTransactionHelper.getLoanDetails(requestSpec, responseSpec, loanID);
loanStatusHashMap = this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount("02 March 2020", loanID,
loanStatusHashMap = this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount("02 June 2020", loanID,
JsonPath.from(loanDetails).get("netDisbursalAmount").toString());
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
this.loanTransactionHelper.addChargesForLoan(loanID,
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(fee), "02 March 2020", "10", null));
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(fee), "02 June 2020", "10", null));
String jobName = "Loan COB";
this.schedulerJobHelper.executeAndAwaitJob(jobName);
@@ -765,7 +770,7 @@ public class SchedulerJobsTestResults {
// First accrual transaction
assertTrue(getLoansLoanIdResponse.getTransactions().get(1).getType().getAccrual());
assertEquals(10.0f, getLoansLoanIdResponse.getTransactions().get(1).getFeeChargesPortion());
assertEquals(LocalDate.of(2020, 3, 2), getLoansLoanIdResponse.getTransactions().get(1).getDate());
assertEquals(LocalDate.of(2020, 6, 2), getLoansLoanIdResponse.getTransactions().get(1).getDate());
Long transactionId = getLoansLoanIdResponse.getTransactions().get(1).getId();
final GetJournalEntriesTransactionIdResponse journalEntriesResponse = journalEntryHelper.getJournalEntries("L" + transactionId);
@@ -774,8 +779,8 @@ public class SchedulerJobsTestResults {
assertEquals(2, journalEntries.size());
assertEquals(10, journalEntries.get(0).getAmount());
assertEquals(10, journalEntries.get(1).getAmount());
assertEquals(LocalDate.of(2020, 3, 2), journalEntries.get(1).getTransactionDate());
assertEquals(LocalDate.of(2020, 3, 2), journalEntries.get(0).getTransactionDate());
assertEquals(LocalDate.of(2020, 6, 2), journalEntries.get(1).getTransactionDate());
assertEquals(LocalDate.of(2020, 6, 2), journalEntries.get(0).getTransactionDate());
} finally {
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.FALSE);
}
@@ -806,31 +811,31 @@ public class SchedulerJobsTestResults {
loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
loanStatusHashMap = loanTransactionHelper.approveLoan("01 March 2020", loanID);
loanStatusHashMap = loanTransactionHelper.approveLoan("01 July 2020", loanID);
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
String loanDetails = loanTransactionHelper.getLoanDetails(requestSpec, responseSpec, loanID);
loanStatusHashMap = loanTransactionHelper.disburseLoanWithNetDisbursalAmount("02 March 2020", loanID,
loanStatusHashMap = loanTransactionHelper.disburseLoanWithNetDisbursalAmount("02 July 2020", loanID,
JsonPath.from(loanDetails).get("netDisbursalAmount").toString());
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.COB_DATE, LocalDate.of(2020, 3, 2));
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.COB_DATE, LocalDate.of(2020, 7, 2));
String jobName = "Loan COB";
schedulerJobHelper.executeAndAwaitJob(jobName);
GetLoansLoanIdResponse loan = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanID);
Assertions.assertEquals(LocalDate.of(2020, 3, 2), loan.getLastClosedBusinessDate());
Assertions.assertEquals(LocalDate.of(2020, 7, 2), loan.getLastClosedBusinessDate());
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.COB_DATE, LocalDate.of(2020, 3, 3));
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.COB_DATE, LocalDate.of(2020, 7, 3));
schedulerJobHelper.executeAndAwaitJob(jobName);
loan = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanID);
Assertions.assertEquals(LocalDate.of(2020, 3, 3), loan.getLastClosedBusinessDate());
Assertions.assertEquals(LocalDate.of(2020, 7, 3), loan.getLastClosedBusinessDate());
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.COB_DATE, LocalDate.of(2020, 3, 5));
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.COB_DATE, LocalDate.of(2020, 7, 5));
schedulerJobHelper.executeAndAwaitJob(jobName);
loan = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanID);
Assertions.assertEquals(LocalDate.of(2020, 3, 3), loan.getLastClosedBusinessDate());
Assertions.assertEquals(LocalDate.of(2020, 7, 3), loan.getLastClosedBusinessDate());
} finally {
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.FALSE);
}
@@ -840,7 +845,7 @@ public class SchedulerJobsTestResults {
public void testLoanCOBApplyPenaltyOnDue() {
try {
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE);
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.COB_DATE, LocalDate.of(2019, 2, 2));
// set penalty wait period to 0
GlobalConfigurationHelper.updateValueForGlobalConfiguration(this.requestSpec, this.responseSpec, "10", "0");
this.loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec);
@@ -856,21 +861,21 @@ public class SchedulerJobsTestResults {
Assertions.assertNotNull(loanProductID);
HashMap loanStatusHashMap;
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), null, "10 January 2020");
final Integer loanID = applyForLoanApplication(clientID.toString(), loanProductID.toString(), null, "10 January 2019");
Assertions.assertNotNull(loanID);
loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
loanStatusHashMap = this.loanTransactionHelper.approveLoan("01 March 2020", loanID);
loanStatusHashMap = this.loanTransactionHelper.approveLoan("01 March 2019", loanID);
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
String loanDetails = this.loanTransactionHelper.getLoanDetails(requestSpec, responseSpec, loanID);
loanStatusHashMap = this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount("02 March 2020", loanID,
loanStatusHashMap = this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount("02 March 2019", loanID,
JsonPath.from(loanDetails).get("netDisbursalAmount").toString());
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.COB_DATE, LocalDate.of(2020, 4, 1));
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.COB_DATE, LocalDate.of(2019, 4, 1));
String jobName = "Loan COB";
this.schedulerJobHelper.executeAndAwaitJob(jobName);
@@ -879,7 +884,7 @@ public class SchedulerJobsTestResults {
Assertions.assertEquals(0, (Integer) repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
"Verifying From Penalty Charges due fot first Repayment after Successful completion of Scheduler Job");
LocalDate lastBusinessDateBeforeFastForward = LocalDate.of(2020, 4, 2);
LocalDate lastBusinessDateBeforeFastForward = LocalDate.of(2019, 4, 2);
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.COB_DATE, lastBusinessDateBeforeFastForward);
this.schedulerJobHelper.executeAndAwaitJob(jobName);
repaymentScheduleDataAfter = this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec, loanID);
@@ -888,10 +893,34 @@ public class SchedulerJobsTestResults {
List<Map> transactions = this.loanTransactionHelper.getLoanTransactions(this.requestSpec, this.responseSpec, loanID);
Assertions.assertEquals(39.39f, (Float) transactions.get(2).get("amount"));
Assertions.assertEquals(2020, ((List) transactions.get(2).get("date")).get(0));
Assertions.assertEquals(2019, ((List) transactions.get(2).get("date")).get(0));
Assertions.assertEquals(4, ((List) transactions.get(2).get("date")).get(1));
Assertions.assertEquals(2, ((List) transactions.get(2).get("date")).get(2));
} finally {
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.FALSE);
GlobalConfigurationHelper.updateValueForGlobalConfiguration(this.requestSpec, this.responseSpec, "10", "2");
}
}
@Test
public void testLoanCOBApplyPenaltyOnDue1DayGracePeriod() {
try {
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE);
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.COB_DATE, LocalDate.of(2020, 2, 2));
// set penalty wait period to 0
GlobalConfigurationHelper.updateValueForGlobalConfiguration(this.requestSpec, this.responseSpec, "10", "0");
this.loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec);
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec);
Assertions.assertNotNull(clientID);
Integer overdueFeeChargeId = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanOverdueFeeJSONWithCalculationTypePercentage("1"));
Assertions.assertNotNull(overdueFeeChargeId);
final Integer loanProductID = createLoanProduct(overdueFeeChargeId.toString());
Assertions.assertNotNull(loanProductID);
HashMap loanStatusHashMap;
// Test penalty where there is 1 day grace period
final Integer loanID2 = applyForLoanApplication(clientID.toString(), loanProductID.toString(), null, "10 January 2020");
@@ -910,10 +939,11 @@ public class SchedulerJobsTestResults {
GlobalConfigurationHelper.updateValueForGlobalConfiguration(this.requestSpec, this.responseSpec, "10", "1");
LocalDate dateToFastForward = LocalDate.of(2020, 5, 2);
String jobName = "Loan COB";
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.COB_DATE, dateToFastForward);
this.schedulerJobHelper.executeAndAwaitJob(jobName);
repaymentScheduleDataAfter = this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec, loanID2);
List<HashMap> repaymentScheduleDataAfter = this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec,
loanID2);
Assertions.assertEquals(0, (Integer) repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
"Verifying From Penalty Charges due fot first Repayment after Successful completion of Scheduler Job");
@@ -923,7 +953,7 @@ public class SchedulerJobsTestResults {
Assertions.assertEquals(39.39f, (Float) repaymentScheduleDataAfter.get(1).get("penaltyChargesDue"),
"Verifying From Penalty Charges due fot first Repayment after Successful completion of Scheduler Job");
transactions = this.loanTransactionHelper.getLoanTransactions(this.requestSpec, this.responseSpec, loanID2);
List<Map> transactions = this.loanTransactionHelper.getLoanTransactions(this.requestSpec, this.responseSpec, loanID2);
Assertions.assertEquals(39.39f, (Float) transactions.get(2).get("amount"));
Assertions.assertEquals(2020, ((List) transactions.get(2).get("date")).get(0));
Assertions.assertEquals(5, ((List) transactions.get(2).get("date")).get(1));
@@ -1148,13 +1178,6 @@ public class SchedulerJobsTestResults {
assertEquals(LocalDate.of(2022, 9, 5), loanDetails.getTransactions().get(1).getDate());
} finally {
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.FALSE);
}
try {
this.schedulerJobHelper.updateSchedulerJob(16L, new PutJobsJobIDRequest().cronExpression("0 2 0 1/1 * ? *"));
} catch (CallFailedRuntimeException e) {
// Try again (maybe it was executed by scheduler at the same time when it was called... :/
Thread.sleep(2000);
this.schedulerJobHelper.updateSchedulerJob(16L, new PutJobsJobIDRequest().cronExpression("0 2 0 1/1 * ? *"));
}
}
@@ -68,6 +68,8 @@ import org.apache.fineract.client.models.PostLoansLoanIdResponse;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest;
import org.apache.fineract.client.models.PostLoansRequest;
import org.apache.fineract.client.models.PostLoansResponse;
import org.apache.fineract.client.models.PutChargeTransactionChangesRequest;
import org.apache.fineract.client.models.PutChargeTransactionChangesResponse;
import org.apache.fineract.client.models.PutLoanProductsProductIdRequest;
@@ -790,6 +792,10 @@ public class LoanTransactionHelper extends IntegrationTest {
return (Integer) response.get("resourceId");
}
public PostLoansLoanIdChargesResponse addChargesForLoan(final Long loanId, PostLoansLoanIdChargesRequest request) {
return ok(fineract().loanCharges.executeLoanCharge(loanId, request, null));
}
public PostLoansLoanIdChargesResponse addChargeForLoan(final Integer loanId, final String payload,
final ResponseSpecification responseSpecParam) {
log.info("--------------------------------- ADD CHARGES FOR LOAN --------------------------------");
@@ -1752,10 +1758,18 @@ public class LoanTransactionHelper extends IntegrationTest {
return ok(fineract().loans.getDelinquencyTagHistory1(loanExternalId));
}
public PostLoansResponse applyLoan(PostLoansRequest request) {
return ok(fineract().loans.calculateLoanScheduleOrSubmitLoanApplication(request, null));
}
public PostLoansLoanIdResponse approveLoan(String loanExternalId, PostLoansLoanIdRequest request) {
return ok(fineract().loans.stateTransitions1(loanExternalId, request, "approve"));
}
public PostLoansLoanIdResponse approveLoan(Long loanId, PostLoansLoanIdRequest request) {
return ok(fineract().loans.stateTransitions(loanId, request, "approve"));
}
public PostLoansLoanIdResponse rejectLoan(String loanExternalId, PostLoansLoanIdRequest request) {
return ok(fineract().loans.stateTransitions1(loanExternalId, request, "reject"));
}