From 4029464e32d8494875de970b3bb4ab60eb79d8a9 Mon Sep 17 00:00:00 2001 From: Adam Saghy Date: Mon, 8 Aug 2022 23:44:59 +0200 Subject: [PATCH] FINERACT-1670: Add auditable fields to Loan Repayment Schedule installment and history --- .../LoanRepaymentScheduleInstallment.java | 6 +- .../domain/LoanRepaymentScheduleHistory.java | 31 ++++-- ...oanScheduleHistoryReadPlatformService.java | 3 + ...cheduleHistoryReadPlatformServiceImpl.java | 7 ++ ...heduleHistoryWritePlatformServiceImpl.java | 43 +++++--- ...heduleRequestWritePlatformServiceImpl.java | 5 +- ...WritePlatformServiceJpaRepositoryImpl.java | 3 - ...to_loan_repayment_schedule_installment.xml | 103 ++++++++++++++++++ 8 files changed, 165 insertions(+), 36 deletions(-) create mode 100644 fineract-provider/src/main/resources/db/changelog/tenant/parts/0032_add_audit_entries_to_loan_repayment_schedule_installment.xml diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java index 5430c4b6a..078e051b0 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java @@ -31,14 +31,14 @@ import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.Table; -import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom; +import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; import org.apache.fineract.portfolio.repaymentwithpostdatedchecks.domain.PostDatedChecks; @Entity @Table(name = "m_loan_repayment_schedule") -public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCustom +public class LoanRepaymentScheduleInstallment extends AbstractAuditableWithUTCDateTimeCustom implements Comparable { @ManyToOne(optional = false) @@ -135,7 +135,7 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "installment") private Set installmentCharges = new HashSet<>(); - LoanRepaymentScheduleInstallment() { + public LoanRepaymentScheduleInstallment() { this.installmentNumber = null; this.fromDate = null; this.dueDate = null; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanRepaymentScheduleHistory.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanRepaymentScheduleHistory.java index 7b2acca54..36147cc1a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanRepaymentScheduleHistory.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanRepaymentScheduleHistory.java @@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.loanschedule.domain; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.OffsetDateTime; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.JoinColumn; @@ -28,6 +29,8 @@ import javax.persistence.ManyToOne; import javax.persistence.OneToOne; import javax.persistence.Table; import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_DATE_DB_FIELD; +import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.LAST_MODIFIED_DATE_DB_FIELD; import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequest; @@ -65,7 +68,7 @@ public class LoanRepaymentScheduleHistory extends AbstractPersistableCustom { private BigDecimal penaltyCharges; @Column(name = "created_date") - private LocalDateTime createdOnDate; + private LocalDateTime oldCreatedOnDate; @Column(name = "createdby_id") private Long createdByUser; @@ -74,7 +77,13 @@ public class LoanRepaymentScheduleHistory extends AbstractPersistableCustom { private Long lastModifiedByUser; @Column(name = "lastmodified_date") - private LocalDateTime lastModifiedOnDate; + private LocalDateTime oldLastModifiedOnDate; + + @Column(name = CREATED_DATE_DB_FIELD) + private OffsetDateTime createdDate; + + @Column(name = LAST_MODIFIED_DATE_DB_FIELD) + private OffsetDateTime lastModifiedDate; @Column(name = "version") private Integer version; @@ -90,8 +99,8 @@ public class LoanRepaymentScheduleHistory extends AbstractPersistableCustom { private LoanRepaymentScheduleHistory(final Loan loan, final LoanRescheduleRequest loanRescheduleRequest, final Integer installmentNumber, final LocalDate fromDate, final LocalDate dueDate, final BigDecimal principal, final BigDecimal interestCharged, final BigDecimal feeChargesCharged, final BigDecimal penaltyCharges, - final LocalDateTime createdOnDate, final Long createdByUser, final Long lastModifiedByUser, - final LocalDateTime lastModifiedOnDate, final Integer version) { + final LocalDateTime oldCreatedOnDate, final Long createdByUser, final Long lastModifiedByUser, + final LocalDateTime oldLastModifiedOnDate, final Integer version, final OffsetDateTime createdDate, final OffsetDateTime lastModifiedDate) { this.loan = loan; this.loanRescheduleRequest = loanRescheduleRequest; @@ -102,11 +111,13 @@ public class LoanRepaymentScheduleHistory extends AbstractPersistableCustom { this.interestCharged = interestCharged; this.feeChargesCharged = feeChargesCharged; this.penaltyCharges = penaltyCharges; - this.createdOnDate = createdOnDate; + this.oldCreatedOnDate = oldCreatedOnDate; this.createdByUser = createdByUser; this.lastModifiedByUser = lastModifiedByUser; - this.lastModifiedOnDate = lastModifiedOnDate; + this.oldLastModifiedOnDate = oldLastModifiedOnDate; this.version = version; + this.createdDate = createdDate; + this.lastModifiedDate = lastModifiedDate; } /** @@ -115,12 +126,12 @@ public class LoanRepaymentScheduleHistory extends AbstractPersistableCustom { public static LoanRepaymentScheduleHistory instance(final Loan loan, final LoanRescheduleRequest loanRescheduleRequest, final Integer installmentNumber, final LocalDate fromDate, final LocalDate dueDate, final BigDecimal principal, final BigDecimal interestCharged, final BigDecimal feeChargesCharged, final BigDecimal penaltyCharges, - final LocalDateTime createdOnDate, final Long createdByUser, final Long lastModifiedByUser, - final LocalDateTime lastModifiedOnDate, final Integer version) { + final LocalDateTime oldCreatedOnDate, final Long createdByUser, final Long lastModifiedByUser, + final LocalDateTime oldLastModifiedOnDate, final Integer version, final OffsetDateTime createdDate, final OffsetDateTime lastModifiedDate) { return new LoanRepaymentScheduleHistory(loan, loanRescheduleRequest, installmentNumber, fromDate, dueDate, principal, - interestCharged, feeChargesCharged, penaltyCharges, createdOnDate, createdByUser, lastModifiedByUser, lastModifiedOnDate, - version); + interestCharged, feeChargesCharged, penaltyCharges, oldCreatedOnDate, createdByUser, lastModifiedByUser, oldLastModifiedOnDate, + version, createdDate, lastModifiedDate); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryReadPlatformService.java index cd2bf3e03..22270a17b 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryReadPlatformService.java @@ -19,6 +19,7 @@ package org.apache.fineract.portfolio.loanaccount.loanschedule.service; import java.util.Collection; +import java.util.Map; import org.apache.fineract.portfolio.loanaccount.data.DisbursementData; import org.apache.fineract.portfolio.loanaccount.data.RepaymentScheduleRelatedLoanData; import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData; @@ -29,4 +30,6 @@ public interface LoanScheduleHistoryReadPlatformService { LoanScheduleData retrieveRepaymentArchiveSchedule(Long loanId, RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData, Collection disbursementData); + + Map fetchOldAuditDates(Long id); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryReadPlatformServiceImpl.java index ebf487643..4ab2750c9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryReadPlatformServiceImpl.java @@ -25,6 +25,7 @@ import java.time.LocalDate; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Collection; +import java.util.Map; import org.apache.commons.lang3.ObjectUtils; import org.apache.fineract.infrastructure.core.domain.JdbcSupport; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; @@ -86,6 +87,12 @@ public class LoanScheduleHistoryReadPlatformServiceImpl implements LoanScheduleH } } + @Override + public Map fetchOldAuditDates(Long id) { + final String sql = "select lrs.created_date, lrs.lastmodified_date from m_loan_repayment_schedule lrs where lrs.id = ?"; + return this.jdbcTemplate.queryForMap(sql, id); + } + private static final class LoanScheduleArchiveResultSetExtractor implements ResultSetExtractor { private final CurrencyData currency; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryWritePlatformServiceImpl.java index 12f5d2f78..91f46815a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryWritePlatformServiceImpl.java @@ -21,32 +21,31 @@ package org.apache.fineract.portfolio.loanaccount.loanschedule.service; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.infrastructure.core.service.DateUtils; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanRepaymentScheduleHistory; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanRepaymentScheduleHistoryRepository; import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequest; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service @Transactional +@RequiredArgsConstructor public class LoanScheduleHistoryWritePlatformServiceImpl implements LoanScheduleHistoryWritePlatformService { private final LoanScheduleHistoryReadPlatformService loanScheduleHistoryReadPlatformService; private final LoanRepaymentScheduleHistoryRepository loanRepaymentScheduleHistoryRepository; - @Autowired - public LoanScheduleHistoryWritePlatformServiceImpl(final LoanScheduleHistoryReadPlatformService loanScheduleHistoryReadPlatformService, - final LoanRepaymentScheduleHistoryRepository loanRepaymentScheduleHistoryRepository) { - this.loanScheduleHistoryReadPlatformService = loanScheduleHistoryReadPlatformService; - this.loanRepaymentScheduleHistoryRepository = loanRepaymentScheduleHistoryRepository; - - } + private final PlatformSecurityContext platformSecurityContext; @Override public List createLoanScheduleArchive( @@ -73,23 +72,33 @@ public class LoanScheduleHistoryWritePlatformServiceImpl implements LoanSchedule final BigDecimal feeChargesCharged = repaymentScheduleInstallment.getFeeChargesCharged(currency).getAmount(); final BigDecimal penaltyCharges = repaymentScheduleInstallment.getPenaltyChargesCharged(currency).getAmount(); - LocalDateTime createdOnDate = null; + Map oldDates = null; + OffsetDateTime createdOnDate = DateUtils.getOffsetDateTimeOfTenant(); + LocalDateTime oldCreatedOnDate = null; + LocalDateTime oldLastModifiedOnDate = null; if (repaymentScheduleInstallment.getCreatedDate().isPresent()) { - createdOnDate = repaymentScheduleInstallment.getCreatedDate().get(); // NOSONAR + createdOnDate = repaymentScheduleInstallment.getCreatedDate().get(); + } else if (repaymentScheduleInstallment.getId() != null) { + oldDates = loanScheduleHistoryReadPlatformService.fetchOldAuditDates(repaymentScheduleInstallment.getId()); + oldCreatedOnDate = (LocalDateTime) oldDates.get("created_date"); + oldLastModifiedOnDate = (LocalDateTime) oldDates.get("lastmodified_date"); } - final Long createdByUser = repaymentScheduleInstallment.getCreatedBy().orElse(null); - final Long lastModifiedByUser = repaymentScheduleInstallment.getLastModifiedBy().orElse(null); - - LocalDateTime lastModifiedOnDate = null; + final Long createdByUser = repaymentScheduleInstallment.getCreatedBy().orElse(platformSecurityContext.authenticatedUser().getId()); + final Long lastModifiedByUser = repaymentScheduleInstallment.getLastModifiedBy().orElse(platformSecurityContext.authenticatedUser().getId()); + OffsetDateTime lastModifiedOnDate = DateUtils.getOffsetDateTimeOfTenant(); if (repaymentScheduleInstallment.getLastModifiedDate().isPresent()) { - lastModifiedOnDate = repaymentScheduleInstallment.getLastModifiedDate().get(); // NOSONAR + lastModifiedOnDate = repaymentScheduleInstallment.getLastModifiedDate().get(); + } else if (repaymentScheduleInstallment.getId() != null && oldDates == null) { + oldDates = loanScheduleHistoryReadPlatformService.fetchOldAuditDates(repaymentScheduleInstallment.getId()); + oldCreatedOnDate = (LocalDateTime) oldDates.get("created_date"); + oldLastModifiedOnDate = (LocalDateTime) oldDates.get("lastmodified_date"); } LoanRepaymentScheduleHistory loanRepaymentScheduleHistory = LoanRepaymentScheduleHistory.instance(loan, loanRescheduleRequest, - installmentNumber, fromDate, dueDate, principal, interestCharged, feeChargesCharged, penaltyCharges, createdOnDate, - createdByUser, lastModifiedByUser, lastModifiedOnDate, version); + installmentNumber, fromDate, dueDate, principal, interestCharged, feeChargesCharged, penaltyCharges, oldCreatedOnDate, + createdByUser, lastModifiedByUser, oldLastModifiedOnDate, version, createdOnDate, lastModifiedOnDate); loanRepaymentScheduleHistoryList.add(loanRepaymentScheduleHistory); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java index 976b19ab2..6f7e37d87 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java @@ -475,9 +475,8 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche loan.recalculateAllCharges(); ChangedTransactionDetail changedTransactionDetail = loan.processTransactions(); - for (LoanRepaymentScheduleHistory loanRepaymentScheduleHistory : loanRepaymentScheduleHistoryList) { - this.loanRepaymentScheduleHistoryRepository.save(loanRepaymentScheduleHistory); - } + + this.loanRepaymentScheduleHistoryRepository.saveAll(loanRepaymentScheduleHistoryList); loan.updateRescheduledByUser(appUser); loan.updateRescheduledOnDate(DateUtils.getBusinessLocalDate()); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 936c37690..029ca66e1 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -1943,9 +1943,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf // Subtract the amount waived from the existing fee charges waived amount. chargePerInstallment.getInstallment().setFeeChargesWaived(feeChargesWaivedAmount.subtract(amountWaived)); - // Set the last modification date. - chargePerInstallment.getInstallment().setLastModifiedDate(DateUtils.getLocalDateTimeOfSystem()); - // Update loan charge. loanCharge.setInstallmentLoanCharge(chargePerInstallment, chargePerInstallment.getInstallment().getInstallmentNumber()); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0032_add_audit_entries_to_loan_repayment_schedule_installment.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0032_add_audit_entries_to_loan_repayment_schedule_installment.xml new file mode 100644 index 000000000..9144fea66 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0032_add_audit_entries_to_loan_repayment_schedule_installment.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select count(*) from m_loan_repayment_schedule + + + + + + + select count(*) from m_loan_repayment_schedule + + + + + + + select count(*) from m_loan_repayment_schedule where created_by is null or last_modified_by is null + + + + + + + + + + + + + + + + + + + select count(*) from m_loan_repayment_schedule_history + + + + + + + select count(*) from m_loan_repayment_schedule_history + + + + +