FINERACT-1670: Add auditable fields to Loan Repayment Schedule installment and history
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 5430c4b..078e051 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.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<LoanRepaymentScheduleInstallment> {
@ManyToOne(optional = false)
@@ -135,7 +135,7 @@
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "installment")
private Set<LoanInstallmentCharge> 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 7b2acca..36147cc 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 @@
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.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 @@
private BigDecimal penaltyCharges;
@Column(name = "created_date")
- private LocalDateTime createdOnDate;
+ private LocalDateTime oldCreatedOnDate;
@Column(name = "createdby_id")
private Long createdByUser;
@@ -74,7 +77,13 @@
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 @@
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 @@
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 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 cd2bf3e..22270a1 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 @@
LoanScheduleData retrieveRepaymentArchiveSchedule(Long loanId, RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData,
Collection<DisbursementData> disbursementData);
+
+ Map<String, Object> 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 ebf4876..4ab2750 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.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 @@
}
}
+ @Override
+ public Map<String, Object> 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<LoanScheduleData> {
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 12f5d2f..91f4681 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 @@
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<LoanRepaymentScheduleHistory> createLoanScheduleArchive(
@@ -73,23 +72,33 @@
final BigDecimal feeChargesCharged = repaymentScheduleInstallment.getFeeChargesCharged(currency).getAmount();
final BigDecimal penaltyCharges = repaymentScheduleInstallment.getPenaltyChargesCharged(currency).getAmount();
- LocalDateTime createdOnDate = null;
+ Map<String, Object> 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);
+ final Long createdByUser = repaymentScheduleInstallment.getCreatedBy().orElse(platformSecurityContext.authenticatedUser().getId());
+ final Long lastModifiedByUser = repaymentScheduleInstallment.getLastModifiedBy().orElse(platformSecurityContext.authenticatedUser().getId());
- LocalDateTime lastModifiedOnDate = null;
-
+ 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 976b19a..6f7e37d 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 @@
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 936c376..029ca66 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 @@
// 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 0000000..9144fea
--- /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 @@
+<?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="loan_repayment_schedule-1" context="mysql">
+ <addColumn tableName="m_loan_repayment_schedule">
+ <column name="created_on_utc" type="DATETIME"/>
+ <column name="last_modified_on_utc" type="DATETIME"/>
+ </addColumn>
+ </changeSet>
+ <changeSet author="fineract" id="loan_repayment_schedule-1" context="postgresql">
+ <addColumn tableName="m_loan_repayment_schedule">
+ <column name="created_on_utc" type="TIMESTAMP WITH TIME ZONE"/>
+ <column name="last_modified_on_utc" type="TIMESTAMP WITH TIME ZONE"/>
+ </addColumn>
+ </changeSet>
+
+ <changeSet id="loan_repayment_schedule-2" author="fineract">
+ <dropNotNullConstraint tableName="m_loan_repayment_schedule" columnName="created_date" columnDataType="datetime"/>
+ <dropNotNullConstraint tableName="m_loan_repayment_schedule" columnName="lastmodified_date" columnDataType="datetime"/>
+ </changeSet>
+ <changeSet id="loan_repayment_schedule-3" author="fineract">
+ <renameColumn tableName="m_loan_repayment_schedule" oldColumnName="createdby_id" newColumnName="created_by" columnDataType="BIGINT"/>
+ <renameColumn tableName="m_loan_repayment_schedule" oldColumnName="lastmodifiedby_id" newColumnName="last_modified_by" columnDataType="BIGINT"/>
+ </changeSet>
+ <changeSet author="fineract" id="loan_repayment_schedule-4">
+ <addForeignKeyConstraint baseColumnNames="created_by" baseTableName="m_loan_repayment_schedule"
+ constraintName="FK_loan_repayment_schedule_created_by" deferrable="false" initiallyDeferred="false"
+ onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="id"
+ referencedTableName="m_appuser" validate="true"/>
+ <addForeignKeyConstraint baseColumnNames="last_modified_by" baseTableName="m_loan_repayment_schedule"
+ constraintName="FK_loan_repayment_schedule_last_modified_by" deferrable="false" initiallyDeferred="false"
+ onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="id"
+ referencedTableName="m_appuser" validate="true"/>
+ </changeSet>
+ <changeSet id="loan_repayment_schedule-5" author="fineract" context="mysql">
+ <preConditions onFail="MARK_RAN">
+ <sqlCheck expectedResult="0">select count(*) from m_loan_repayment_schedule</sqlCheck>
+ </preConditions>
+ <addNotNullConstraint tableName="m_loan_repayment_schedule" columnName="created_on_utc" columnDataType="DATETIME"/>
+ <addNotNullConstraint tableName="m_loan_repayment_schedule" columnName="last_modified_on_utc" columnDataType="DATETIME"/>
+ </changeSet>
+ <changeSet id="loan_repayment_schedule-5" author="fineract" context="postgresql">
+ <preConditions onFail="MARK_RAN">
+ <sqlCheck expectedResult="0">select count(*) from m_loan_repayment_schedule</sqlCheck>
+ </preConditions>
+ <addNotNullConstraint tableName="m_loan_repayment_schedule" columnName="created_on_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
+ <addNotNullConstraint tableName="m_loan_repayment_schedule" columnName="last_modified_on_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
+ </changeSet>
+ <changeSet id="loan_repayment_schedule-6" author="fineract">
+ <preConditions onFail="MARK_RAN">
+ <sqlCheck expectedResult="0">select count(*) from m_loan_repayment_schedule where created_by is null or last_modified_by is null</sqlCheck>
+ </preConditions>
+ <addNotNullConstraint tableName="m_loan_repayment_schedule" columnName="created_by" columnDataType="BIGINT"/>
+ <addNotNullConstraint tableName="m_loan_repayment_schedule" columnName="last_modified_by" columnDataType="BIGINT"/>
+ </changeSet>
+ <changeSet author="fineract" id="loan_repayment_schedule_history-1" context="mysql">
+ <addColumn tableName="m_loan_repayment_schedule_history">
+ <column name="created_on_utc" type="DATETIME"/>
+ <column name="last_modified_on_utc" type="DATETIME"/>
+ </addColumn>
+ </changeSet>
+ <changeSet author="fineract" id="loan_repayment_schedule_history-1" context="postgresql">
+ <addColumn tableName="m_loan_repayment_schedule_history">
+ <column name="created_on_utc" type="TIMESTAMP WITH TIME ZONE"/>
+ <column name="last_modified_on_utc" type="TIMESTAMP WITH TIME ZONE"/>
+ </addColumn>
+ </changeSet>
+ <changeSet id="loan_repayment_schedule_history-2" author="fineract" context="mysql">
+ <preConditions onFail="MARK_RAN">
+ <sqlCheck expectedResult="0">select count(*) from m_loan_repayment_schedule_history</sqlCheck>
+ </preConditions>
+ <addNotNullConstraint tableName="m_loan_repayment_schedule_history" columnName="created_on_utc" columnDataType="DATETIME"/>
+ <addNotNullConstraint tableName="m_loan_repayment_schedule_history" columnName="last_modified_on_utc" columnDataType="DATETIME"/>
+ </changeSet>
+ <changeSet id="loan_repayment_schedule_history-2" author="fineract" context="postgresql">
+ <preConditions onFail="MARK_RAN">
+ <sqlCheck expectedResult="0">select count(*) from m_loan_repayment_schedule_history</sqlCheck>
+ </preConditions>
+ <addNotNullConstraint tableName="m_loan_repayment_schedule_history" columnName="created_on_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
+ <addNotNullConstraint tableName="m_loan_repayment_schedule_history" columnName="last_modified_on_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
+ </changeSet>
+</databaseChangeLog>