This is an automated email from the ASF dual-hosted git repository.

arnold pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new 65c6b18ed Fix inconsistenant Date and Date time handling
65c6b18ed is described below

commit 65c6b18ed13f4e208dec053e01b39e7d5e94928f
Author: Adam Saghy <[email protected]>
AuthorDate: Mon Aug 1 10:48:06 2022 +0200

    Fix inconsistenant Date and Date time handling
---
 .../AccrualAccountingWritePlatformServiceImpl.java |   4 +-
 .../infrastructure/core/domain/JdbcSupport.java    |  12 +
 .../jobs/service/updatenpa/UpdateNpaConfig.java    |   6 +-
 .../jobs/service/updatenpa/UpdateNpaTasklet.java   |  21 +-
 .../portfolio/client/domain/ClientTransaction.java |  49 +++--
 ...hargeWritePlatformServiceJpaRepositoryImpl.java |  19 +-
 .../ClientTransactionReadPlatformServiceImpl.java  |   6 +-
 .../floatingrates/data/FloatingRateData.java       |  14 +-
 .../floatingrates/data/FloatingRatePeriodData.java |  21 +-
 .../floatingrates/domain/FloatingRate.java         |  75 ++-----
 .../floatingrates/domain/FloatingRatePeriod.java   |  73 ++-----
 .../FloatingRateWritePlatformServiceImpl.java      |  14 +-
 .../FloatingRatesReadPlatformServiceImpl.java      |  30 ++-
 .../AddAccrualEntriesTasklet.java                  |  12 +-
 .../service/LoanAccrualPlatformServiceImpl.java    |  20 +-
 .../LoanAccrualWritePlatformServiceImpl.java       | 211 +++++++++---------
 .../db/changelog/tenant/changelog-tenant.xml       |   2 +
 .../0023_use_the_proper_date_or_datetime_type.xml  |  41 ++++
 .../tenant/parts/0024_add_audit_entries.xml        | 241 +++++++++++++++++++++
 .../integrationtests/FixedDepositTest.java         |  88 ++++----
 20 files changed, 595 insertions(+), 364 deletions(-)

diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/accrual/service/AccrualAccountingWritePlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/accrual/service/AccrualAccountingWritePlatformServiceImpl.java
index 3ce56a237..7856cf65e 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/accounting/accrual/service/AccrualAccountingWritePlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/accounting/accrual/service/AccrualAccountingWritePlatformServiceImpl.java
@@ -46,9 +46,9 @@ public class AccrualAccountingWritePlatformServiceImpl 
implements AccrualAccount
     @Override
     public CommandProcessingResult executeLoansPeriodicAccrual(JsonCommand 
command) {
         
this.accountingDataValidator.validateLoanPeriodicAccrualData(command.json());
-        LocalDate tilldate = 
command.localDateValueOfParameterNamed(accrueTillParamName);
+        LocalDate tillDate = 
command.localDateValueOfParameterNamed(accrueTillParamName);
         try {
-            this.loanAccrualPlatformService.addPeriodicAccruals(tilldate);
+            this.loanAccrualPlatformService.addPeriodicAccruals(tillDate);
         } catch (MultiException e) {
             final List<ApiParameterError> dataValidationErrors = new 
ArrayList<>();
             final DataValidatorBuilder baseDataValidator = new 
DataValidatorBuilder(dataValidationErrors)
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/domain/JdbcSupport.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/domain/JdbcSupport.java
index 74728c2c3..2be81ae87 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/domain/JdbcSupport.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/domain/JdbcSupport.java
@@ -26,6 +26,8 @@ import java.sql.Timestamp;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
 import java.time.ZonedDateTime;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.springframework.jdbc.support.JdbcUtils;
@@ -133,4 +135,14 @@ public final class JdbcSupport {
         }
         return result;
     }
+
+    public static OffsetDateTime getOffsetDateTime(ResultSet rs, String 
columnName) throws SQLException {
+        final Timestamp timestamp = rs.getTimestamp(columnName);
+        if (timestamp != null) {
+            OffsetDateTime offsetDateTimeAtUTC = 
OffsetDateTime.of(timestamp.toLocalDateTime(), ZoneOffset.UTC);
+            return offsetDateTimeAtUTC
+                    
.withOffsetSameInstant(DateUtils.getDateTimeZoneOfTenant().getRules().getOffset(offsetDateTimeAtUTC.toInstant()));
+        }
+        return null;
+    }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/updatenpa/UpdateNpaConfig.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/updatenpa/UpdateNpaConfig.java
index 861537566..b0c72d164 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/updatenpa/UpdateNpaConfig.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/updatenpa/UpdateNpaConfig.java
@@ -22,6 +22,7 @@ import 
org.apache.fineract.infrastructure.core.service.RoutingDataSourceServiceF
 import 
org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
 import 
org.apache.fineract.infrastructure.core.service.database.DatabaseTypeResolver;
 import org.apache.fineract.infrastructure.jobs.service.JobName;
+import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
 import org.springframework.batch.core.Job;
 import org.springframework.batch.core.Step;
 import 
org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
@@ -46,6 +47,9 @@ public class UpdateNpaConfig {
     @Autowired
     private DatabaseSpecificSQLGenerator sqlGenerator;
 
+    @Autowired
+    private PlatformSecurityContext platformSecurityContext;
+
     @Bean
     protected Step updateNpaStep() {
         return 
steps.get(JobName.UPDATE_NPA.name()).tasklet(updateNpaTasklet()).build();
@@ -58,6 +62,6 @@ public class UpdateNpaConfig {
 
     @Bean
     public UpdateNpaTasklet updateNpaTasklet() {
-        return new UpdateNpaTasklet(dataSourceServiceFactory, 
databaseTypeResolver, sqlGenerator);
+        return new UpdateNpaTasklet(dataSourceServiceFactory, 
databaseTypeResolver, sqlGenerator, platformSecurityContext);
     }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/updatenpa/UpdateNpaTasklet.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/updatenpa/UpdateNpaTasklet.java
index 60836514e..d2de9abae 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/updatenpa/UpdateNpaTasklet.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/updatenpa/UpdateNpaTasklet.java
@@ -20,10 +20,13 @@ package 
org.apache.fineract.infrastructure.jobs.service.updatenpa;
 
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
 import 
org.apache.fineract.infrastructure.core.service.RoutingDataSourceServiceFactory;
 import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import 
org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
 import 
org.apache.fineract.infrastructure.core.service.database.DatabaseTypeResolver;
+import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.apache.fineract.useradministration.domain.AppUser;
 import org.springframework.batch.core.StepContribution;
 import org.springframework.batch.core.scope.context.ChunkContext;
 import org.springframework.batch.core.step.tasklet.Tasklet;
@@ -37,9 +40,11 @@ public class UpdateNpaTasklet implements Tasklet {
     private final RoutingDataSourceServiceFactory dataSourceServiceFactory;
     private final DatabaseTypeResolver databaseTypeResolver;
     private final DatabaseSpecificSQLGenerator sqlGenerator;
+    private final PlatformSecurityContext context;
 
     @Override
     public RepeatStatus execute(StepContribution contribution, ChunkContext 
chunkContext) throws Exception {
+        AppUser user = context.getAuthenticatedUserIfPresent();
         final JdbcTemplate jdbcTemplate = new 
JdbcTemplate(dataSourceServiceFactory.determineDataSourceService().retrieveDataSource());
 
         final StringBuilder resetNPASqlBuilder = new StringBuilder();
@@ -52,11 +57,13 @@ public class UpdateNpaTasklet implements Tasklet {
         String wherePart = " where loan.id = sl.id ";
 
         if (databaseTypeResolver.isMySQL()) {
-            resetNPASqlBuilder.append(", ").append(fromPart).append(" set 
loan.is_npa = false").append(wherePart);
+            resetNPASqlBuilder.append(", ").append(fromPart).append(" set 
loan.is_npa = false")
+                    .append(", loan.last_modified_by = ?, 
loan.last_modified_on_utc = ? ").append(wherePart);
         } else {
-            resetNPASqlBuilder.append("set is_npa = false").append(" FROM 
").append(fromPart).append(wherePart);
+            resetNPASqlBuilder.append("set is_npa = false").append(", 
last_modified_by = ?, last_modified_on_utc = ? ").append(" FROM ")
+                    .append(fromPart).append(wherePart);
         }
-        jdbcTemplate.update(resetNPASqlBuilder.toString());
+        jdbcTemplate.update(resetNPASqlBuilder.toString(), user.getId(), 
DateUtils.getOffsetDateTimeOfTenant());
 
         final StringBuilder updateSqlBuilder = new StringBuilder(900);
 
@@ -68,12 +75,14 @@ public class UpdateNpaTasklet implements Tasklet {
         wherePart = " where ml.id=sl.id ";
         updateSqlBuilder.append("UPDATE m_loan as ml ");
         if (databaseTypeResolver.isMySQL()) {
-            updateSqlBuilder.append(", ").append(fromPart).append(" SET 
ml.is_npa = true").append(wherePart);
+            updateSqlBuilder.append(", ").append(fromPart).append(" SET 
ml.is_npa = true")
+                    .append(", ml.last_modified_by = ?, 
ml.last_modified_on_utc = ? ").append(wherePart);
         } else {
-            updateSqlBuilder.append(" SET is_npa = true").append(" FROM 
").append(fromPart).append(wherePart);
+            updateSqlBuilder.append(" SET is_npa = true").append(", 
last_modified_by = ?, last_modified_on_utc = ? ").append(" FROM ")
+                    .append(fromPart).append(wherePart);
         }
 
-        final int result = jdbcTemplate.update(updateSqlBuilder.toString());
+        final int result = jdbcTemplate.update(updateSqlBuilder.toString(), 
user.getId(), DateUtils.getOffsetDateTimeOfTenant());
 
         log.info("{}: Records affected by updateNPA: {}", 
ThreadLocalContextUtil.getTenant().getName(), result);
         return RepeatStatus.FINISHED;
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientTransaction.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientTransaction.java
index 0023d9025..b292b521f 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientTransaction.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientTransaction.java
@@ -20,7 +20,6 @@ package org.apache.fineract.portfolio.client.domain;
 
 import java.math.BigDecimal;
 import java.time.LocalDate;
-import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
@@ -39,18 +38,17 @@ import javax.persistence.Transient;
 import javax.persistence.UniqueConstraint;
 import org.apache.fineract.accounting.glaccount.domain.GLAccount;
 import org.apache.fineract.infrastructure.core.data.EnumOptionData;
-import 
org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
+import 
org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
 import org.apache.fineract.organisation.monetary.domain.Money;
 import org.apache.fineract.organisation.office.domain.Office;
 import org.apache.fineract.organisation.office.domain.OrganisationCurrency;
 import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
-import org.apache.fineract.useradministration.domain.AppUser;
 
 @Entity
 @Table(name = "m_client_transaction", uniqueConstraints = { 
@UniqueConstraint(columnNames = { "external_id" }, name = "external_id") })
-public class ClientTransaction extends AbstractPersistableCustom {
+public class ClientTransaction extends AbstractAuditableWithUTCDateTimeCustom {
 
     @ManyToOne(optional = false)
     @JoinColumn(name = "client_id", nullable = false)
@@ -73,6 +71,9 @@ public class ClientTransaction extends 
AbstractPersistableCustom {
     @Column(name = "transaction_date", nullable = false)
     private LocalDate dateOf;
 
+    @Column(name = "submitted_on_date", nullable = false)
+    private LocalDate submittedOnDate;
+
     @Column(name = "amount", scale = 6, precision = 19, nullable = false)
     private BigDecimal amount;
 
@@ -82,12 +83,11 @@ public class ClientTransaction extends 
AbstractPersistableCustom {
     @Column(name = "external_id", length = 100, nullable = true, unique = true)
     private String externalId;
 
-    @Column(name = "created_date", nullable = false)
-    private LocalDateTime createdDate;
-
-    @ManyToOne
-    @JoinColumn(name = "appuser_id", nullable = true)
-    private AppUser appUser;
+    /*
+     * Deprecated since common Auditable fields were introduced. Columns and 
data left untouched to help migration.
+     *
+     * @Column(name = "created_date", nullable = false) private LocalDateTime 
createdDate;
+     */
 
     @OneToMany(cascade = CascadeType.ALL, mappedBy = "clientTransaction", 
orphanRemoval = true, fetch = FetchType.EAGER)
     private Set<ClientChargePaidBy> clientChargePaidByCollection = new 
HashSet<>();
@@ -97,37 +97,36 @@ public class ClientTransaction extends 
AbstractPersistableCustom {
 
     protected ClientTransaction() {}
 
-    public static ClientTransaction payCharge(final Client client, final 
Office office, PaymentDetail paymentDetail, final LocalDate date,
-            final Money amount, final String currencyCode, final AppUser 
appUser) {
+    public static ClientTransaction payCharge(final Client client, final 
Office office, PaymentDetail paymentDetail,
+            final LocalDate transactionDate, final Money amount, final String 
currencyCode) {
         final boolean isReversed = false;
         final String externalId = null;
-        return new ClientTransaction(client, office, paymentDetail, 
ClientTransactionType.PAY_CHARGE.getValue(), date, amount, isReversed,
-                externalId, DateUtils.getLocalDateTimeOfTenant(), 
currencyCode, appUser);
+        return new ClientTransaction(client, office, paymentDetail, 
ClientTransactionType.PAY_CHARGE.getValue(), transactionDate, amount,
+                isReversed, externalId, currencyCode);
     }
 
-    public static ClientTransaction waiver(final Client client, final Office 
office, final LocalDate date, final Money amount,
-            final String currencyCode, final AppUser appUser) {
+    public static ClientTransaction waiver(final Client client, final Office 
office, final LocalDate transactionDate, final Money amount,
+            final String currencyCode) {
         final boolean isReversed = false;
         final String externalId = null;
         final PaymentDetail paymentDetail = null;
-        return new ClientTransaction(client, office, paymentDetail, 
ClientTransactionType.WAIVE_CHARGE.getValue(), date, amount, isReversed,
-                externalId, DateUtils.getLocalDateTimeOfTenant(), 
currencyCode, appUser);
+        return new ClientTransaction(client, office, paymentDetail, 
ClientTransactionType.WAIVE_CHARGE.getValue(), transactionDate, amount,
+                isReversed, externalId, currencyCode);
     }
 
-    public ClientTransaction(Client client, Office office, PaymentDetail 
paymentDetail, Integer typeOf, LocalDate transactionLocalDate,
-            Money amount, boolean reversed, String externalId, LocalDateTime 
createdDate, String currencyCode, AppUser appUser) {
+    public ClientTransaction(Client client, Office office, PaymentDetail 
paymentDetail, Integer typeOf, LocalDate transactionDate,
+            Money amount, boolean reversed, String externalId, String 
currencyCode) {
 
         this.client = client;
         this.office = office;
         this.paymentDetail = paymentDetail;
         this.typeOf = typeOf;
-        this.dateOf = transactionLocalDate;
+        this.dateOf = transactionDate;
         this.amount = amount.getAmount();
         this.reversed = reversed;
         this.externalId = externalId;
-        this.createdDate = createdDate;
         this.currencyCode = currencyCode;
-        this.appUser = appUser;
+        this.submittedOnDate = DateUtils.getBusinessLocalDate();
     }
 
     public void reverse() {
@@ -226,4 +225,8 @@ public class ClientTransaction extends 
AbstractPersistableCustom {
         return this.dateOf;
     }
 
+    public LocalDate getSubmittedOnDate() {
+        return this.submittedOnDate;
+    }
+
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientChargeWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientChargeWritePlatformServiceJpaRepositoryImpl.java
index 8b3a65e17..f0133d0bc 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientChargeWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientChargeWritePlatformServiceJpaRepositoryImpl.java
@@ -54,7 +54,6 @@ import 
org.apache.fineract.portfolio.client.domain.ClientTransaction;
 import org.apache.fineract.portfolio.client.domain.ClientTransactionRepository;
 import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
 import 
org.apache.fineract.portfolio.paymentdetail.service.PaymentDetailWritePlatformService;
-import org.apache.fineract.useradministration.domain.AppUser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -174,7 +173,7 @@ public class 
ClientChargeWritePlatformServiceJpaRepositoryImpl implements Client
             final PaymentDetail paymentDetail = 
this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, 
changes);
 
             ClientTransaction clientTransaction = 
ClientTransaction.payCharge(client, client.getOffice(), paymentDetail, 
transactionDate,
-                    chargePaid, clientCharge.getCurrency().getCode(), 
getAppUserIfPresent());
+                    chargePaid, clientCharge.getCurrency().getCode());
             this.clientTransactionRepository.saveAndFlush(clientTransaction);
 
             // update charge paid by associations
@@ -217,7 +216,7 @@ public class 
ClientChargeWritePlatformServiceJpaRepositoryImpl implements Client
 
             // create Waiver Transaction
             ClientTransaction clientTransaction = 
ClientTransaction.waiver(client, client.getOffice(), transactionDate, 
waivedAmount,
-                    clientCharge.getCurrency().getCode(), 
getAppUserIfPresent());
+                    clientCharge.getCurrency().getCode());
             this.clientTransactionRepository.saveAndFlush(clientTransaction);
 
             // update charge paid by associations
@@ -392,7 +391,8 @@ public class 
ClientChargeWritePlatformServiceJpaRepositoryImpl implements Client
     /**
      * Ensures that the charge transaction date (for payments) is not on a 
holiday or a non working day
      *
-     * @param savingsAccountCharge
+     * @param transactionDate
+     * @param clientCharge
      * @param fmt
      */
     private void validateTransactionDateOnWorkingDay(final LocalDate 
transactionDate, final ClientCharge clientCharge,
@@ -406,7 +406,8 @@ public class 
ClientChargeWritePlatformServiceJpaRepositoryImpl implements Client
      * @param date
      * @param officeId
      * @param jsonPropertyName
-     * @param errorMessageFragment
+     * @param errorMessageFragmentForActivityOnHoliday
+     * @param errorMessageFragmentForActivityOnNonWorkingDay
      * @param fmt
      */
     private void validateActivityDateFallOnAWorkingDay(final LocalDate date, 
final Long officeId, final String jsonPropertyName,
@@ -436,14 +437,6 @@ public class 
ClientChargeWritePlatformServiceJpaRepositoryImpl implements Client
         }
     }
 
-    private AppUser getAppUserIfPresent() {
-        AppUser user = null;
-        if (this.context != null) {
-            user = this.context.getAuthenticatedUserIfPresent();
-        }
-        return user;
-    }
-
     private void handleDataIntegrityIssues(@SuppressWarnings("unused") final 
Long clientId, final Long clientChargeId,
             final Throwable realCause, final NonTransientDataAccessException 
dve) {
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientTransactionReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientTransactionReadPlatformServiceImpl.java
index 5f9194de9..476c6aad9 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientTransactionReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientTransactionReadPlatformServiceImpl.java
@@ -68,7 +68,7 @@ public class ClientTransactionReadPlatformServiceImpl 
implements ClientTransacti
             final StringBuilder sqlBuilder = new StringBuilder(400);
             sqlBuilder.append("tr.id as transactionId, 
tr.transaction_type_enum as transactionType,  ");
             sqlBuilder.append("tr.transaction_date as transactionDate, 
tr.amount as transactionAmount, ");
-            sqlBuilder.append("tr.created_date as submittedOnDate, 
tr.is_reversed as reversed, ");
+            sqlBuilder.append("tr.submitted_on_date as submittedOnDate, 
tr.is_reversed as reversed, ");
             sqlBuilder.append("tr.external_id as externalId, o.name as 
officeName, o.id as officeId, ");
             sqlBuilder.append("c.id as clientId, c.account_no as accountNo, 
ccpb.client_charge_id as clientChargeId, ");
             sqlBuilder.append("pd.payment_type_id as 
paymentType,pd.account_number as accountNumber,pd.check_number as checkNumber, 
");
@@ -143,7 +143,7 @@ public class ClientTransactionReadPlatformServiceImpl 
implements ClientTransacti
         sqlBuilder.append("select " + sqlGenerator.calcFoundRows() + " 
").append(this.clientTransactionMapper.schema())
                 .append(" where c.id = ? ");
         parameters[0] = clientId;
-        sqlBuilder.append(" order by tr.transaction_date DESC, tr.created_date 
DESC, tr.id DESC ");
+        sqlBuilder.append(" order by tr.transaction_date DESC, 
tr.submitted_on_date DESC, tr.id DESC ");
 
         // apply limit and offsets
 
@@ -169,7 +169,7 @@ public class ClientTransactionReadPlatformServiceImpl 
implements ClientTransacti
             sql = sql + " and ccpb.client_charge_id = ?";
         }
         parameters[0] = clientId;
-        sql = sql + " order by tr.transaction_date DESC, tr.created_date DESC, 
tr.id DESC";
+        sql = sql + " order by tr.transaction_date DESC, tr.submitted_on_date 
DESC, tr.id DESC";
         return this.jdbcTemplate.query(sql, this.clientTransactionMapper, 
parameters); // NOSONAR
     }
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/data/FloatingRateData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/data/FloatingRateData.java
index 5d88d25f7..f443a9d93 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/data/FloatingRateData.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/data/FloatingRateData.java
@@ -19,7 +19,7 @@
 package org.apache.fineract.portfolio.floatingrates.data;
 
 import java.io.Serializable;
-import java.time.LocalDate;
+import java.time.OffsetDateTime;
 import java.util.List;
 import org.apache.commons.lang3.builder.CompareToBuilder;
 import org.apache.commons.lang3.builder.EqualsBuilder;
@@ -33,15 +33,15 @@ public class FloatingRateData implements 
Comparable<FloatingRateData>, Serializa
     private final boolean isBaseLendingRate;
     private final boolean isActive;
     private final String createdBy;
-    private final LocalDate createdOn;
+    private final OffsetDateTime createdOn;
     private final String modifiedBy;
-    private final LocalDate modifiedOn;
+    private final OffsetDateTime modifiedOn;
     private final List<FloatingRatePeriodData> ratePeriods;
     @SuppressWarnings("unused")
     private final List<EnumOptionData> interestRateFrequencyTypeOptions;
 
-    public FloatingRateData(Long id, String name, boolean isBaseLendingRate, 
boolean isActive, String createdBy, LocalDate createdOn,
-            String modifiedBy, LocalDate modifiedOn, 
List<FloatingRatePeriodData> ratePeriods,
+    public FloatingRateData(Long id, String name, boolean isBaseLendingRate, 
boolean isActive, String createdBy, OffsetDateTime createdOn,
+            String modifiedBy, OffsetDateTime modifiedOn, 
List<FloatingRatePeriodData> ratePeriods,
             List<EnumOptionData> interestRateFrequencyTypeOptions) {
         this.id = id;
         this.name = name;
@@ -75,7 +75,7 @@ public class FloatingRateData implements 
Comparable<FloatingRateData>, Serializa
         return this.createdBy;
     }
 
-    public LocalDate getCreatedOn() {
+    public OffsetDateTime getCreatedOn() {
         return this.createdOn;
     }
 
@@ -83,7 +83,7 @@ public class FloatingRateData implements 
Comparable<FloatingRateData>, Serializa
         return this.modifiedBy;
     }
 
-    public LocalDate getModifiedOn() {
+    public OffsetDateTime getModifiedOn() {
         return this.modifiedOn;
     }
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/data/FloatingRatePeriodData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/data/FloatingRatePeriodData.java
index fd2c14d78..93516f1a9 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/data/FloatingRatePeriodData.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/data/FloatingRatePeriodData.java
@@ -21,7 +21,7 @@ package org.apache.fineract.portfolio.floatingrates.data;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.time.LocalDate;
-import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
 import org.apache.commons.lang3.builder.CompareToBuilder;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
@@ -34,12 +34,12 @@ public class FloatingRatePeriodData implements 
Comparable<FloatingRatePeriodData
     private boolean isDifferentialToBaseLendingRate;
     private boolean isActive;
     private String createdBy;
-    private LocalDateTime createdOn;
+    private OffsetDateTime createdOn;
     private String modifiedBy;
-    private LocalDateTime modifiedOn;
+    private OffsetDateTime modifiedOn;
 
     public FloatingRatePeriodData(Long id, LocalDate fromDate, BigDecimal 
interestRate, boolean isDifferentialToBaseLendingRate,
-            boolean isActive, String createdBy, LocalDateTime createdOn, 
String modifiedBy, LocalDateTime modifiedOn) {
+            boolean isActive, String createdBy, OffsetDateTime createdOn, 
String modifiedBy, OffsetDateTime modifiedOn) {
         this.id = id;
         this.fromDate = fromDate;
         this.interestRate = interestRate;
@@ -51,6 +51,15 @@ public class FloatingRatePeriodData implements 
Comparable<FloatingRatePeriodData
         this.modifiedOn = modifiedOn;
     }
 
+    public FloatingRatePeriodData(Long id, LocalDate fromDate, BigDecimal 
interestRate, boolean isDifferentialToBaseLendingRate,
+            boolean isActive) {
+        this.id = id;
+        this.fromDate = fromDate;
+        this.interestRate = interestRate;
+        this.isDifferentialToBaseLendingRate = isDifferentialToBaseLendingRate;
+        this.isActive = isActive;
+    }
+
     public Long getId() {
         return this.id;
     }
@@ -79,7 +88,7 @@ public class FloatingRatePeriodData implements 
Comparable<FloatingRatePeriodData
         return this.createdBy;
     }
 
-    public LocalDateTime getCreatedOn() {
+    public OffsetDateTime getCreatedOn() {
         return this.createdOn;
     }
 
@@ -87,7 +96,7 @@ public class FloatingRatePeriodData implements 
Comparable<FloatingRatePeriodData
         return this.modifiedBy;
     }
 
-    public LocalDateTime getModifiedOn() {
+    public OffsetDateTime getModifiedOn() {
         return this.modifiedOn;
     }
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/domain/FloatingRate.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/domain/FloatingRate.java
index a7e252f21..4fc93e6ba 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/domain/FloatingRate.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/domain/FloatingRate.java
@@ -23,7 +23,6 @@ import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import java.math.BigDecimal;
 import java.time.LocalDate;
-import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
@@ -34,24 +33,20 @@ import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
 import javax.persistence.OrderBy;
 import javax.persistence.Table;
 import javax.persistence.UniqueConstraint;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
-import 
org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
+import 
org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
 import org.apache.fineract.infrastructure.core.serialization.JsonParserHelper;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.portfolio.floatingrates.data.FloatingRateDTO;
 import org.apache.fineract.portfolio.floatingrates.data.FloatingRatePeriodData;
-import org.apache.fineract.useradministration.domain.AppUser;
 
-//TODO: refactor to use AbstractAuditableCustom!
 @Entity
 @Table(name = "m_floating_rates", uniqueConstraints = { 
@UniqueConstraint(columnNames = { "name" }, name = "unq_name") })
-public class FloatingRate extends AbstractPersistableCustom {
+public class FloatingRate extends AbstractAuditableWithUTCDateTimeCustom {
 
     @Column(name = "name", length = 200, unique = true, nullable = false)
     private String name;
@@ -66,34 +61,23 @@ public class FloatingRate extends AbstractPersistableCustom 
{
     @OneToMany(cascade = CascadeType.ALL, mappedBy = "floatingRate", 
orphanRemoval = true, fetch = FetchType.EAGER)
     private List<FloatingRatePeriod> floatingRatePeriods;
 
-    @ManyToOne(optional = true, fetch = FetchType.LAZY)
-    @JoinColumn(name = "createdby_id", nullable = false)
-    private AppUser createdBy;
-
-    @ManyToOne(optional = true, fetch = FetchType.LAZY)
-    @JoinColumn(name = "lastmodifiedby_id", nullable = false)
-    private AppUser modifiedBy;
-
-    @Column(name = "created_date", nullable = false)
-    private LocalDateTime createdOn;
-
-    @Column(name = "lastmodified_date", nullable = false)
-    private LocalDateTime modifiedOn;
+    /*
+     * Deprecated since common Auditable fields were introduced. Columns and 
data left untouched to help migration.
+     *
+     * @Column(name = "created_date", nullable = false) private LocalDateTime 
createdOn;
+     *
+     * @Column(name = "lastmodified_date", nullable = false) private 
LocalDateTime modifiedOn;
+     */
 
     public FloatingRate() {
 
     }
 
-    public FloatingRate(String name, boolean isBaseLendingRate, boolean 
isActive, List<FloatingRatePeriod> floatingRatePeriods,
-            AppUser createdBy, AppUser modifiedBy, LocalDateTime createdOn, 
LocalDateTime modifiedOn) {
+    public FloatingRate(String name, boolean isBaseLendingRate, boolean 
isActive, List<FloatingRatePeriod> floatingRatePeriods) {
         this.name = name;
         this.isBaseLendingRate = isBaseLendingRate;
         this.isActive = isActive;
         this.floatingRatePeriods = floatingRatePeriods;
-        this.createdBy = createdBy;
-        this.createdOn = createdOn;
-        this.modifiedBy = modifiedBy;
-        this.modifiedOn = modifiedOn;
         if (floatingRatePeriods != null) {
             for (FloatingRatePeriod ratePeriod : floatingRatePeriods) {
                 ratePeriod.updateFloatingRate(this);
@@ -101,20 +85,19 @@ public class FloatingRate extends 
AbstractPersistableCustom {
         }
     }
 
-    public static FloatingRate createNew(AppUser currentUser, JsonCommand 
command) {
+    public static FloatingRate createNew(JsonCommand command) {
 
         final String name = command.stringValueOfParameterNamed("name");
         final boolean isBaseLendingRate = 
command.parameterExists("isBaseLendingRate")
                 ? 
command.booleanPrimitiveValueOfParameterNamed("isBaseLendingRate")
                 : false;
         final boolean isActive = command.parameterExists("isActive") ? 
command.booleanPrimitiveValueOfParameterNamed("isActive") : true;
-        final List<FloatingRatePeriod> floatingRatePeriods = 
getRatePeriods(currentUser, command);
-        final LocalDateTime currentDate = DateUtils.getLocalDateTimeOfSystem();
+        final List<FloatingRatePeriod> floatingRatePeriods = 
getRatePeriods(command);
 
-        return new FloatingRate(name, isBaseLendingRate, isActive, 
floatingRatePeriods, currentUser, currentUser, currentDate, currentDate);
+        return new FloatingRate(name, isBaseLendingRate, isActive, 
floatingRatePeriods);
     }
 
-    private static List<FloatingRatePeriod> getRatePeriods(final AppUser 
currentUser, final JsonCommand command) {
+    private static List<FloatingRatePeriod> getRatePeriods(final JsonCommand 
command) {
         if (!command.parameterExists("ratePeriods")) {
             return null;
         }
@@ -129,9 +112,7 @@ public class FloatingRate extends AbstractPersistableCustom 
{
                     ? 
ratePeriodObject.get("isDifferentialToBaseLendingRate").getAsBoolean()
                     : false;
             final boolean isActive = true;
-            final LocalDateTime currentDate = 
DateUtils.getLocalDateTimeOfSystem();
-            ratePeriods.add(new FloatingRatePeriod(fromDate, interestRate, 
isDifferentialToBaseLendingRate, isActive, currentUser,
-                    currentUser, currentDate, currentDate));
+            ratePeriods.add(new FloatingRatePeriod(fromDate, interestRate, 
isDifferentialToBaseLendingRate, isActive));
         }
 
         return ratePeriods;
@@ -153,23 +134,7 @@ public class FloatingRate extends 
AbstractPersistableCustom {
         return this.floatingRatePeriods;
     }
 
-    public AppUser getCreatedBy() {
-        return this.createdBy;
-    }
-
-    public AppUser getModifiedBy() {
-        return this.modifiedBy;
-    }
-
-    public LocalDateTime getCreatedOn() {
-        return this.createdOn;
-    }
-
-    public LocalDateTime getModifiedOn() {
-        return this.modifiedOn;
-    }
-
-    public Map<String, Object> update(final JsonCommand command, final AppUser 
appUser) {
+    public Map<String, Object> update(final JsonCommand command) {
 
         final Map<String, Object> actualChanges = new LinkedHashMap<>(9);
 
@@ -191,24 +156,22 @@ public class FloatingRate extends 
AbstractPersistableCustom {
             this.isActive = newValue;
         }
 
-        final List<FloatingRatePeriod> newRatePeriods = 
getRatePeriods(appUser, command);
+        final List<FloatingRatePeriod> newRatePeriods = 
getRatePeriods(command);
         if (newRatePeriods != null && !newRatePeriods.isEmpty()) {
-            updateRatePeriods(newRatePeriods, appUser);
+            updateRatePeriods(newRatePeriods);
             actualChanges.put("ratePeriods", 
command.jsonFragment("ratePeriods"));
         }
 
         return actualChanges;
     }
 
-    private void updateRatePeriods(final List<FloatingRatePeriod> 
newRatePeriods, final AppUser appUser) {
+    private void updateRatePeriods(final List<FloatingRatePeriod> 
newRatePeriods) {
         final LocalDate today = DateUtils.getBusinessLocalDate();
         if (this.floatingRatePeriods != null) {
             for (FloatingRatePeriod ratePeriod : this.floatingRatePeriods) {
                 LocalDate fromDate = ratePeriod.getFromDate();
                 if (fromDate.isAfter(today)) {
                     ratePeriod.setActive(false);
-                    ratePeriod.setModifiedBy(appUser);
-                    
ratePeriod.setModifiedOn(DateUtils.getLocalDateTimeOfSystem());
                 }
             }
         }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/domain/FloatingRatePeriod.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/domain/FloatingRatePeriod.java
index f85bd8be5..0e244f81f 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/domain/FloatingRatePeriod.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/domain/FloatingRatePeriod.java
@@ -20,22 +20,18 @@ package org.apache.fineract.portfolio.floatingrates.domain;
 
 import java.math.BigDecimal;
 import java.time.LocalDate;
-import java.time.LocalDateTime;
 import javax.persistence.Column;
 import javax.persistence.Entity;
-import javax.persistence.FetchType;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
-import 
org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
+import 
org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
 import org.apache.fineract.portfolio.floatingrates.data.FloatingRateDTO;
 import org.apache.fineract.portfolio.floatingrates.data.FloatingRatePeriodData;
-import org.apache.fineract.useradministration.domain.AppUser;
 
-//TODO: refactor to use AbstractAuditableCustom!
 @Entity
 @Table(name = "m_floating_rates_periods")
-public class FloatingRatePeriod extends AbstractPersistableCustom {
+public class FloatingRatePeriod extends AbstractAuditableWithUTCDateTimeCustom 
{
 
     @ManyToOne
     @JoinColumn(name = "floating_rates_id", nullable = false)
@@ -53,41 +49,30 @@ public class FloatingRatePeriod extends 
AbstractPersistableCustom {
     @Column(name = "is_active", nullable = false)
     private boolean isActive;
 
-    @ManyToOne(optional = true, fetch = FetchType.LAZY)
-    @JoinColumn(name = "createdby_id", nullable = false)
-    private AppUser createdBy;
-
-    @ManyToOne(optional = true, fetch = FetchType.LAZY)
-    @JoinColumn(name = "lastmodifiedby_id", nullable = false)
-    private AppUser modifiedBy;
-
-    @Column(name = "created_date", nullable = false)
-    private LocalDateTime createdOn;
-
-    @Column(name = "lastmodified_date", nullable = false)
-    private LocalDateTime modifiedOn;
+    /*
+     * Deprecated since common Auditable fields were introduced. Columns and 
data left untouched to help migration.
+     *
+     * @Column(name = "created_date", nullable = false) private LocalDateTime 
createdOn;
+     *
+     * @Column(name = "lastmodified_date", nullable = false) private 
LocalDateTime modifiedOn;
+     */
 
     public FloatingRatePeriod() {
 
     }
 
-    public FloatingRatePeriod(LocalDate fromDate, BigDecimal interestRate, 
boolean isDifferentialToBaseLendingRate, boolean isActive,
-            AppUser createdBy, AppUser modifiedBy, LocalDateTime createdOn, 
LocalDateTime modifiedOn) {
+    public FloatingRatePeriod(LocalDate fromDate, BigDecimal interestRate, 
boolean isDifferentialToBaseLendingRate, boolean isActive) {
         this.fromDate = fromDate;
         this.interestRate = interestRate;
         this.isDifferentialToBaseLendingRate = isDifferentialToBaseLendingRate;
         this.isActive = isActive;
-        this.createdBy = createdBy;
-        this.modifiedBy = modifiedBy;
-        this.createdOn = createdOn;
-        this.modifiedOn = modifiedOn;
     }
 
     public void updateFloatingRate(FloatingRate floatingRate) {
         this.floatingRate = floatingRate;
     }
 
-    public FloatingRate getFloatingRatesId() {
+    public FloatingRate getFloatingRate() {
         return this.floatingRate;
     }
 
@@ -107,32 +92,8 @@ public class FloatingRatePeriod extends 
AbstractPersistableCustom {
         return this.isActive;
     }
 
-    public AppUser getCreatedBy() {
-        return this.createdBy;
-    }
-
-    public AppUser getModifiedBy() {
-        return this.modifiedBy;
-    }
-
-    public LocalDateTime getCreatedOn() {
-        return this.createdOn;
-    }
-
-    public LocalDateTime getModifiedOn() {
-        return this.modifiedOn;
-    }
-
-    public void setModifiedBy(AppUser modifiedBy) {
-        this.modifiedBy = modifiedBy;
-    }
-
-    public void setModifiedOn(LocalDateTime modifiedOn) {
-        this.modifiedOn = modifiedOn;
-    }
-
-    public void setActive(boolean b) {
-        this.isActive = b;
+    public void setActive(boolean isActive) {
+        this.isActive = isActive;
     }
 
     public LocalDate fetchFromDate() {
@@ -147,13 +108,7 @@ public class FloatingRatePeriod extends 
AbstractPersistableCustom {
         }
 
         final LocalDate fromDate = getFromDate();
-        final LocalDateTime createdOn = getCreatedOn();
-        final LocalDateTime modifiedOn = getModifiedOn();
-
-        String createdBy = getCreatedBy() != null ? 
getCreatedBy().getUsername() : null;
-        String modifiedBy = getModifiedBy() != null ? 
getModifiedBy().getUsername() : null;
-        return new FloatingRatePeriodData(getId(), fromDate, interest, 
isDifferentialToBaseLendingRate(), isActive(), createdBy, createdOn,
-                modifiedBy, modifiedOn);
+        return new FloatingRatePeriodData(getId(), fromDate, interest, 
isDifferentialToBaseLendingRate(), isActive());
     }
 
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRateWritePlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRateWritePlatformServiceImpl.java
index fabba549c..730b27b07 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRateWritePlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRateWritePlatformServiceImpl.java
@@ -25,11 +25,9 @@ import 
org.apache.fineract.infrastructure.core.api.JsonCommand;
 import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
 import 
org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
 import 
org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
-import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
 import org.apache.fineract.portfolio.floatingrates.domain.FloatingRate;
 import 
org.apache.fineract.portfolio.floatingrates.domain.FloatingRateRepositoryWrapper;
 import 
org.apache.fineract.portfolio.floatingrates.serialization.FloatingRateDataValidator;
-import org.apache.fineract.useradministration.domain.AppUser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -42,14 +40,12 @@ import 
org.springframework.transaction.annotation.Transactional;
 public class FloatingRateWritePlatformServiceImpl implements 
FloatingRateWritePlatformService {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(FloatingRateWritePlatformServiceImpl.class);
-    private final PlatformSecurityContext context;
     private final FloatingRateDataValidator fromApiJsonDeserializer;
     private final FloatingRateRepositoryWrapper floatingRateRepository;
 
     @Autowired
-    public FloatingRateWritePlatformServiceImpl(final PlatformSecurityContext 
context,
-            final FloatingRateDataValidator fromApiJsonDeserializer, final 
FloatingRateRepositoryWrapper floatingRateRepository) {
-        this.context = context;
+    public FloatingRateWritePlatformServiceImpl(final 
FloatingRateDataValidator fromApiJsonDeserializer,
+            final FloatingRateRepositoryWrapper floatingRateRepository) {
         this.fromApiJsonDeserializer = fromApiJsonDeserializer;
         this.floatingRateRepository = floatingRateRepository;
     }
@@ -59,8 +55,7 @@ public class FloatingRateWritePlatformServiceImpl implements 
FloatingRateWritePl
     public CommandProcessingResult createFloatingRate(final JsonCommand 
command) {
         try {
             this.fromApiJsonDeserializer.validateForCreate(command.json());
-            final AppUser currentUser = this.context.authenticatedUser();
-            final FloatingRate newFloatingRate = 
FloatingRate.createNew(currentUser, command);
+            final FloatingRate newFloatingRate = 
FloatingRate.createNew(command);
             this.floatingRateRepository.saveAndFlush(newFloatingRate);
             return new CommandProcessingResultBuilder() //
                     .withCommandId(command.commandId()) //
@@ -82,8 +77,7 @@ public class FloatingRateWritePlatformServiceImpl implements 
FloatingRateWritePl
         try {
             final FloatingRate floatingRateForUpdate = 
this.floatingRateRepository.findOneWithNotFoundDetection(command.entityId());
             this.fromApiJsonDeserializer.validateForUpdate(command.json(), 
floatingRateForUpdate);
-            final AppUser currentUser = this.context.authenticatedUser();
-            final Map<String, Object> changes = 
floatingRateForUpdate.update(command, currentUser);
+            final Map<String, Object> changes = 
floatingRateForUpdate.update(command);
 
             if (!changes.isEmpty()) {
                 this.floatingRateRepository.save(floatingRateForUpdate);
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRatesReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRatesReadPlatformServiceImpl.java
index 7439a93c0..9d8bcea3a 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRatesReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/floatingrates/service/FloatingRatesReadPlatformServiceImpl.java
@@ -24,8 +24,10 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
 import java.util.List;
 import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.portfolio.floatingrates.data.FloatingRateData;
 import org.apache.fineract.portfolio.floatingrates.data.FloatingRatePeriodData;
 import org.apache.fineract.portfolio.floatingrates.data.InterestRatePeriodData;
@@ -106,7 +108,8 @@ public class FloatingRatesReadPlatformServiceImpl 
implements FloatingRatesReadPl
         private final StringBuilder sqlQuery = new 
StringBuilder().append("rate.id as id, ").append("rate.name as name, ")
                 .append("rate.is_base_lending_rate as isBaseLendingRate, 
").append("rate.is_active as isActive, ")
                 .append("crappu.username as createdBy, 
").append("rate.created_date as createdOn, ")
-                .append("moappu.username as modifiedBy, 
").append("rate.lastmodified_date as modifiedOn ")
+                .append("rate.created_on_utc as createdOnUTC, 
").append("moappu.username as modifiedBy, ")
+                .append("rate.lastmodified_date as modifiedOn, 
").append("rate.last_modified_on_utc as modifiedOnUTC ")
                 .append("FROM m_floating_rates as rate ").append("LEFT JOIN 
m_appuser as crappu on rate.createdby_id = crappu.id ")
                 .append("LEFT JOIN m_appuser as moappu on 
rate.lastmodifiedby_id = moappu.id ");
 
@@ -121,10 +124,16 @@ public class FloatingRatesReadPlatformServiceImpl 
implements FloatingRatesReadPl
             final boolean isBaseLendingRate = 
rs.getBoolean("isBaseLendingRate");
             final boolean isActive = rs.getBoolean("isActive");
             final String createdBy = rs.getString("createdBy");
-            final LocalDate createdOn = JdbcSupport.getLocalDate(rs, 
"createdOn");
+            final LocalDateTime createdOnLocal = 
JdbcSupport.getLocalDateTime(rs, "createdOn");
+            final OffsetDateTime createdOnUtc = 
JdbcSupport.getOffsetDateTime(rs, "createdOnUTC");
             final String modifiedBy = rs.getString("modifiedBy");
-            final LocalDate modifiedOn = JdbcSupport.getLocalDate(rs, 
"modifiedOn");
+            final LocalDateTime modifiedOnLocal = 
JdbcSupport.getLocalDateTime(rs, "modifiedOn");
+            final OffsetDateTime modifiedOnUtc = 
JdbcSupport.getOffsetDateTime(rs, "modifiedOnUTC");
             List<FloatingRatePeriodData> ratePeriods = null;
+            final OffsetDateTime createdOn = createdOnUtc != null ? 
createdOnUtc
+                    : OffsetDateTime.of(createdOnLocal, 
DateUtils.getDateTimeZoneOfTenant().getRules().getOffset(createdOnLocal));
+            final OffsetDateTime modifiedOn = modifiedOnUtc != null ? 
modifiedOnUtc
+                    : OffsetDateTime.of(modifiedOnLocal, 
DateUtils.getDateTimeZoneOfTenant().getRules().getOffset(modifiedOnLocal));
             if (addRatePeriods) {
                 FloatingRatePeriodRowMapper ratePeriodMapper = new 
FloatingRatePeriodRowMapper();
                 final String sql = "select " + ratePeriodMapper.schema()
@@ -146,8 +155,9 @@ public class FloatingRatesReadPlatformServiceImpl 
implements FloatingRatesReadPl
                 .append("period.interest_rate as interestRate, ")
                 .append("period.is_differential_to_base_lending_rate as 
isDifferentialToBaseLendingRate, ")
                 .append("period.is_active as isActive, 
").append("crappu.username as createdBy, ")
-                .append("period.created_date as createdOn, 
").append("moappu.username as modifiedBy, ")
-                .append("period.lastmodified_date as modifiedOn 
").append("FROM m_floating_rates_periods as period ")
+                .append("period.created_date as createdOn, 
").append("rate.created_on_utc as createdOnUTC, ")
+                .append("moappu.username as modifiedBy, 
").append("period.lastmodified_date as modifiedOn, ")
+                .append("rate.last_modified_on_utc as modifiedOnUTC 
").append("FROM m_floating_rates_periods as period ")
                 .append("LEFT JOIN m_appuser as crappu on period.createdby_id 
= crappu.id ")
                 .append("LEFT JOIN m_appuser as moappu on 
period.lastmodifiedby_id = moappu.id ");
 
@@ -159,9 +169,15 @@ public class FloatingRatesReadPlatformServiceImpl 
implements FloatingRatesReadPl
             final boolean isDifferentialToBaseLendingRate = 
rs.getBoolean("isDifferentialToBaseLendingRate");
             final boolean isActive = rs.getBoolean("isActive");
             final String createdBy = rs.getString("createdBy");
-            final LocalDateTime createdOn = JdbcSupport.getLocalDateTime(rs, 
"createdOn");
+            final LocalDateTime createdOnLocal = 
JdbcSupport.getLocalDateTime(rs, "createdOn");
+            final OffsetDateTime createdOnUtc = 
JdbcSupport.getOffsetDateTime(rs, "createdOnUTC");
             final String modifiedBy = rs.getString("modifiedBy");
-            final LocalDateTime modifiedOn = JdbcSupport.getLocalDateTime(rs, 
"modifiedOn");
+            final LocalDateTime modifiedOnLocal = 
JdbcSupport.getLocalDateTime(rs, "modifiedOn");
+            final OffsetDateTime modifiedOnUtc = 
JdbcSupport.getOffsetDateTime(rs, "modifiedOnUTC");
+            final OffsetDateTime createdOn = createdOnUtc != null ? 
createdOnUtc
+                    : OffsetDateTime.of(createdOnLocal, 
DateUtils.getDateTimeZoneOfTenant().getRules().getOffset(createdOnLocal));
+            final OffsetDateTime modifiedOn = modifiedOnUtc != null ? 
modifiedOnUtc
+                    : OffsetDateTime.of(modifiedOnLocal, 
DateUtils.getDateTimeZoneOfTenant().getRules().getOffset(modifiedOnLocal));
             return new FloatingRatePeriodData(id, fromDate, interestRate, 
isDifferentialToBaseLendingRate, isActive, createdBy, createdOn,
                     modifiedBy, modifiedOn);
         }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/addaccrualentries/AddAccrualEntriesTasklet.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/addaccrualentries/AddAccrualEntriesTasklet.java
index d5777093c..12be78e39 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/addaccrualentries/AddAccrualEntriesTasklet.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/addaccrualentries/AddAccrualEntriesTasklet.java
@@ -45,15 +45,15 @@ public class AddAccrualEntriesTasklet implements Tasklet {
 
     @Override
     public RepeatStatus execute(StepContribution contribution, ChunkContext 
chunkContext) throws Exception {
-        Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas = 
loanReadPlatformService.retriveScheduleAccrualData();
+        Collection<LoanScheduleAccrualData> loanScheduleAccrualDataList = 
loanReadPlatformService.retriveScheduleAccrualData();
         Map<Long, Collection<LoanScheduleAccrualData>> loanDataMap = new 
HashMap<>();
-        for (final LoanScheduleAccrualData accrualData : 
loanScheduleAccrualDatas) {
+        for (final LoanScheduleAccrualData accrualData : 
loanScheduleAccrualDataList) {
             if (loanDataMap.containsKey(accrualData.getLoanId())) {
                 loanDataMap.get(accrualData.getLoanId()).add(accrualData);
             } else {
-                Collection<LoanScheduleAccrualData> accrualDatas = new 
ArrayList<>();
-                accrualDatas.add(accrualData);
-                loanDataMap.put(accrualData.getLoanId(), accrualDatas);
+                Collection<LoanScheduleAccrualData> accrualDataList = new 
ArrayList<>();
+                accrualDataList.add(accrualData);
+                loanDataMap.put(accrualData.getLoanId(), accrualDataList);
             }
         }
 
@@ -62,7 +62,7 @@ public class AddAccrualEntriesTasklet implements Tasklet {
             try {
                 
loanAccrualWritePlatformService.addAccrualAccounting(mapEntry.getKey(), 
mapEntry.getValue());
             } catch (Exception e) {
-                log.error("Failed to add accural transaction for loan {}", 
mapEntry.getKey(), e);
+                log.error("Failed to add accrual transaction for loan {}", 
mapEntry.getKey(), e);
                 errors.add(e);
             }
         }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
index bdaf03a10..f181bd81f 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualPlatformServiceImpl.java
@@ -39,31 +39,31 @@ public class LoanAccrualPlatformServiceImpl implements 
LoanAccrualPlatformServic
     private final LoanAccrualWritePlatformService 
loanAccrualWritePlatformService;
 
     @Override
-    public void addPeriodicAccruals(final LocalDate tilldate) throws 
JobExecutionException {
-        Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas = 
this.loanReadPlatformService.retrivePeriodicAccrualData(tilldate);
-        addPeriodicAccruals(tilldate, loanScheduleAccrualDatas);
+    public void addPeriodicAccruals(final LocalDate tillDate) throws 
JobExecutionException {
+        Collection<LoanScheduleAccrualData> loanScheduleAccrualDataList = 
this.loanReadPlatformService.retrivePeriodicAccrualData(tillDate);
+        addPeriodicAccruals(tillDate, loanScheduleAccrualDataList);
     }
 
     @Override
-    public void addPeriodicAccruals(final LocalDate tilldate, 
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas)
+    public void addPeriodicAccruals(final LocalDate tillDate, 
Collection<LoanScheduleAccrualData> loanScheduleAccrualDataList)
             throws JobExecutionException {
         Map<Long, Collection<LoanScheduleAccrualData>> loanDataMap = new 
HashMap<>();
-        for (final LoanScheduleAccrualData accrualData : 
loanScheduleAccrualDatas) {
+        for (final LoanScheduleAccrualData accrualData : 
loanScheduleAccrualDataList) {
             if (loanDataMap.containsKey(accrualData.getLoanId())) {
                 loanDataMap.get(accrualData.getLoanId()).add(accrualData);
             } else {
-                Collection<LoanScheduleAccrualData> accrualDatas = new 
ArrayList<>();
-                accrualDatas.add(accrualData);
-                loanDataMap.put(accrualData.getLoanId(), accrualDatas);
+                Collection<LoanScheduleAccrualData> accrualDataList = new 
ArrayList<>();
+                accrualDataList.add(accrualData);
+                loanDataMap.put(accrualData.getLoanId(), accrualDataList);
             }
         }
 
         List<Throwable> errors = new ArrayList<>();
         for (Map.Entry<Long, Collection<LoanScheduleAccrualData>> mapEntry : 
loanDataMap.entrySet()) {
             try {
-                
this.loanAccrualWritePlatformService.addPeriodicAccruals(tilldate, 
mapEntry.getKey(), mapEntry.getValue());
+                
this.loanAccrualWritePlatformService.addPeriodicAccruals(tillDate, 
mapEntry.getKey(), mapEntry.getValue());
             } catch (Exception e) {
-                log.error("Failed to add accural transaction for loan {}", 
mapEntry.getKey(), e);
+                log.error("Failed to add accrual transaction for loan {}", 
mapEntry.getKey(), e);
                 errors.add(e);
             }
         }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java
index 2042b7cc2..2f21fffdc 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualWritePlatformServiceImpl.java
@@ -32,6 +32,7 @@ import lombok.RequiredArgsConstructor;
 import 
org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import 
org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
+import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
 import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
 import 
org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
 import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
@@ -47,6 +48,7 @@ import 
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
 import 
org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData;
 import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
+import org.apache.fineract.useradministration.domain.AppUser;
 import org.apache.fineract.useradministration.domain.AppUserRepositoryWrapper;
 import org.springframework.dao.DataAccessException;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -63,63 +65,62 @@ public class LoanAccrualWritePlatformServiceImpl implements 
LoanAccrualWritePlat
     private final DatabaseSpecificSQLGenerator sqlGenerator;
     private final JournalEntryWritePlatformService 
journalEntryWritePlatformService;
     private final AppUserRepositoryWrapper userRepository;
+    private final PlatformSecurityContext context;
     private final LoanRepositoryWrapper loanRepositoryWrapper;
     private final ApplicationCurrencyRepositoryWrapper 
applicationCurrencyRepository;
 
     @Override
     @Transactional
-    public void addAccrualAccounting(final Long loanId, final 
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas)
-            throws Exception {
+    public void addAccrualAccounting(final Long loanId, final 
Collection<LoanScheduleAccrualData> loanScheduleAccrualData) {
         Collection<LoanChargeData> chargeData = 
this.loanChargeReadPlatformService.retrieveLoanChargesForAccural(loanId);
         Collection<LoanSchedulePeriodData> loanWaiverScheduleData = new 
ArrayList<>(1);
-        Collection<LoanTransactionData> loanWaiverTansactionData = new 
ArrayList<>(1);
+        Collection<LoanTransactionData> loanWaiverTransactionData = new 
ArrayList<>(1);
 
-        for (final LoanScheduleAccrualData accrualData : 
loanScheduleAccrualDatas) {
+        for (final LoanScheduleAccrualData accrualData : 
loanScheduleAccrualData) {
             if (accrualData.getWaivedInterestIncome() != null && 
loanWaiverScheduleData.isEmpty()) {
                 loanWaiverScheduleData = 
this.loanReadPlatformService.fetchWaiverInterestRepaymentData(accrualData.getLoanId());
-                loanWaiverTansactionData = 
this.loanReadPlatformService.retrieveWaiverLoanTransactions(accrualData.getLoanId());
+                loanWaiverTransactionData = 
this.loanReadPlatformService.retrieveWaiverLoanTransactions(accrualData.getLoanId());
             }
             updateCharges(chargeData, accrualData, 
accrualData.getFromDateAsLocaldate(), accrualData.getDueDateAsLocaldate());
-            updateInterestIncome(accrualData, loanWaiverTansactionData, 
loanWaiverScheduleData, accrualData.getDueDateAsLocaldate());
+            updateInterestIncome(accrualData, loanWaiverTransactionData, 
loanWaiverScheduleData, accrualData.getDueDateAsLocaldate());
             addAccrualAccounting(accrualData);
         }
     }
 
     @Override
     @Transactional
-    public void addPeriodicAccruals(final LocalDate tilldate, Long loanId, 
Collection<LoanScheduleAccrualData> loanScheduleAccrualDatas)
-            throws Exception {
+    public void addPeriodicAccruals(final LocalDate tillDate, Long loanId, 
Collection<LoanScheduleAccrualData> loanScheduleAccrualData) {
         boolean firstTime = true;
-        LocalDate accruredTill = null;
+        LocalDate accruedTill = null;
         Collection<LoanChargeData> chargeData = 
this.loanChargeReadPlatformService.retrieveLoanChargesForAccural(loanId);
         Collection<LoanSchedulePeriodData> loanWaiverScheduleData = new 
ArrayList<>(1);
-        Collection<LoanTransactionData> loanWaiverTansactionData = new 
ArrayList<>(1);
-        for (final LoanScheduleAccrualData accrualData : 
loanScheduleAccrualDatas) {
+        Collection<LoanTransactionData> loanWaiverTransactionData = new 
ArrayList<>(1);
+        for (final LoanScheduleAccrualData accrualData : 
loanScheduleAccrualData) {
             if (accrualData.getWaivedInterestIncome() != null && 
loanWaiverScheduleData.isEmpty()) {
                 loanWaiverScheduleData = 
this.loanReadPlatformService.fetchWaiverInterestRepaymentData(accrualData.getLoanId());
-                loanWaiverTansactionData = 
this.loanReadPlatformService.retrieveWaiverLoanTransactions(accrualData.getLoanId());
+                loanWaiverTransactionData = 
this.loanReadPlatformService.retrieveWaiverLoanTransactions(accrualData.getLoanId());
             }
 
-            if (accrualData.getDueDateAsLocaldate().isAfter(tilldate)) {
-                if (accruredTill == null || firstTime) {
-                    accruredTill = accrualData.getAccruedTill();
+            if (accrualData.getDueDateAsLocaldate().isAfter(tillDate)) {
+                if (accruedTill == null || firstTime) {
+                    accruedTill = accrualData.getAccruedTill();
                     firstTime = false;
                 }
-                if (accruredTill == null || accruredTill.isBefore(tilldate)) {
-                    updateCharges(chargeData, accrualData, 
accrualData.getFromDateAsLocaldate(), tilldate);
-                    updateInterestIncome(accrualData, 
loanWaiverTansactionData, loanWaiverScheduleData, tilldate);
-                    addAccrualTillSpecificDate(tilldate, accrualData);
+                if (accruedTill == null || accruedTill.isBefore(tillDate)) {
+                    updateCharges(chargeData, accrualData, 
accrualData.getFromDateAsLocaldate(), tillDate);
+                    updateInterestIncome(accrualData, 
loanWaiverTransactionData, loanWaiverScheduleData, tillDate);
+                    addAccrualTillSpecificDate(tillDate, accrualData);
                 }
             } else {
                 updateCharges(chargeData, accrualData, 
accrualData.getFromDateAsLocaldate(), accrualData.getDueDateAsLocaldate());
-                updateInterestIncome(accrualData, loanWaiverTansactionData, 
loanWaiverScheduleData, tilldate);
+                updateInterestIncome(accrualData, loanWaiverTransactionData, 
loanWaiverScheduleData, tillDate);
                 addAccrualAccounting(accrualData);
-                accruredTill = accrualData.getDueDateAsLocaldate();
+                accruedTill = accrualData.getDueDateAsLocaldate();
             }
         }
     }
 
-    private void addAccrualTillSpecificDate(final LocalDate tilldate, final 
LoanScheduleAccrualData accrualData) throws Exception {
+    private void addAccrualTillSpecificDate(final LocalDate tillDate, final 
LoanScheduleAccrualData accrualData) {
         LocalDate interestStartDate = accrualData.getFromDateAsLocaldate();
         if (accrualData.getInterestCalculatedFrom() != null
                 && 
accrualData.getFromDateAsLocaldate().isBefore(accrualData.getInterestCalculatedFrom()))
 {
@@ -133,150 +134,150 @@ public class LoanAccrualWritePlatformServiceImpl 
implements LoanAccrualWritePlat
         int totalNumberOfDays = 
Math.toIntExact(ChronoUnit.DAYS.between(interestStartDate, 
accrualData.getDueDateAsLocaldate()));
         LocalDate startDate = accrualData.getFromDateAsLocaldate();
         if (accrualData.getInterestCalculatedFrom() != null && 
startDate.isBefore(accrualData.getInterestCalculatedFrom())) {
-            if (accrualData.getInterestCalculatedFrom().isBefore(tilldate)) {
+            if (accrualData.getInterestCalculatedFrom().isBefore(tillDate)) {
                 startDate = accrualData.getInterestCalculatedFrom();
             } else {
-                startDate = tilldate;
+                startDate = tillDate;
             }
         }
-        int daysToBeAccrued = 
Math.toIntExact(ChronoUnit.DAYS.between(startDate, tilldate));
+        int daysToBeAccrued = 
Math.toIntExact(ChronoUnit.DAYS.between(startDate, tillDate));
         double interestPerDay = accrualData.getAccruableIncome().doubleValue() 
/ totalNumberOfDays;
         BigDecimal amount = BigDecimal.ZERO;
-        BigDecimal interestportion = null;
-        BigDecimal feeportion = accrualData.getDueDateFeeIncome();
-        BigDecimal penaltyportion = accrualData.getDueDatePenaltyIncome();
+        BigDecimal interestPortion;
+        BigDecimal feePortion = accrualData.getDueDateFeeIncome();
+        BigDecimal penaltyPortion = accrualData.getDueDatePenaltyIncome();
         if (daysToBeAccrued >= totalNumberOfDays) {
-            interestportion = accrualData.getAccruableIncome();
+            interestPortion = accrualData.getAccruableIncome();
         } else {
-            double iterest = interestPerDay * daysToBeAccrued;
-            interestportion = BigDecimal.valueOf(iterest);
+            interestPortion = BigDecimal.valueOf(interestPerDay * 
daysToBeAccrued);
         }
-        interestportion = 
interestportion.setScale(accrualData.getCurrencyData().decimalPlaces(), 
MoneyHelper.getRoundingMode());
+        interestPortion = 
interestPortion.setScale(accrualData.getCurrencyData().decimalPlaces(), 
MoneyHelper.getRoundingMode());
 
         BigDecimal totalAccInterest = accrualData.getAccruedInterestIncome();
         BigDecimal totalAccPenalty = accrualData.getAccruedPenaltyIncome();
         BigDecimal totalAccFee = accrualData.getAccruedFeeIncome();
 
-        if (interestportion != null) {
-            if (totalAccInterest == null) {
-                totalAccInterest = BigDecimal.ZERO;
-            }
-            interestportion = interestportion.subtract(totalAccInterest);
-            amount = amount.add(interestportion);
-            totalAccInterest = totalAccInterest.add(interestportion);
-            if (interestportion.compareTo(BigDecimal.ZERO) == 0) {
-                interestportion = null;
-            }
+        if (totalAccInterest == null) {
+            totalAccInterest = BigDecimal.ZERO;
+        }
+        interestPortion = interestPortion.subtract(totalAccInterest);
+        amount = amount.add(interestPortion);
+        totalAccInterest = totalAccInterest.add(interestPortion);
+        if (interestPortion.compareTo(BigDecimal.ZERO) == 0) {
+            interestPortion = null;
         }
-        if (feeportion != null) {
+        if (feePortion != null) {
             if (totalAccFee == null) {
                 totalAccFee = BigDecimal.ZERO;
             }
-            feeportion = feeportion.subtract(totalAccFee);
-            amount = amount.add(feeportion);
-            totalAccFee = totalAccFee.add(feeportion);
-            if (feeportion.compareTo(BigDecimal.ZERO) == 0) {
-                feeportion = null;
+            feePortion = feePortion.subtract(totalAccFee);
+            amount = amount.add(feePortion);
+            totalAccFee = totalAccFee.add(feePortion);
+            if (feePortion.compareTo(BigDecimal.ZERO) == 0) {
+                feePortion = null;
             }
         }
 
-        if (penaltyportion != null) {
+        if (penaltyPortion != null) {
             if (totalAccPenalty == null) {
                 totalAccPenalty = BigDecimal.ZERO;
             }
-            penaltyportion = penaltyportion.subtract(totalAccPenalty);
-            amount = amount.add(penaltyportion);
-            totalAccPenalty = totalAccPenalty.add(penaltyportion);
-            if (penaltyportion.compareTo(BigDecimal.ZERO) == 0) {
-                penaltyportion = null;
+            penaltyPortion = penaltyPortion.subtract(totalAccPenalty);
+            amount = amount.add(penaltyPortion);
+            totalAccPenalty = totalAccPenalty.add(penaltyPortion);
+            if (penaltyPortion.compareTo(BigDecimal.ZERO) == 0) {
+                penaltyPortion = null;
             }
         }
         if (amount.compareTo(BigDecimal.ZERO) > 0) {
-            addAccrualAccounting(accrualData, amount, interestportion, 
totalAccInterest, feeportion, totalAccFee, penaltyportion,
-                    totalAccPenalty, tilldate);
+            addAccrualAccounting(accrualData, amount, interestPortion, 
totalAccInterest, feePortion, totalAccFee, penaltyPortion,
+                    totalAccPenalty, tillDate);
         }
     }
 
     @Transactional
-    public void addAccrualAccounting(LoanScheduleAccrualData 
scheduleAccrualData) throws Exception {
+    public void addAccrualAccounting(LoanScheduleAccrualData 
scheduleAccrualData) {
 
         BigDecimal amount = BigDecimal.ZERO;
-        BigDecimal interestportion = null;
+        BigDecimal interestPortion = null;
         BigDecimal totalAccInterest = null;
         if (scheduleAccrualData.getAccruableIncome() != null) {
-            interestportion = scheduleAccrualData.getAccruableIncome();
-            totalAccInterest = interestportion;
+            interestPortion = scheduleAccrualData.getAccruableIncome();
+            totalAccInterest = interestPortion;
             if (scheduleAccrualData.getAccruedInterestIncome() != null) {
-                interestportion = 
interestportion.subtract(scheduleAccrualData.getAccruedInterestIncome());
+                interestPortion = 
interestPortion.subtract(scheduleAccrualData.getAccruedInterestIncome());
             }
-            amount = amount.add(interestportion);
-            if (interestportion.compareTo(BigDecimal.ZERO) == 0) {
-                interestportion = null;
+            amount = amount.add(interestPortion);
+            if (interestPortion.compareTo(BigDecimal.ZERO) == 0) {
+                interestPortion = null;
             }
         }
 
-        BigDecimal feeportion = null;
+        BigDecimal feePortion = null;
         BigDecimal totalAccFee = null;
         if (scheduleAccrualData.getDueDateFeeIncome() != null) {
-            feeportion = scheduleAccrualData.getDueDateFeeIncome();
-            totalAccFee = feeportion;
+            feePortion = scheduleAccrualData.getDueDateFeeIncome();
+            totalAccFee = feePortion;
             if (scheduleAccrualData.getAccruedFeeIncome() != null) {
-                feeportion = 
feeportion.subtract(scheduleAccrualData.getAccruedFeeIncome());
+                feePortion = 
feePortion.subtract(scheduleAccrualData.getAccruedFeeIncome());
             }
-            amount = amount.add(feeportion);
-            if (feeportion.compareTo(BigDecimal.ZERO) == 0) {
-                feeportion = null;
+            amount = amount.add(feePortion);
+            if (feePortion.compareTo(BigDecimal.ZERO) == 0) {
+                feePortion = null;
             }
         }
 
-        BigDecimal penaltyportion = null;
+        BigDecimal penaltyPortion = null;
         BigDecimal totalAccPenalty = null;
         if (scheduleAccrualData.getDueDatePenaltyIncome() != null) {
-            penaltyportion = scheduleAccrualData.getDueDatePenaltyIncome();
-            totalAccPenalty = penaltyportion;
+            penaltyPortion = scheduleAccrualData.getDueDatePenaltyIncome();
+            totalAccPenalty = penaltyPortion;
             if (scheduleAccrualData.getAccruedPenaltyIncome() != null) {
-                penaltyportion = 
penaltyportion.subtract(scheduleAccrualData.getAccruedPenaltyIncome());
+                penaltyPortion = 
penaltyPortion.subtract(scheduleAccrualData.getAccruedPenaltyIncome());
             }
-            amount = amount.add(penaltyportion);
-            if (penaltyportion.compareTo(BigDecimal.ZERO) == 0) {
-                penaltyportion = null;
+            amount = amount.add(penaltyPortion);
+            if (penaltyPortion.compareTo(BigDecimal.ZERO) == 0) {
+                penaltyPortion = null;
             }
         }
         if (amount.compareTo(BigDecimal.ZERO) > 0) {
-            addAccrualAccounting(scheduleAccrualData, amount, interestportion, 
totalAccInterest, feeportion, totalAccFee, penaltyportion,
+            addAccrualAccounting(scheduleAccrualData, amount, interestPortion, 
totalAccInterest, feePortion, totalAccFee, penaltyPortion,
                     totalAccPenalty, 
scheduleAccrualData.getDueDateAsLocaldate());
         }
     }
 
-    private void addAccrualAccounting(LoanScheduleAccrualData 
scheduleAccrualData, BigDecimal amount, BigDecimal interestportion,
-            BigDecimal totalAccInterest, BigDecimal feeportion, BigDecimal 
totalAccFee, BigDecimal penaltyportion,
+    private void addAccrualAccounting(LoanScheduleAccrualData 
scheduleAccrualData, BigDecimal amount, BigDecimal interestPortion,
+            BigDecimal totalAccInterest, BigDecimal feePortion, BigDecimal 
totalAccFee, BigDecimal penaltyPortion,
             BigDecimal totalAccPenalty, final LocalDate accruedTill) throws 
DataAccessException {
+        AppUser user = context.authenticatedUser();
         String transactionSql = "INSERT INTO m_loan_transaction  
(loan_id,office_id,is_reversed,transaction_type_enum,transaction_date,amount,interest_portion_derived,"
-                + 
"fee_charges_portion_derived,penalty_charges_portion_derived, 
submitted_on_date) VALUES (?, ?, false, ?, ?, ?, ?, ?, ?, ?)";
+                + 
"fee_charges_portion_derived,penalty_charges_portion_derived, 
submitted_on_date, created_by, last_modified_by, created_on_utc, 
last_modified_on_utc) "
+                + "VALUES (?, ?, false, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
         this.jdbcTemplate.update(transactionSql, 
scheduleAccrualData.getLoanId(), scheduleAccrualData.getOfficeId(),
-                LoanTransactionType.ACCRUAL.getValue(), accruedTill, amount, 
interestportion, feeportion, penaltyportion,
-                DateUtils.getBusinessLocalDate());
-        @SuppressWarnings("deprecation")
-        final Long transactonId = this.jdbcTemplate.queryForObject("SELECT " + 
sqlGenerator.lastInsertId(), Long.class); // NOSONAR
+                LoanTransactionType.ACCRUAL.getValue(), accruedTill, amount, 
interestPortion, feePortion, penaltyPortion,
+                DateUtils.getBusinessLocalDate(), user.getId(), user.getId(), 
DateUtils.getOffsetDateTimeOfTenant(),
+                DateUtils.getOffsetDateTimeOfTenant());
+        final Long transactionId = this.jdbcTemplate.queryForObject("SELECT " 
+ sqlGenerator.lastInsertId(), Long.class); // NOSONAR
 
         Map<LoanChargeData, BigDecimal> applicableCharges = 
scheduleAccrualData.getApplicableCharges();
-        String chargespaidSql = "INSERT INTO m_loan_charge_paid_by 
(loan_transaction_id, loan_charge_id, amount,installment_number) VALUES 
(?,?,?,?)";
+        String chargesPaidSql = "INSERT INTO m_loan_charge_paid_by 
(loan_transaction_id, loan_charge_id, amount,installment_number) VALUES 
(?,?,?,?)";
         for (Map.Entry<LoanChargeData, BigDecimal> entry : 
applicableCharges.entrySet()) {
             LoanChargeData chargeData = entry.getKey();
-            this.jdbcTemplate.update(chargespaidSql, transactonId, 
chargeData.getId(), entry.getValue(),
+            this.jdbcTemplate.update(chargesPaidSql, transactionId, 
chargeData.getId(), entry.getValue(),
                     scheduleAccrualData.getInstallmentNumber());
         }
 
-        Map<String, Object> transactionMap = toMapData(transactonId, amount, 
interestportion, feeportion, penaltyportion,
+        Map<String, Object> transactionMap = toMapData(transactionId, amount, 
interestPortion, feePortion, penaltyPortion,
                 scheduleAccrualData, accruedTill);
 
-        String repaymetUpdatesql = "UPDATE m_loan_repayment_schedule SET 
accrual_interest_derived=?, accrual_fee_charges_derived=?, "
+        String repaymentUpdateSql = "UPDATE m_loan_repayment_schedule SET 
accrual_interest_derived=?, accrual_fee_charges_derived=?, "
                 + "accrual_penalty_charges_derived=? WHERE  id=?";
-        this.jdbcTemplate.update(repaymetUpdatesql, totalAccInterest, 
totalAccFee, totalAccPenalty,
+        this.jdbcTemplate.update(repaymentUpdateSql, totalAccInterest, 
totalAccFee, totalAccPenalty,
                 scheduleAccrualData.getRepaymentScheduleId());
 
-        String updateLoan = "UPDATE m_loan  SET accrued_till=?  WHERE  id=?";
-        this.jdbcTemplate.update(updateLoan, accruedTill, 
scheduleAccrualData.getLoanId());
+        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(),
+                scheduleAccrualData.getLoanId());
         final Map<String, Object> accountingBridgeData = 
deriveAccountingBridgeData(scheduleAccrualData, transactionMap);
         
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
     }
@@ -301,9 +302,9 @@ public class LoanAccrualWritePlatformServiceImpl implements 
LoanAccrualWritePlat
         return accountingBridgeData;
     }
 
-    public Map<String, Object> toMapData(final Long id, final BigDecimal 
amount, final BigDecimal interestportion,
-            final BigDecimal feeportion, final BigDecimal penaltyportion, 
final LoanScheduleAccrualData loanScheduleAccrualData,
-            final LocalDate accruredTill) {
+    public Map<String, Object> toMapData(final Long id, final BigDecimal 
amount, final BigDecimal interestPortion,
+            final BigDecimal feePortion, final BigDecimal penaltyPortion, 
final LoanScheduleAccrualData loanScheduleAccrualData,
+            final LocalDate accruedTill) {
         final Map<String, Object> thisTransactionData = new LinkedHashMap<>();
 
         final LoanTransactionEnumData transactionType = 
LoanEnumerations.transactionType(LoanTransactionType.ACCRUAL);
@@ -312,13 +313,13 @@ public class LoanAccrualWritePlatformServiceImpl 
implements LoanAccrualWritePlat
         thisTransactionData.put("officeId", 
loanScheduleAccrualData.getOfficeId());
         thisTransactionData.put("type", transactionType);
         thisTransactionData.put("reversed", false);
-        thisTransactionData.put("date", accruredTill);
+        thisTransactionData.put("date", accruedTill);
         thisTransactionData.put("currency", 
loanScheduleAccrualData.getCurrencyData());
         thisTransactionData.put("amount", amount);
         thisTransactionData.put("principalPortion", null);
-        thisTransactionData.put("interestPortion", interestportion);
-        thisTransactionData.put("feeChargesPortion", feeportion);
-        thisTransactionData.put("penaltyChargesPortion", penaltyportion);
+        thisTransactionData.put("interestPortion", interestPortion);
+        thisTransactionData.put("feeChargesPortion", feePortion);
+        thisTransactionData.put("penaltyChargesPortion", penaltyPortion);
         thisTransactionData.put("overPaymentPortion", null);
 
         Map<LoanChargeData, BigDecimal> applicableCharges = 
loanScheduleAccrualData.getApplicableCharges();
@@ -411,8 +412,8 @@ public class LoanAccrualWritePlatformServiceImpl implements 
LoanAccrualWritePlat
     }
 
     private void updateInterestIncome(final LoanScheduleAccrualData 
accrualData,
-            final Collection<LoanTransactionData> loanWaiverTansactions, final 
Collection<LoanSchedulePeriodData> loanSchedulePeriodDatas,
-            final LocalDate tilldate) {
+            final Collection<LoanTransactionData> loanWaiverTransactions,
+            final Collection<LoanSchedulePeriodData> 
loanSchedulePeriodDataList, final LocalDate tillDate) {
 
         BigDecimal interestIncome = BigDecimal.ZERO;
         if (accrualData.getInterestIncome() != null) {
@@ -424,17 +425,17 @@ public class LoanAccrualWritePlatformServiceImpl 
implements LoanAccrualWritePlat
             BigDecimal remainingAmt = BigDecimal.ZERO;
             Collection<LoanTransactionData> loanTransactionDatas = new 
ArrayList<>();
 
-            for (LoanTransactionData loanTransactionData : 
loanWaiverTansactions) {
+            for (LoanTransactionData loanTransactionData : 
loanWaiverTransactions) {
                 if 
(!loanTransactionData.dateOf().isAfter(accrualData.getFromDateAsLocaldate())
                         || 
(loanTransactionData.dateOf().isAfter(accrualData.getFromDateAsLocaldate())
                                 && 
!loanTransactionData.dateOf().isAfter(accrualData.getDueDateAsLocaldate())
-                                && 
!loanTransactionData.dateOf().isAfter(tilldate))) {
+                                && 
!loanTransactionData.dateOf().isAfter(tillDate))) {
                     loanTransactionDatas.add(loanTransactionData);
                 }
             }
 
             Iterator<LoanTransactionData> iterator = 
loanTransactionDatas.iterator();
-            for (LoanSchedulePeriodData loanSchedulePeriodData : 
loanSchedulePeriodDatas) {
+            for (LoanSchedulePeriodData loanSchedulePeriodData : 
loanSchedulePeriodDataList) {
                 if (recognized.compareTo(BigDecimal.ZERO) <= 0 && 
unrecognized.compareTo(BigDecimal.ZERO) <= 0 && iterator.hasNext()) {
                     LoanTransactionData loanTransactionData = iterator.next();
                     recognized = 
recognized.add(loanTransactionData.getInterestPortion());
diff --git 
a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml 
b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml
index 7f3d90b79..cb283230e 100644
--- 
a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml
+++ 
b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml
@@ -42,4 +42,6 @@
     <include file="parts/0020_add_audit_entries.xml" 
relativeToChangelogFile="true"/>
     <include file="parts/0021_add_spring_batch_db_structure.xml" 
relativeToChangelogFile="true"/>
     <include file="parts/0022_add_batch_business_step_configuration_table.xml" 
relativeToChangelogFile="true"/>
+    <include file="parts/0023_use_the_proper_date_or_datetime_type.xml" 
relativeToChangelogFile="true"/>
+    <include file="parts/0024_add_audit_entries.xml" 
relativeToChangelogFile="true"/>
 </databaseChangeLog>
diff --git 
a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0023_use_the_proper_date_or_datetime_type.xml
 
b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0023_use_the_proper_date_or_datetime_type.xml
new file mode 100644
index 000000000..2a2ea0562
--- /dev/null
+++ 
b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0023_use_the_proper_date_or_datetime_type.xml
@@ -0,0 +1,41 @@
+<?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">
+        <modifyDataType tableName="m_client_non_person" 
columnName="incorp_validity_till" newDataType="date"/>
+        <modifyDataType tableName="m_floating_rates_periods" 
columnName="from_date" newDataType="date"/>
+        <modifyDataType tableName="m_holiday" columnName="from_date" 
newDataType="date"/>
+        <modifyDataType tableName="m_holiday" columnName="to_date" 
newDataType="date"/>
+        <modifyDataType tableName="m_holiday" 
columnName="repayments_rescheduled_to" newDataType="date"/>
+        <modifyDataType tableName="m_loan_disbursement_detail" 
columnName="expected_disburse_date" newDataType="date"/>
+        <modifyDataType tableName="m_loan_disbursement_detail" 
columnName="disbursedon_date" newDataType="date"/>
+        <modifyDataType tableName="m_share_product" columnName="start_date" 
newDataType="date"/>
+        <modifyDataType tableName="m_share_product" columnName="end_date" 
newDataType="date"/>
+        <modifyDataType tableName="m_surveys" columnName="valid_from" 
newDataType="date"/>
+        <modifyDataType tableName="m_surveys" columnName="valid_to" 
newDataType="date"/>
+    </changeSet>
+
+
+</databaseChangeLog>
diff --git 
a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0024_add_audit_entries.xml
 
b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0024_add_audit_entries.xml
new file mode 100644
index 000000000..739751d04
--- /dev/null
+++ 
b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0024_add_audit_entries.xml
@@ -0,0 +1,241 @@
+<?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";>
+    <!--Client-->
+    <changeSet id="client-4" author="fineract" context="mysql">
+        <preConditions onFail="MARK_RAN">
+            <sqlCheck expectedResult="0">select count(*) from 
m_client</sqlCheck>
+        </preConditions>
+        <addNotNullConstraint tableName="m_client" columnName="created_on_utc" 
columnDataType="DATETIME"/>
+        <addNotNullConstraint tableName="m_client" columnName="created_by" 
columnDataType="BIGINT"/>
+        <addNotNullConstraint tableName="m_client" 
columnName="last_modified_on_utc" columnDataType="DATETIME"/>
+        <addNotNullConstraint tableName="m_client" 
columnName="last_modified_by" columnDataType="BIGINT"/>
+    </changeSet>
+    <changeSet id="client-4" author="fineract" context="postgresql">
+        <preConditions onFail="MARK_RAN">
+            <sqlCheck expectedResult="0">select count(*) from 
m_client</sqlCheck>
+        </preConditions>
+        <addNotNullConstraint tableName="m_client" columnName="created_on_utc" 
columnDataType="TIMESTAMP WITH TIME ZONE"/>
+        <addNotNullConstraint tableName="m_client" columnName="created_by" 
columnDataType="BIGINT"/>
+        <addNotNullConstraint tableName="m_client" 
columnName="last_modified_on_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
+        <addNotNullConstraint tableName="m_client" 
columnName="last_modified_by" columnDataType="BIGINT"/>
+    </changeSet>
+    <!--Loan-->
+    <changeSet id="loan-7" author="fineract" context="mysql">
+        <preConditions onFail="MARK_RAN">
+            <sqlCheck expectedResult="0">select count(*) from m_loan</sqlCheck>
+        </preConditions>
+        <addNotNullConstraint tableName="m_loan" columnName="created_on_utc" 
columnDataType="DATETIME"/>
+        <addNotNullConstraint tableName="m_loan" columnName="created_by" 
columnDataType="BIGINT"/>
+        <addNotNullConstraint tableName="m_loan" 
columnName="last_modified_on_utc" columnDataType="DATETIME"/>
+        <addNotNullConstraint tableName="m_loan" columnName="last_modified_by" 
columnDataType="BIGINT"/>
+    </changeSet>
+    <changeSet id="loan-7" author="fineract" context="postgresql">
+        <preConditions onFail="MARK_RAN">
+            <sqlCheck expectedResult="0">select count(*) from m_loan</sqlCheck>
+        </preConditions>
+        <addNotNullConstraint tableName="m_loan" columnName="created_on_utc" 
columnDataType="TIMESTAMP WITH TIME ZONE"/>
+        <addNotNullConstraint tableName="m_loan" columnName="created_by" 
columnDataType="BIGINT"/>
+        <addNotNullConstraint tableName="m_loan" 
columnName="last_modified_on_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
+        <addNotNullConstraint tableName="m_loan" columnName="last_modified_by" 
columnDataType="BIGINT"/>
+    </changeSet>
+    <!-- Loan transactions -->
+    <changeSet id="loan-transaction-13" author="fineract" context="mysql">
+        <preConditions onFail="MARK_RAN">
+            <sqlCheck expectedResult="0">select count(*) from 
m_loan_transaction</sqlCheck>
+        </preConditions>
+        <addNotNullConstraint tableName="m_loan_transaction" 
columnName="created_on_utc" columnDataType="DATETIME"/>
+        <addNotNullConstraint tableName="m_loan_transaction" 
columnName="created_by" columnDataType="BIGINT"/>
+        <addNotNullConstraint tableName="m_loan_transaction" 
columnName="last_modified_on_utc" columnDataType="DATETIME"/>
+        <addNotNullConstraint tableName="m_loan_transaction" 
columnName="last_modified_by" columnDataType="BIGINT"/>
+    </changeSet>
+    <changeSet id="loan-transaction-13" author="fineract" context="postgresql">
+        <preConditions onFail="MARK_RAN">
+            <sqlCheck expectedResult="0">select count(*) from 
m_loan_transaction</sqlCheck>
+        </preConditions>
+        <addNotNullConstraint tableName="m_loan_transaction" 
columnName="created_on_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
+        <addNotNullConstraint tableName="m_loan_transaction" 
columnName="created_by" columnDataType="BIGINT"/>
+        <addNotNullConstraint tableName="m_loan_transaction" 
columnName="last_modified_on_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
+        <addNotNullConstraint tableName="m_loan_transaction" 
columnName="last_modified_by" columnDataType="BIGINT"/>
+    </changeSet>
+    <!-- Client transaction -->
+    <changeSet author="fineract" id="client-transaction-1" context="mysql">
+        <addColumn tableName="m_client_transaction">
+            <column name="created_on_utc" type="DATETIME"/>
+            <column name="created_by" type="BIGINT" 
valueComputed="appuser_id"/>
+            <column name="last_modified_by" type="BIGINT"/>
+            <column name="last_modified_on_utc" type="DATETIME"/>
+        </addColumn>
+    </changeSet>
+    <changeSet author="fineract" id="client-transaction-1" 
context="postgresql">
+        <addColumn tableName="m_client_transaction">
+            <column name="created_on_utc" type="TIMESTAMP WITH TIME ZONE"/>
+            <column name="created_by" type="BIGINT" 
valueComputed="appuser_id"/>
+            <column name="last_modified_by" type="BIGINT"/>
+            <column name="last_modified_on_utc" type="TIMESTAMP WITH TIME 
ZONE"/>
+        </addColumn>
+    </changeSet>
+    <changeSet id="client-transaction-2" author="fineract">
+        <addColumn tableName="m_client_transaction">
+            <column name="submitted_on_date" type="DATE" 
valueComputed="created_date">
+                <constraints nullable="false"/>
+            </column>
+        </addColumn>
+    </changeSet>
+    <changeSet author="fineract" id="client-transaction-3">
+        <addForeignKeyConstraint baseColumnNames="created_by" 
baseTableName="m_client_transaction"
+                                 
constraintName="FK_client_transaction_created_by" deferrable="false" 
initiallyDeferred="false"
+                                 onDelete="RESTRICT" onUpdate="RESTRICT" 
referencedColumnNames="id"
+                                 referencedTableName="m_appuser" 
validate="true"/>
+        <addForeignKeyConstraint baseColumnNames="last_modified_by" 
baseTableName="m_client_transaction"
+                                 
constraintName="FK_client_transaction_last_modified_by" deferrable="false" 
initiallyDeferred="false"
+                                 onDelete="RESTRICT" onUpdate="RESTRICT" 
referencedColumnNames="id"
+                                 referencedTableName="m_appuser" 
validate="true"/>
+    </changeSet>
+    <changeSet id="client-transaction-4" author="fineract">
+        <dropForeignKeyConstraint baseTableName="m_client_transaction" 
constraintName="FK_m_client_transaction_m_appuser"/>
+        <dropColumn tableName="m_client_transaction">
+            <column name="appuser_id"/>
+        </dropColumn>
+    </changeSet>
+    <changeSet id="client-transaction-5" author="fineract" context="mysql">
+        <preConditions onFail="MARK_RAN">
+            <sqlCheck expectedResult="0">select count(*) from 
m_client_transaction</sqlCheck>
+        </preConditions>
+        <addNotNullConstraint tableName="m_client_transaction" 
columnName="created_on_utc" columnDataType="DATETIME"/>
+        <addNotNullConstraint tableName="m_client_transaction" 
columnName="created_by" columnDataType="BIGINT"/>
+        <addNotNullConstraint tableName="m_client_transaction" 
columnName="last_modified_on_utc" columnDataType="DATETIME"/>
+        <addNotNullConstraint tableName="m_client_transaction" 
columnName="last_modified_by" columnDataType="BIGINT"/>
+    </changeSet>
+    <changeSet id="client-transaction-5" author="fineract" 
context="postgresql">
+        <preConditions onFail="MARK_RAN">
+            <sqlCheck expectedResult="0">select count(*) from 
m_client_transaction</sqlCheck>
+        </preConditions>
+        <addNotNullConstraint tableName="m_client_transaction" 
columnName="created_on_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
+        <addNotNullConstraint tableName="m_client_transaction" 
columnName="created_by" columnDataType="BIGINT"/>
+        <addNotNullConstraint tableName="m_client_transaction" 
columnName="last_modified_on_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
+        <addNotNullConstraint tableName="m_client_transaction" 
columnName="last_modified_by" columnDataType="BIGINT"/>
+    </changeSet>
+    <changeSet id="client-transaction-6" author="fineract">
+        <dropNotNullConstraint tableName="m_client_transaction" 
columnName="created_date" columnDataType="datetime"/>
+    </changeSet>
+    <!-- Floating rate -->
+    <changeSet author="fineract" id="floating-rate-1" context="mysql">
+        <addColumn tableName="m_floating_rates">
+            <column name="created_on_utc" type="DATETIME"/>
+            <column name="last_modified_on_utc" type="DATETIME"/>
+        </addColumn>
+    </changeSet>
+    <changeSet author="fineract" id="floating-rate-1" context="postgresql">
+        <addColumn tableName="m_floating_rates">
+            <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="floating-rate-2" author="fineract">
+        <renameColumn tableName="m_floating_rates" 
oldColumnName="createdby_id" newColumnName="created_by" 
columnDataType="BIGINT"/>
+        <renameColumn tableName="m_floating_rates" 
oldColumnName="lastmodifiedby_id" newColumnName="last_modified_by" 
columnDataType="BIGINT"/>
+    </changeSet>
+    <changeSet author="fineract" id="floating-rate-3">
+        <addForeignKeyConstraint baseColumnNames="created_by" 
baseTableName="m_floating_rates"
+                                 constraintName="FK_floating_rates_created_by" 
deferrable="false" initiallyDeferred="false"
+                                 onDelete="RESTRICT" onUpdate="RESTRICT" 
referencedColumnNames="id"
+                                 referencedTableName="m_appuser" 
validate="true"/>
+        <addForeignKeyConstraint baseColumnNames="last_modified_by" 
baseTableName="m_floating_rates"
+                                 
constraintName="FK_floating_rates_last_modified_by" deferrable="false" 
initiallyDeferred="false"
+                                 onDelete="RESTRICT" onUpdate="RESTRICT" 
referencedColumnNames="id"
+                                 referencedTableName="m_appuser" 
validate="true"/>
+    </changeSet>
+    <changeSet id="floating-rate-4" author="fineract" context="mysql">
+        <preConditions onFail="MARK_RAN">
+            <sqlCheck expectedResult="0">select count(*) from 
m_floating_rates</sqlCheck>
+        </preConditions>
+        <addNotNullConstraint tableName="m_floating_rates" 
columnName="created_on_utc" columnDataType="DATETIME"/>
+        <addNotNullConstraint tableName="m_floating_rates" 
columnName="created_by" columnDataType="BIGINT"/>
+        <addNotNullConstraint tableName="m_floating_rates" 
columnName="last_modified_on_utc" columnDataType="DATETIME"/>
+        <addNotNullConstraint tableName="m_floating_rates" 
columnName="last_modified_by" columnDataType="BIGINT"/>
+    </changeSet>
+    <changeSet id="floating-rate-4" author="fineract" context="postgresql">
+        <preConditions onFail="MARK_RAN">
+            <sqlCheck expectedResult="0">select count(*) from 
m_client_transaction</sqlCheck>
+        </preConditions>
+        <addNotNullConstraint tableName="m_floating_rates" 
columnName="created_on_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
+        <addNotNullConstraint tableName="m_floating_rates" 
columnName="created_by" columnDataType="BIGINT"/>
+        <addNotNullConstraint tableName="m_floating_rates" 
columnName="last_modified_on_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
+        <addNotNullConstraint tableName="m_floating_rates" 
columnName="last_modified_by" columnDataType="BIGINT"/>
+    </changeSet>
+    <changeSet id="floating-rate-5" author="fineract">
+        <dropNotNullConstraint tableName="m_floating_rates" 
columnName="created_date" columnDataType="datetime"/>
+        <dropNotNullConstraint tableName="m_floating_rates" 
columnName="lastmodified_date" columnDataType="datetime"/>
+    </changeSet>
+    <!-- Floating rates period -->
+    <changeSet author="fineract" id="floating-rate-period-1" context="mysql">
+        <addColumn tableName="m_floating_rates_periods">
+            <column name="created_on_utc" type="DATETIME"/>
+            <column name="last_modified_on_utc" type="DATETIME"/>
+        </addColumn>
+    </changeSet>
+    <changeSet author="fineract" id="floating-rate-period-1" 
context="postgresql">
+        <addColumn tableName="m_floating_rates_periods">
+            <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="floating-rate-period-2" author="fineract">
+        <renameColumn tableName="m_floating_rates_periods" 
oldColumnName="createdby_id" newColumnName="created_by" 
columnDataType="BIGINT"/>
+        <renameColumn tableName="m_floating_rates_periods" 
oldColumnName="lastmodifiedby_id" newColumnName="last_modified_by" 
columnDataType="BIGINT"/>
+    </changeSet>
+    <changeSet author="fineract" id="floating-rate-period-3">
+        <addForeignKeyConstraint baseColumnNames="created_by" 
baseTableName="m_floating_rates_periods"
+                                 
constraintName="FK_floating_rates_period_created_by" deferrable="false" 
initiallyDeferred="false"
+                                 onDelete="RESTRICT" onUpdate="RESTRICT" 
referencedColumnNames="id"
+                                 referencedTableName="m_appuser" 
validate="true"/>
+        <addForeignKeyConstraint baseColumnNames="last_modified_by" 
baseTableName="m_floating_rates_periods"
+                                 
constraintName="FK_floating_rates_period_last_modified_by" deferrable="false" 
initiallyDeferred="false"
+                                 onDelete="RESTRICT" onUpdate="RESTRICT" 
referencedColumnNames="id"
+                                 referencedTableName="m_appuser" 
validate="true"/>
+    </changeSet>
+    <changeSet id="floating-rate-period-4" author="fineract" context="mysql">
+        <preConditions onFail="MARK_RAN">
+            <sqlCheck expectedResult="0">select count(*) from 
m_floating_rates_periods</sqlCheck>
+        </preConditions>
+        <addNotNullConstraint tableName="m_floating_rates_periods" 
columnName="created_on_utc" columnDataType="DATETIME"/>
+        <addNotNullConstraint tableName="m_floating_rates_periods" 
columnName="created_by" columnDataType="BIGINT"/>
+        <addNotNullConstraint tableName="m_floating_rates_periods" 
columnName="last_modified_on_utc" columnDataType="DATETIME"/>
+        <addNotNullConstraint tableName="m_floating_rates_periods" 
columnName="last_modified_by" columnDataType="BIGINT"/>
+    </changeSet>
+    <changeSet id="floating-rate-period-4" author="fineract" 
context="postgresql">
+        <preConditions onFail="MARK_RAN">
+            <sqlCheck expectedResult="0">select count(*) from 
m_floating_rates_periods</sqlCheck>
+        </preConditions>
+        <addNotNullConstraint tableName="m_floating_rates_periods" 
columnName="created_on_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
+        <addNotNullConstraint tableName="m_floating_rates_periods" 
columnName="created_by" columnDataType="BIGINT"/>
+        <addNotNullConstraint tableName="m_floating_rates_periods" 
columnName="last_modified_on_utc" columnDataType="TIMESTAMP WITH TIME ZONE"/>
+        <addNotNullConstraint tableName="m_floating_rates_periods" 
columnName="last_modified_by" columnDataType="BIGINT"/>
+    </changeSet>
+    <changeSet id="floating-rate-period-5" author="fineract">
+        <dropNotNullConstraint tableName="m_floating_rates_periods" 
columnName="created_date" columnDataType="datetime"/>
+        <dropNotNullConstraint tableName="m_floating_rates_periods" 
columnName="lastmodified_date" columnDataType="datetime"/>
+    </changeSet>
+</databaseChangeLog>
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/FixedDepositTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/FixedDepositTest.java
index 63e5a5f69..fd4bc8036 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/FixedDepositTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/FixedDepositTest.java
@@ -30,7 +30,10 @@ import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
+import java.time.LocalDate;
 import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -442,7 +445,7 @@ public class FixedDepositTest {
     }
 
     @Test
-    public void testFixedDepositAccountClosureTypeWithdrawal_WITH_HOLD_TAX() 
throws InterruptedException {
+    public void testFixedDepositAccountClosureTypeWithdrawal_WITH_HOLD_TAX() {
         this.fixedDepositProductHelper = new 
FixedDepositProductHelper(this.requestSpec, this.responseSpec);
         this.accountHelper = new AccountHelper(this.requestSpec, 
this.responseSpec);
         this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, 
this.responseSpec);
@@ -457,30 +460,23 @@ public class FixedDepositTest {
         final Account liabilityAccount = 
this.accountHelper.createLiabilityAccount();
         final Account liabilityAccountForTax = 
this.accountHelper.createLiabilityAccount();
 
-        DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", 
Locale.US);
-        DateFormat monthDayFormat = new SimpleDateFormat("dd MMM", Locale.US);
-        DateFormat currentDateFormat = new SimpleDateFormat("dd");
+        DateTimeFormatter monthDayFormat = new 
DateTimeFormatterBuilder().appendPattern("dd MMM").toFormatter();
+        DateTimeFormatter currentDateFormat = new 
DateTimeFormatterBuilder().appendPattern("dd").toFormatter();
 
-        Calendar todaysDate = Calendar.getInstance();
-        todaysDate.add(Calendar.MONTH, -20);
-        final String VALID_FROM = dateFormat.format(todaysDate.getTime());
-        todaysDate.add(Calendar.YEAR, 10);
-        final String VALID_TO = dateFormat.format(todaysDate.getTime());
+        LocalDate todaysDate = Utils.getLocalDateOfTenant();
+        todaysDate = todaysDate.minusMonths(20);
+        final String VALID_FROM = Utils.dateFormatter.format(todaysDate);
+        todaysDate = todaysDate.plusYears(10);
+        final String VALID_TO = Utils.dateFormatter.format(todaysDate);
 
-        todaysDate = Calendar.getInstance();
-        todaysDate.add(Calendar.MONTH, -20);
-        final String SUBMITTED_ON_DATE = 
dateFormat.format(todaysDate.getTime());
-        final String APPROVED_ON_DATE = 
dateFormat.format(todaysDate.getTime());
-        final String ACTIVATION_DATE = dateFormat.format(todaysDate.getTime());
-        monthDayFormat.format(todaysDate.getTime());
+        todaysDate = Utils.getLocalDateOfTenant();
+        todaysDate = todaysDate.minusMonths(20);
+        final String SUBMITTED_ON_DATE = 
Utils.dateFormatter.format(todaysDate);
+        final String APPROVED_ON_DATE = Utils.dateFormatter.format(todaysDate);
+        final String ACTIVATION_DATE = Utils.dateFormatter.format(todaysDate);
 
-        Integer currentDate = 
Integer.valueOf(currentDateFormat.format(todaysDate.getTime()));
-        Integer daysInMonth = todaysDate.getActualMaximum(Calendar.DATE);
-        int numberOfDaysLeft = daysInMonth - currentDate + 1;
-        todaysDate.add(Calendar.DATE, numberOfDaysLeft);
-        Calendar closedOn = Calendar.getInstance();
-        closedOn.add(Calendar.MONTH, -6);
-        final String CLOSED_ON_DATE = dateFormat.format(closedOn.getTime());
+        LocalDate closedOn = todaysDate.plusMonths(14);
+        final String CLOSED_ON_DATE = Utils.dateFormatter.format(closedOn);
 
         Integer clientId = ClientHelper.createClient(requestSpec, 
responseSpec);
         Assertions.assertNotNull(clientId);
@@ -1282,26 +1278,23 @@ public class FixedDepositTest {
         this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, 
this.responseSpec);
         this.fixedDepositAccountHelper = new 
FixedDepositAccountHelper(this.requestSpec, this.responseSpec);
 
-        DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", 
Locale.US);
-        DateFormat monthDayFormat = new SimpleDateFormat("dd MMM", Locale.US);
-        DateFormat currentDateFormat = new SimpleDateFormat("dd");
+        DateTimeFormatter dateFormat = Utils.dateFormatter;
 
-        Calendar todaysDate = Calendar.getInstance();
-        todaysDate.add(Calendar.MONTH, -3);
-        final String VALID_FROM = dateFormat.format(todaysDate.getTime());
-        todaysDate.add(Calendar.YEAR, 10);
-        final String VALID_TO = dateFormat.format(todaysDate.getTime());
+        LocalDate todaysDate = Utils.getLocalDateOfTenant();
+        todaysDate = todaysDate.minusMonths(3);
+        final String VALID_FROM = dateFormat.format(todaysDate);
+        todaysDate = todaysDate.plusYears(10);
+        final String VALID_TO = dateFormat.format(todaysDate);
 
-        todaysDate = Calendar.getInstance();
-        todaysDate.add(Calendar.MONTH, -1);
-        todaysDate.add(Calendar.DAY_OF_MONTH, -1);
-        final String SUBMITTED_ON_DATE = 
dateFormat.format(todaysDate.getTime());
-        final String APPROVED_ON_DATE = 
dateFormat.format(todaysDate.getTime());
-        final String ACTIVATION_DATE = dateFormat.format(todaysDate.getTime());
-        monthDayFormat.format(todaysDate.getTime());
-        todaysDate.add(Calendar.MONTH, 1);
-        todaysDate.add(Calendar.DAY_OF_MONTH, 1);
-        final String CLOSED_ON_DATE = dateFormat.format(todaysDate.getTime());
+        todaysDate = Utils.getLocalDateOfTenant();
+        todaysDate = todaysDate.minusMonths(1);
+        todaysDate = todaysDate.minusDays(1);
+        final String SUBMITTED_ON_DATE = dateFormat.format(todaysDate);
+        final String APPROVED_ON_DATE = dateFormat.format(todaysDate);
+        final String ACTIVATION_DATE = dateFormat.format(todaysDate);
+
+        todaysDate = Utils.getLocalDateOfTenant();
+        final String CLOSED_ON_DATE = dateFormat.format(todaysDate);
 
         Integer clientId = ClientHelper.createClient(this.requestSpec, 
this.responseSpec);
         Assertions.assertNotNull(clientId);
@@ -1345,18 +1338,13 @@ public class FixedDepositTest {
         log.info("per day = {}", perDay);
         double interestPerDay = interestRateInFraction * perDay;
 
-        todaysDate.add(Calendar.MONTH, -1);
-        todaysDate.add(Calendar.DAY_OF_MONTH, -1);
-        Integer currentDate = 
Integer.valueOf(currentDateFormat.format(todaysDate.getTime()));
-        Integer daysInMonth = todaysDate.getActualMaximum(Calendar.DATE);
-        daysInMonth = daysInMonth - currentDate + 1;
-        Float interestPerMonth = (float) (interestPerDay * principal * 
daysInMonth);
+        todaysDate = todaysDate.minusMonths(1);
+        todaysDate = todaysDate.minusDays(1);
+
+        Float interestPerMonth = (float) (interestPerDay * principal * 
ChronoUnit.DAYS.between(todaysDate, Utils.getLocalDateOfTenant()));
         principal += interestPerMonth;
-        todaysDate.add(Calendar.DATE, daysInMonth);
-        log.info("{}", monthDayFormat.format(todaysDate.getTime()));
-        interestPerMonth = (float) (interestPerDay * principal * currentDate);
+        log.info("{}", Utils.dateFormatter.format(todaysDate));
         log.info("IPM = {}", interestPerMonth);
-        principal += interestPerMonth;
         log.info("principal = {}", principal);
 
         Integer transactionIdForPostInterest = 
this.fixedDepositAccountHelper.postInterestForFixedDeposit(fixedDepositAccountId);

Reply via email to