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 b30d5c5a1 Loan transaction date handling enhancement + Make Loan 
transaction auditable
b30d5c5a1 is described below

commit b30d5c5a165be3362a7f236eafa19a7c1bcb3c5e
Author: Adam Saghy <[email protected]>
AuthorDate: Thu Jul 7 14:15:11 2022 +0200

    Loan transaction date handling enhancement + Make Loan transaction auditable
---
 .../TellerManagementReadPlatformServiceImpl.java   |   4 +-
 .../portfolio/loanaccount/domain/Loan.java         | 170 ++++++++---------
 .../domain/LoanAccountDomainServiceJpa.java        |  32 ++--
 .../loanaccount/domain/LoanTransaction.java        | 206 ++++++++-------------
 .../domain/AbstractLoanScheduleGenerator.java      |   6 +-
 .../service/LoanScheduleAssembler.java             |   4 +-
 .../LoanScheduleWritePlatformServiceImpl.java      |   4 +-
 ...nRescheduleRequestWritePlatformServiceImpl.java |   2 +-
 .../LoanAccrualWritePlatformServiceImpl.java       |   2 +-
 ...ationWritePlatformServiceJpaRepositoryImpl.java |   6 +-
 .../service/LoanReadPlatformServiceImpl.java       |   3 +-
 .../LoanWritePlatformServiceJpaRepositoryImpl.java |  59 +++---
 .../db/changelog/tenant/changelog-tenant.xml       |   1 +
 .../parts/0019_refactor_loan_transaction.xml       |  59 ++++++
 14 files changed, 259 insertions(+), 299 deletions(-)

diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/service/TellerManagementReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/service/TellerManagementReadPlatformServiceImpl.java
index e2df2384b..fec043215 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/service/TellerManagementReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/service/TellerManagementReadPlatformServiceImpl.java
@@ -664,7 +664,7 @@ public class TellerManagementReadPlatformServiceImpl 
implements TellerManagement
             sqlBuilder.append(" left join m_loan loan on loan_txn.loan_id = 
loan.id ");
             sqlBuilder.append(" left join m_client cl on loan.client_id = 
cl.id ");
             sqlBuilder.append(" left join m_office o on cl.office_id = o.id ");
-            sqlBuilder.append(" left join m_appuser user on 
loan_txn.appuser_id = user.id ");
+            sqlBuilder.append(" left join m_appuser user on 
loan_txn.createdby_id = user.id ");
             sqlBuilder.append(" left join m_staff staff on user.staff_id = 
staff.id ");
             sqlBuilder.append(" left join m_cashiers c on c.staff_id = 
staff.id ");
             sqlBuilder.append(" left join m_payment_detail payDetails on 
payDetails.id = loan_txn.payment_detail_id ");
@@ -829,7 +829,7 @@ public class TellerManagementReadPlatformServiceImpl 
implements TellerManagement
             sqlBuilder.append("    left join m_loan loan on loan_txn.loan_id = 
loan.id ");
             sqlBuilder.append("    left join m_client cl on loan.client_id = 
cl.id ");
             sqlBuilder.append("    left join m_office o on cl.office_id = o.id 
");
-            sqlBuilder.append("    left join m_appuser user on 
loan_txn.appuser_id = user.id ");
+            sqlBuilder.append("    left join m_appuser user on 
loan_txn.createdby_id = user.id ");
             sqlBuilder.append("    left join m_staff staff on user.staff_id = 
staff.id ");
             sqlBuilder.append("    left join m_cashiers c on c.staff_id = 
staff.id ");
             sqlBuilder.append(" left join m_payment_detail payDetails on 
payDetails.id = loan_txn.payment_detail_id ");
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index d89bed39c..f8ef7d7d2 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -688,8 +688,7 @@ public class Loan extends AbstractPersistableCustom {
      * @param suppliedTransactionDate
      * @return
      */
-    public LoanTransaction handleChargeAppliedTransaction(final LoanCharge 
loanCharge, final LocalDate suppliedTransactionDate,
-            final AppUser currentUser) {
+    public LoanTransaction handleChargeAppliedTransaction(final LoanCharge 
loanCharge, final LocalDate suppliedTransactionDate) {
         final Money chargeAmount = loanCharge.getAmount(getCurrency());
         Money feeCharges = chargeAmount;
         Money penaltyCharges = Money.zero(loanCurrency());
@@ -714,7 +713,7 @@ public class Loan extends AbstractPersistableCustom {
         }
 
         final LoanTransaction applyLoanChargeTransaction = 
LoanTransaction.accrueLoanCharge(this, getOffice(), chargeAmount,
-                transactionDate, feeCharges, penaltyCharges, 
DateUtils.getLocalDateTimeOfTenant(), currentUser);
+                transactionDate, feeCharges, penaltyCharges);
 
         Integer installmentNumber = null;
         final LoanChargePaidBy loanChargePaidBy = new 
LoanChargePaidBy(applyLoanChargeTransaction, loanCharge,
@@ -1009,8 +1008,7 @@ public class Loan extends AbstractPersistableCustom {
 
     public LoanTransaction waiveLoanCharge(final LoanCharge loanCharge, final 
LoanLifecycleStateMachine loanLifecycleStateMachine,
             final Map<String, Object> changes, final List<Long> 
existingTransactionIds, final List<Long> existingReversedTransactionIds,
-            final Integer loanInstallmentNumber, final ScheduleGeneratorDTO 
scheduleGeneratorDTO, final Money accruedCharge,
-            final AppUser currentUser) {
+            final Integer loanInstallmentNumber, final ScheduleGeneratorDTO 
scheduleGeneratorDTO, final Money accruedCharge) {
 
         validateLoanIsNotClosed(loanCharge);
 
@@ -1062,14 +1060,14 @@ public class Loan extends AbstractPersistableCustom {
         
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
 
         final LoanTransaction waiveLoanChargeTransaction = 
LoanTransaction.waiveLoanCharge(this, getOffice(), amountWaived, 
transactionDate,
-                feeChargesWaived, penaltyChargesWaived, unrecognizedIncome, 
DateUtils.getLocalDateTimeOfTenant(), currentUser);
+                feeChargesWaived, penaltyChargesWaived, unrecognizedIncome);
         final LoanChargePaidBy loanChargePaidBy = new 
LoanChargePaidBy(waiveLoanChargeTransaction, loanCharge,
                 
waiveLoanChargeTransaction.getAmount(getCurrency()).getAmount(), 
loanInstallmentNumber);
         waiveLoanChargeTransaction.getLoanChargesPaid().add(loanChargePaidBy);
         addLoanTransaction(waiveLoanChargeTransaction);
         if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()
                 && (loanCharge.getDueLocalDate() == null || 
DateUtils.getBusinessLocalDate().isAfter(loanCharge.getDueLocalDate()))) {
-            
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, 
currentUser);
+            
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
         }
         // Waive of charges whose due date falls after latest 'repayment'
         // transaction dont require entire loan schedule to be reprocessed.
@@ -1225,7 +1223,7 @@ public class Loan extends AbstractPersistableCustom {
         this.rates.addAll(loanRates);
     }
 
-    public void updateLoanSchedule(final LoanScheduleModel 
modifiedLoanSchedule, AppUser currentUser) {
+    public void updateLoanSchedule(final LoanScheduleModel 
modifiedLoanSchedule) {
         this.repaymentScheduleInstallments.clear();
         for (final LoanScheduleModelPeriod scheduledLoanInstallment : 
modifiedLoanSchedule.getPeriods()) {
 
@@ -1242,11 +1240,11 @@ public class Loan extends AbstractPersistableCustom {
 
         updateLoanScheduleDependentDerivedFields();
         updateLoanSummaryDerivedFields();
-        applyAccurals(currentUser);
+        applyAccurals();
 
     }
 
-    public void updateLoanSchedule(final 
Collection<LoanRepaymentScheduleInstallment> installments, AppUser currentUser) 
{
+    public void updateLoanSchedule(final 
Collection<LoanRepaymentScheduleInstallment> installments) {
         List<LoanRepaymentScheduleInstallment> existingInstallments = new 
ArrayList<>(this.repaymentScheduleInstallments);
         repaymentScheduleInstallments.clear();
         for (final LoanRepaymentScheduleInstallment installment : 
installments) {
@@ -1262,7 +1260,7 @@ public class Loan extends AbstractPersistableCustom {
         }
         updateLoanScheduleDependentDerivedFields();
         updateLoanSummaryDerivedFields();
-        applyAccurals(currentUser);
+        applyAccurals();
 
     }
 
@@ -1279,13 +1277,13 @@ public class Loan extends AbstractPersistableCustom {
     /**
      * method updates accrual derived fields on installments and reverse the 
unprocessed transactions
      */
-    private void applyAccurals(AppUser currentUser) {
+    private void applyAccurals() {
         Collection<LoanTransaction> accruals = 
retreiveListOfAccrualTransactions();
         if (accruals.size() > 0) {
             if (isPeriodicAccrualAccountingEnabledOnLoanProduct()) {
                 applyPeriodicAccruals(accruals);
             } else if 
(isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) {
-                updateAccrualsForNonPeriodicAccruals(accruals, currentUser);
+                updateAccrualsForNonPeriodicAccruals(accruals);
             }
         }
     }
@@ -1325,7 +1323,7 @@ public class Loan extends AbstractPersistableCustom {
         }
     }
 
-    private void updateAccrualsForNonPeriodicAccruals(final 
Collection<LoanTransaction> accruals, final AppUser currentUser) {
+    private void updateAccrualsForNonPeriodicAccruals(final 
Collection<LoanTransaction> accruals) {
 
         final Money interestApplied = Money.of(getCurrency(), 
this.summary.getTotalInterestCharged());
         for (LoanTransaction loanTransaction : accruals) {
@@ -1334,7 +1332,7 @@ public class Loan extends AbstractPersistableCustom {
                     loanTransaction.reverse();
                     final LocalDateTime currentDateTime = 
DateUtils.getLocalDateTimeOfTenant();
                     final LoanTransaction interestAppliedTransaction = 
LoanTransaction.accrueInterest(getOffice(), this, interestApplied,
-                            getDisbursementDate(), currentDateTime, 
currentUser);
+                            getDisbursementDate());
                     addLoanTransaction(interestAppliedTransaction);
                 }
             } else {
@@ -1344,7 +1342,7 @@ public class Loan extends AbstractPersistableCustom {
                     Money chargeAmount = loanCharge.getAmount(getCurrency());
                     if 
(chargeAmount.isNotEqualTo(loanTransaction.getAmount(getCurrency()))) {
                         loanTransaction.reverse();
-                        handleChargeAppliedTransaction(loanCharge, 
loanTransaction.getTransactionDate(), currentUser);
+                        handleChargeAppliedTransaction(loanCharge, 
loanTransaction.getTransactionDate());
                     }
 
                 }
@@ -2068,7 +2066,7 @@ public class Loan extends AbstractPersistableCustom {
             final LocalDate submittedOn, final String externalId, final 
boolean allowTransactionsOnHoliday, final List<Holiday> holidays,
             final WorkingDays workingDays, final boolean 
allowTransactionsOnNonWorkingDay) {
 
-        updateLoanSchedule(loanSchedule, currentUser);
+        updateLoanSchedule(loanSchedule);
 
         LoanStatus from = null;
         if (this.loanStatus != null) {
@@ -2483,12 +2481,11 @@ public class Loan extends AbstractPersistableCustom {
         
validateDisbursementDateIsOnHoliday(holidayDetailDTO.isAllowTransactionsOnHoliday(),
 holidayDetailDTO.getHolidays());
 
         
regenerateRepaymentScheduleWithInterestRecalculationIfNeeded(this.repaymentScheduleDetail().isInterestRecalculationEnabled(),
-                isDisbursementMissed(), scheduleGeneratorDTO, currentUser);
+                isDisbursementMissed(), scheduleGeneratorDTO);
 
         
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
         updateLoanRepaymentPeriodsDerivedFields(actualDisbursementDate);
-        LocalDateTime createdDate = DateUtils.getLocalDateTimeOfTenant();
-        handleDisbursementTransaction(actualDisbursementDate, createdDate, 
currentUser, paymentDetail);
+        handleDisbursementTransaction(actualDisbursementDate, paymentDetail);
         updateLoanSummaryDerivedFields();
         final Money interestApplied = Money.of(getCurrency(), 
this.summary.getTotalInterestCharged());
 
@@ -2500,7 +2497,7 @@ public class Loan extends AbstractPersistableCustom {
         if (((isMultiDisburmentLoan() && 
getDisbursedLoanDisbursementDetails().size() == 1) || !isMultiDisburmentLoan())
                 && 
isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) {
             final LoanTransaction interestAppliedTransaction = 
LoanTransaction.accrueInterest(getOffice(), this, interestApplied,
-                    actualDisbursementDate, createdDate, currentUser);
+                    actualDisbursementDate);
             addLoanTransaction(interestAppliedTransaction);
         }
 
@@ -2509,12 +2506,12 @@ public class Loan extends AbstractPersistableCustom {
     }
 
     private void 
regenerateRepaymentScheduleWithInterestRecalculationIfNeeded(boolean 
interestRecalculationEnabledParam,
-            boolean disbursementMissedParam, ScheduleGeneratorDTO 
scheduleGeneratorDTO, AppUser currentUser) {
+            boolean disbursementMissedParam, ScheduleGeneratorDTO 
scheduleGeneratorDTO) {
 
         LocalDate firstInstallmentDueDate = 
fetchRepaymentScheduleInstallment(1).getDueDate();
         if (interestRecalculationEnabledParam
                 && 
(firstInstallmentDueDate.isBefore(DateUtils.getBusinessLocalDate()) || 
disbursementMissedParam)) {
-            
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, 
currentUser);
+            
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
         }
 
     }
@@ -2532,7 +2529,7 @@ public class Loan extends AbstractPersistableCustom {
     }
 
     public void regenerateScheduleOnDisbursement(final ScheduleGeneratorDTO 
scheduleGeneratorDTO, final boolean recalculateSchedule,
-            final LocalDate actualDisbursementDate, BigDecimal emiAmount, 
final AppUser currentUser, LocalDate nextPossibleRepaymentDate,
+            final LocalDate actualDisbursementDate, BigDecimal emiAmount, 
LocalDate nextPossibleRepaymentDate,
             Date rescheduledRepaymentDate) {
         boolean isEmiAmountChanged = false;
         if ((this.loanProduct.isMultiDisburseLoan() || 
this.loanProduct.canDefineInstallmentAmount()) && emiAmount != null
@@ -2565,9 +2562,9 @@ public class Loan extends AbstractPersistableCustom {
         if 
(isRepaymentScheduleRegenerationRequiredForDisbursement(actualDisbursementDate) 
|| recalculateSchedule || isEmiAmountChanged
                 || rescheduledRepaymentDate != null) {
             if 
(this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
-                
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, 
currentUser);
+                
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
             } else {
-                regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
+                regenerateRepaymentSchedule(scheduleGeneratorDTO);
             }
         }
     }
@@ -2789,12 +2786,12 @@ public class Loan extends AbstractPersistableCustom {
     /*
      * Ability to regenerate the repayment schedule based on the loans current 
details/state.
      */
-    public void regenerateRepaymentSchedule(final ScheduleGeneratorDTO 
scheduleGeneratorDTO, final AppUser currentUser) {
+    public void regenerateRepaymentSchedule(final ScheduleGeneratorDTO 
scheduleGeneratorDTO) {
         final LoanScheduleModel loanSchedule = 
regenerateScheduleModel(scheduleGeneratorDTO);
         if (loanSchedule == null) {
             return;
         }
-        updateLoanSchedule(loanSchedule, currentUser);
+        updateLoanSchedule(loanSchedule);
         final Set<LoanCharge> charges = this.charges();
         for (final LoanCharge loanCharge : charges) {
             if (!loanCharge.isWaived()) {
@@ -2855,8 +2852,7 @@ public class Loan extends AbstractPersistableCustom {
         return interestRate;
     }
 
-    private void handleDisbursementTransaction(final LocalDate disbursedOn, 
final LocalDateTime createdDate, final AppUser currentUser,
-            final PaymentDetail paymentDetail) {
+    private void handleDisbursementTransaction(final LocalDate disbursedOn, 
final PaymentDetail paymentDetail) {
 
         // add repayment transaction to track incoming money from client to mfi
         // for (charges due at time of disbursement)
@@ -2873,7 +2869,7 @@ public class Loan extends AbstractPersistableCustom {
 
         Money disbursentMoney = Money.zero(getCurrency());
         final LoanTransaction chargesPayment = 
LoanTransaction.repaymentAtDisbursement(getOffice(), disbursentMoney, 
paymentDetail,
-                disbursedOn, null, createdDate, currentUser);
+                disbursedOn, null);
         final Integer installmentNumber = null;
         for (final LoanCharge charge : charges()) {
             Date actualDisbursementDate = getActualDisbursementDate(charge);
@@ -2898,7 +2894,7 @@ public class Loan extends AbstractPersistableCustom {
                  * create a Charge applied transaction if Up front Accrual, 
None or Cash based accounting is enabled
                  **/
                 if 
(isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) {
-                    handleChargeAppliedTransaction(charge, disbursedOn, 
currentUser);
+                    handleChargeAppliedTransaction(charge, disbursedOn);
                 }
             }
         }
@@ -2968,7 +2964,7 @@ public class Loan extends AbstractPersistableCustom {
     }
 
     public Map<String, Object> undoDisbursal(final ScheduleGeneratorDTO 
scheduleGeneratorDTO, final List<Long> existingTransactionIds,
-            final List<Long> existingReversedTransactionIds, AppUser 
currentUser) {
+            final List<Long> existingReversedTransactionIds) {
 
         validateAccountStatus(LoanEvent.LOAN_DISBURSAL_UNDO);
 
@@ -3003,7 +2999,7 @@ public class Loan extends AbstractPersistableCustom {
                 // clear off actual disbusrement date so schedule regeneration
                 // uses expected date.
 
-                regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
+                regenerateRepaymentSchedule(scheduleGeneratorDTO);
                 if (isDisbursedAmountChanged) {
                     
updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement());
                 }
@@ -3070,7 +3066,7 @@ public class Loan extends AbstractPersistableCustom {
 
     public ChangedTransactionDetail waiveInterest(final LoanTransaction 
waiveInterestTransaction,
             final LoanLifecycleStateMachine loanLifecycleStateMachine, final 
List<Long> existingTransactionIds,
-            final List<Long> existingReversedTransactionIds, final 
ScheduleGeneratorDTO scheduleGeneratorDTO, final AppUser currentUser) {
+            final List<Long> existingReversedTransactionIds, final 
ScheduleGeneratorDTO scheduleGeneratorDTO) {
 
         validateAccountStatus(LoanEvent.LOAN_REPAYMENT_OR_WAIVER);
 
@@ -3082,7 +3078,7 @@ public class Loan extends AbstractPersistableCustom {
         
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
 
         final ChangedTransactionDetail changedTransactionDetail = 
handleRepaymentOrRecoveryOrWaiverTransaction(waiveInterestTransaction,
-                loanLifecycleStateMachine, null, scheduleGeneratorDTO, 
currentUser);
+                loanLifecycleStateMachine, null, scheduleGeneratorDTO);
 
         return changedTransactionDetail;
     }
@@ -3091,7 +3087,7 @@ public class Loan extends AbstractPersistableCustom {
     public ChangedTransactionDetail makeRepayment(final LoanTransaction 
repaymentTransaction,
             final LoanLifecycleStateMachine loanLifecycleStateMachine, final 
List<Long> existingTransactionIds,
             final List<Long> existingReversedTransactionIds, boolean 
isRecoveryRepayment, final ScheduleGeneratorDTO scheduleGeneratorDTO,
-            final AppUser currentUser, Boolean isHolidayValidationDone) {
+            Boolean isHolidayValidationDone) {
         HolidayDetailDTO holidayDetailDTO = null;
         LoanEvent event = null;
         if (isRecoveryRepayment) {
@@ -3115,7 +3111,7 @@ public class Loan extends AbstractPersistableCustom {
         
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
 
         final ChangedTransactionDetail changedTransactionDetail = 
handleRepaymentOrRecoveryOrWaiverTransaction(repaymentTransaction,
-                loanLifecycleStateMachine, null, scheduleGeneratorDTO, 
currentUser);
+                loanLifecycleStateMachine, null, scheduleGeneratorDTO);
 
         return changedTransactionDetail;
     }
@@ -3184,7 +3180,7 @@ public class Loan extends AbstractPersistableCustom {
 
     private ChangedTransactionDetail 
handleRepaymentOrRecoveryOrWaiverTransaction(final LoanTransaction 
loanTransaction,
             final LoanLifecycleStateMachine loanLifecycleStateMachine, final 
LoanTransaction adjustedTransaction,
-            final ScheduleGeneratorDTO scheduleGeneratorDTO, final AppUser 
currentUser) {
+            final ScheduleGeneratorDTO scheduleGeneratorDTO) {
 
         ChangedTransactionDetail changedTransactionDetail = null;
 
@@ -3289,7 +3285,7 @@ public class Loan extends AbstractPersistableCustom {
         }
         if (reprocess) {
             if 
(this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
-                
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, 
currentUser);
+                
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
             }
             final List<LoanTransaction> 
allNonContraTransactionsPostDisbursement = 
retreiveListOfTransactionsPostDisbursement();
             changedTransactionDetail = 
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
@@ -3457,8 +3453,8 @@ public class Loan extends AbstractPersistableCustom {
             BigDecimal penaltyToPost = 
cumulativeIncomeFromInstallments.get("penalty")
                     
.subtract(cumulativeIncomeFromIncomePosting.get("penalty"));
             BigDecimal amountToPost = 
interestToPost.add(feeToPost).add(penaltyToPost);
-            LoanTransaction finalIncomeTransaction = 
LoanTransaction.incomePosting(this, this.getOffice(), closedDate, amountToPost,
-                    interestToPost, feeToPost, penaltyToPost, null);
+            LoanTransaction finalIncomeTransaction = 
LoanTransaction.incomePosting(this, this.getOffice(), closedLocalDate, 
amountToPost,
+                    interestToPost, feeToPost, penaltyToPost);
             addLoanTransaction(finalIncomeTransaction);
             if (isPeriodicAccrualAccountingEnabledOnLoanProduct()) {
                 List<LoanTransaction> updatedAccrualTransactions = 
retreiveListOfAccrualTransactions();
@@ -3469,7 +3465,7 @@ public class Loan extends AbstractPersistableCustom {
                 HashMap<String, Object> feeDetails = new HashMap<>();
                 determineFeeDetails(lastAccruedDate, closedLocalDate, 
feeDetails);
                 LoanTransaction finalAccrual = 
LoanTransaction.accrueTransaction(this, this.getOffice(), closedLocalDate, 
amountToPost,
-                        interestToPost, feeToPost, penaltyToPost, null);
+                        interestToPost, feeToPost, penaltyToPost);
                 updateLoanChargesPaidBy(finalAccrual, feeDetails, null);
                 addLoanTransaction(finalAccrual);
             }
@@ -3607,7 +3603,7 @@ public class Loan extends AbstractPersistableCustom {
         return loanRepaymentScheduleInstallment;
     }
 
-    public LoanTransaction deriveDefaultInterestWaiverTransaction(final 
LocalDateTime createdDate, final AppUser currentUser) {
+    public LoanTransaction deriveDefaultInterestWaiverTransaction() {
 
         final Money totalInterestOutstanding = 
getTotalInterestOutstandingOnLoan();
         Money possibleInterestToWaive = totalInterestOutstanding.copy();
@@ -3630,13 +3626,13 @@ public class Loan extends AbstractPersistableCustom {
         }
 
         return LoanTransaction.waiver(getOffice(), this, 
possibleInterestToWaive, transactionDate, possibleInterestToWaive,
-                possibleInterestToWaive.zero(), createdDate, currentUser);
+                possibleInterestToWaive.zero());
     }
 
     public ChangedTransactionDetail adjustExistingTransaction(final 
LoanTransaction newTransactionDetail,
             final LoanLifecycleStateMachine loanLifecycleStateMachine, final 
LoanTransaction transactionForAdjustment,
             final List<Long> existingTransactionIds, final List<Long> 
existingReversedTransactionIds,
-            final ScheduleGeneratorDTO scheduleGeneratorDTO, final AppUser 
currentUser) {
+            final ScheduleGeneratorDTO scheduleGeneratorDTO) {
 
         HolidayDetailDTO holidayDetailDTO = 
scheduleGeneratorDTO.getHolidayDetailDTO();
         
validateActivityNotBeforeLastTransactionDate(LoanEvent.LOAN_REPAYMENT_OR_WAIVER,
 transactionForAdjustment.getTransactionDate());
@@ -3675,14 +3671,14 @@ public class Loan extends AbstractPersistableCustom {
 
         if (newTransactionDetail.isRepaymentType() || 
newTransactionDetail.isInterestWaiver()) {
             changedTransactionDetail = 
handleRepaymentOrRecoveryOrWaiverTransaction(newTransactionDetail, 
loanLifecycleStateMachine,
-                    transactionForAdjustment, scheduleGeneratorDTO, 
currentUser);
+                    transactionForAdjustment, scheduleGeneratorDTO);
         }
 
         return changedTransactionDetail;
     }
 
     public ChangedTransactionDetail undoWrittenOff(final List<Long> 
existingTransactionIds, final List<Long> existingReversedTransactionIds,
-            final ScheduleGeneratorDTO scheduleGeneratorDTO, final AppUser 
currentUser) {
+            final ScheduleGeneratorDTO scheduleGeneratorDTO) {
 
         validateAccountStatus(LoanEvent.WRITE_OFF_OUTSTANDING_UNDO);
         existingTransactionIds.addAll(findExistingTransactionIds());
@@ -3694,7 +3690,7 @@ public class Loan extends AbstractPersistableCustom {
                 .determineProcessor(this.transactionProcessingStrategy);
         final List<LoanTransaction> allNonContraTransactionsPostDisbursement = 
retreiveListOfTransactionsPostDisbursement();
         if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
-            
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, 
currentUser);
+            
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
         }
         ChangedTransactionDetail changedTransactionDetail = 
loanRepaymentScheduleTransactionProcessor.handleTransaction(
                 getDisbursementDate(), 
allNonContraTransactionsPostDisbursement, getCurrency(), 
getRepaymentScheduleInstallments(),
@@ -3766,7 +3762,7 @@ public class Loan extends AbstractPersistableCustom {
         final LoanRepaymentScheduleTransactionProcessor 
loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
                 .determineProcessor(this.transactionProcessingStrategy);
         ChangedTransactionDetail changedTransactionDetail = 
closeDisbursements(scheduleGeneratorDTO,
-                loanRepaymentScheduleTransactionProcessor, currentUser);
+                loanRepaymentScheduleTransactionProcessor);
 
         validateAccountStatus(LoanEvent.WRITE_OFF_OUTSTANDING);
 
@@ -3805,7 +3801,7 @@ public class Loan extends AbstractPersistableCustom {
             }
 
             LocalDateTime createdDate = DateUtils.getLocalDateTimeOfTenant();
-            loanTransaction = LoanTransaction.writeoff(this, getOffice(), 
writtenOffOnLocalDate, txnExternalId, createdDate, currentUser);
+            loanTransaction = LoanTransaction.writeoff(this, getOffice(), 
writtenOffOnLocalDate, txnExternalId);
             LocalDate lastTransactionDate = getLastUserTransactionDate();
             if (lastTransactionDate.isAfter(writtenOffOnLocalDate)) {
                 final String errorMessage = "The date of the writeoff 
transaction must occur on or before previous transactions.";
@@ -3826,14 +3822,14 @@ public class Loan extends AbstractPersistableCustom {
     }
 
     private ChangedTransactionDetail closeDisbursements(final 
ScheduleGeneratorDTO scheduleGeneratorDTO,
-            final LoanRepaymentScheduleTransactionProcessor 
loanRepaymentScheduleTransactionProcessor, final AppUser currentUser) {
+            final LoanRepaymentScheduleTransactionProcessor 
loanRepaymentScheduleTransactionProcessor) {
         ChangedTransactionDetail changedTransactionDetail = null;
         if (isDisbursementAllowed() && atleastOnceDisbursed()) {
             
this.loanRepaymentScheduleDetail.setPrincipal(getDisbursedAmount());
             removeDisbursementDetail();
-            regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
+            regenerateRepaymentSchedule(scheduleGeneratorDTO);
             if 
(this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
-                
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, 
currentUser);
+                
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
             }
             final List<LoanTransaction> 
allNonContraTransactionsPostDisbursement = 
retreiveListOfTransactionsPostDisbursement();
             changedTransactionDetail = 
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
@@ -3862,7 +3858,7 @@ public class Loan extends AbstractPersistableCustom {
 
     public ChangedTransactionDetail close(final JsonCommand command, final 
LoanLifecycleStateMachine loanLifecycleStateMachine,
             final Map<String, Object> changes, final List<Long> 
existingTransactionIds, final List<Long> existingReversedTransactionIds,
-            final ScheduleGeneratorDTO scheduleGeneratorDTO, final AppUser 
currentUser) {
+            final ScheduleGeneratorDTO scheduleGeneratorDTO) {
 
         validateAccountStatus(LoanEvent.LOAN_CLOSED);
 
@@ -3890,7 +3886,7 @@ public class Loan extends AbstractPersistableCustom {
         final LoanRepaymentScheduleTransactionProcessor 
loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
                 .determineProcessor(this.transactionProcessingStrategy);
         ChangedTransactionDetail changedTransactionDetail = 
closeDisbursements(scheduleGeneratorDTO,
-                loanRepaymentScheduleTransactionProcessor, currentUser);
+                loanRepaymentScheduleTransactionProcessor);
 
         LoanTransaction loanTransaction = null;
         if (isOpen()) {
@@ -3904,8 +3900,7 @@ public class Loan extends AbstractPersistableCustom {
                     changes.put("status", 
LoanEnumerations.status(this.loanStatus));
                 }
                 this.closedOnDate = 
Date.from(closureDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
-                loanTransaction = LoanTransaction.writeoff(this, getOffice(), 
closureDate, txnExternalId,
-                        DateUtils.getLocalDateTimeOfTenant(), currentUser);
+                loanTransaction = LoanTransaction.writeoff(this, getOffice(), 
closureDate, txnExternalId);
                 final boolean isLastTransaction = 
isChronologicallyLatestTransaction(loanTransaction, getLoanTransactions());
                 if (!isLastTransaction) {
                     final String errorMessage = "The closing date of the loan 
must be on or after latest transaction date.";
@@ -5239,8 +5234,7 @@ public class Loan extends AbstractPersistableCustom {
     }
 
     public ChangedTransactionDetail 
updateDisbursementDateAndAmountForTranche(final LoanDisbursementDetails 
disbursementDetails,
-            final JsonCommand command, final Map<String, Object> 
actualChanges, final ScheduleGeneratorDTO scheduleGeneratorDTO,
-            final AppUser currentUser) {
+            final JsonCommand command, final Map<String, Object> 
actualChanges, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
         final Locale locale = command.extractLocale();
         validateAccountStatus(LoanEvent.LOAN_EDIT_MULTI_DISBURSE_DATE);
         final BigDecimal principal = 
command.bigDecimalValueOfParameterNamed(LoanApiConstants.updatedDisbursementPrincipalParameterName,
@@ -5266,9 +5260,9 @@ public class Loan extends AbstractPersistableCustom {
 
         this.loanRepaymentScheduleDetail.setPrincipal(setPrincipalAmount);
         if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
-            
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, 
currentUser);
+            
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
         } else {
-            regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
+            regenerateRepaymentSchedule(scheduleGeneratorDTO);
         }
 
         final LoanRepaymentScheduleTransactionProcessor 
loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
@@ -5365,7 +5359,7 @@ public class Loan extends AbstractPersistableCustom {
     }
 
     public ChangedTransactionDetail 
recalculateScheduleFromLastTransaction(final ScheduleGeneratorDTO generatorDTO,
-            final List<Long> existingTransactionIds, final List<Long> 
existingReversedTransactionIds, final AppUser currentUser) {
+            final List<Long> existingTransactionIds, final List<Long> 
existingReversedTransactionIds) {
         existingTransactionIds.addAll(findExistingTransactionIds());
         
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
         /*
@@ -5376,17 +5370,16 @@ public class Loan extends AbstractPersistableCustom {
          * loanTransaction.getTransactionDate(); } } 
generatorDTO.setRecalculateFrom(recalculateFrom);
          */
         if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
-            regenerateRepaymentScheduleWithInterestRecalculation(generatorDTO, 
currentUser);
+            regenerateRepaymentScheduleWithInterestRecalculation(generatorDTO);
         } else {
-            regenerateRepaymentSchedule(generatorDTO, currentUser);
+            regenerateRepaymentSchedule(generatorDTO);
         }
         return processTransactions();
 
     }
 
-    public ChangedTransactionDetail 
handleRegenerateRepaymentScheduleWithInterestRecalculation(final 
ScheduleGeneratorDTO generatorDTO,
-            final AppUser currentUser) {
-        regenerateRepaymentScheduleWithInterestRecalculation(generatorDTO, 
currentUser);
+    public ChangedTransactionDetail 
handleRegenerateRepaymentScheduleWithInterestRecalculation(final 
ScheduleGeneratorDTO generatorDTO) {
+        regenerateRepaymentScheduleWithInterestRecalculation(generatorDTO);
         return processTransactions();
 
     }
@@ -5413,14 +5406,14 @@ public class Loan extends AbstractPersistableCustom {
         return changedTransactionDetail;
     }
 
-    public void regenerateRepaymentScheduleWithInterestRecalculation(final 
ScheduleGeneratorDTO generatorDTO, final AppUser currentUser) {
+    public void regenerateRepaymentScheduleWithInterestRecalculation(final 
ScheduleGeneratorDTO generatorDTO) {
 
         LocalDate lastTransactionDate = getLastUserTransactionDate();
         final LoanScheduleDTO loanSchedule = 
getRecalculatedSchedule(generatorDTO);
         if (loanSchedule == null) {
             return;
         }
-        updateLoanSchedule(loanSchedule.getInstallments(), currentUser);
+        updateLoanSchedule(loanSchedule.getInstallments());
         this.interestRecalculatedOn = DateUtils.getBusinessDate();
         LocalDate lastRepaymentDate = this.getLastRepaymentPeriodDueDate(true);
         Set<LoanCharge> charges = this.charges();
@@ -5440,7 +5433,7 @@ public class Loan extends AbstractPersistableCustom {
         }
 
         processPostDisbursementTransactions();
-        processIncomeTransactions(currentUser);
+        processIncomeTransactions();
     }
 
     private void updateLoanChargesPaidBy(LoanTransaction accrual, 
HashMap<String, Object> feeDetails,
@@ -5468,7 +5461,7 @@ public class Loan extends AbstractPersistableCustom {
         }
     }
 
-    public void processIncomeTransactions(AppUser currentUser) {
+    public void processIncomeTransactions() {
         if (this.loanInterestRecalculationDetails != null && 
this.loanInterestRecalculationDetails.isCompoundingToBePostedAsTransaction()) {
             LocalDate lastCompoundingDate = this.getDisbursementDate();
             List<LoanInterestRecalcualtionAdditionalDetails> 
compoundingDetails = extractInterestRecalculationAdditionalDetails();
@@ -5480,8 +5473,7 @@ public class Loan extends AbstractPersistableCustom {
                 }
                 LoanTransaction incomeTransaction = 
getTransactionForDate(incomeTransactions, compoundingDetail.getEffectiveDate());
                 LoanTransaction accrualTransaction = 
getTransactionForDate(accrualTransactions, 
compoundingDetail.getEffectiveDate());
-                addUpdateIncomeAndAccrualTransaction(compoundingDetail, 
lastCompoundingDate, currentUser, incomeTransaction,
-                        accrualTransaction);
+                addUpdateIncomeAndAccrualTransaction(compoundingDetail, 
lastCompoundingDate, incomeTransaction, accrualTransaction);
                 lastCompoundingDate = compoundingDetail.getEffectiveDate();
             }
             List<LoanRepaymentScheduleInstallment> installments = 
getRepaymentScheduleInstallments();
@@ -5501,8 +5493,7 @@ public class Loan extends AbstractPersistableCustom {
     }
 
     private void 
addUpdateIncomeAndAccrualTransaction(LoanInterestRecalcualtionAdditionalDetails 
compoundingDetail,
-            LocalDate lastCompoundingDate, AppUser currentUser, 
LoanTransaction existingIncomeTransaction,
-            LoanTransaction existingAccrualTransaction) {
+            LocalDate lastCompoundingDate, LoanTransaction 
existingIncomeTransaction, LoanTransaction existingAccrualTransaction) {
         BigDecimal interest = BigDecimal.ZERO;
         BigDecimal fee = BigDecimal.ZERO;
         BigDecimal penalties = BigDecimal.ZERO;
@@ -5525,28 +5516,26 @@ public class Loan extends AbstractPersistableCustom {
         }
 
         if (existingIncomeTransaction == null) {
-            LoanTransaction transaction = LoanTransaction.incomePosting(this, 
this.getOffice(),
-                    
Date.from(compoundingDetail.getEffectiveDate().atStartOfDay(ZoneId.systemDefault()).toInstant()),
-                    compoundingDetail.getAmount(), interest, fee, penalties, 
currentUser);
+            LoanTransaction transaction = LoanTransaction.incomePosting(this, 
this.getOffice(), compoundingDetail.getEffectiveDate(),
+                    compoundingDetail.getAmount(), interest, fee, penalties);
             addLoanTransaction(transaction);
         } else if 
(existingIncomeTransaction.getAmount(getCurrency()).getAmount().compareTo(compoundingDetail.getAmount())
 != 0) {
             existingIncomeTransaction.reverse();
-            LoanTransaction transaction = LoanTransaction.incomePosting(this, 
this.getOffice(),
-                    
Date.from(compoundingDetail.getEffectiveDate().atStartOfDay(ZoneId.systemDefault()).toInstant()),
-                    compoundingDetail.getAmount(), interest, fee, penalties, 
currentUser);
+            LoanTransaction transaction = LoanTransaction.incomePosting(this, 
this.getOffice(), compoundingDetail.getEffectiveDate(),
+                    compoundingDetail.getAmount(), interest, fee, penalties);
             addLoanTransaction(transaction);
         }
 
         if (isPeriodicAccrualAccountingEnabledOnLoanProduct()) {
             if (existingAccrualTransaction == null) {
                 LoanTransaction accrual = 
LoanTransaction.accrueTransaction(this, this.getOffice(), 
compoundingDetail.getEffectiveDate(),
-                        compoundingDetail.getAmount(), interest, fee, 
penalties, currentUser);
+                        compoundingDetail.getAmount(), interest, fee, 
penalties);
                 updateLoanChargesPaidBy(accrual, feeDetails, null);
                 addLoanTransaction(accrual);
             } else if 
(existingAccrualTransaction.getAmount(getCurrency()).getAmount().compareTo(compoundingDetail.getAmount())
 != 0) {
                 existingAccrualTransaction.reverse();
                 LoanTransaction accrual = 
LoanTransaction.accrueTransaction(this, this.getOffice(), 
compoundingDetail.getEffectiveDate(),
-                        compoundingDetail.getAmount(), interest, fee, 
penalties, currentUser);
+                        compoundingDetail.getAmount(), interest, fee, 
penalties);
                 updateLoanChargesPaidBy(accrual, feeDetails, null);
                 addLoanTransaction(accrual);
             }
@@ -6293,7 +6282,7 @@ public class Loan extends AbstractPersistableCustom {
     }
 
     public Map<String, Object> undoLastDisbursal(ScheduleGeneratorDTO 
scheduleGeneratorDTO, List<Long> existingTransactionIds,
-            List<Long> existingReversedTransactionIds, AppUser currentUser, 
Loan loan) {
+            List<Long> existingReversedTransactionIds, Loan loan) {
 
         validateAccountStatus(LoanEvent.LOAN_DISBURSAL_UNDO_LAST);
         existingTransactionIds.addAll(findExistingTransactionIds());
@@ -6331,8 +6320,7 @@ public class Loan extends AbstractPersistableCustom {
             }
         }
         reverseExistingTransactionsTillLastDisbursal(actualDisbursementDate);
-        loan.recalculateScheduleFromLastTransaction(scheduleGeneratorDTO, 
existingTransactionIds, existingReversedTransactionIds,
-                currentUser);
+        loan.recalculateScheduleFromLastTransaction(scheduleGeneratorDTO, 
existingTransactionIds, existingReversedTransactionIds);
         actualChanges.put("undolastdisbursal", "true");
         actualChanges.put("disbursedAmount", this.getDisbursedAmount());
         updateLoanSummaryDerivedFields();
@@ -6671,16 +6659,14 @@ public class Loan extends AbstractPersistableCustom {
     }
 
     public ChangedTransactionDetail handleForeClosureTransactions(final 
LoanTransaction repaymentTransaction,
-            final LoanLifecycleStateMachine loanLifecycleStateMachine, final 
ScheduleGeneratorDTO scheduleGeneratorDTO,
-            final AppUser appUser) {
+            final LoanLifecycleStateMachine loanLifecycleStateMachine, final 
ScheduleGeneratorDTO scheduleGeneratorDTO) {
 
         LoanEvent event = LoanEvent.LOAN_FORECLOSURE;
         validateAccountStatus(event);
         validateForForeclosure(repaymentTransaction.getTransactionDate());
         this.loanSubStatus = LoanSubStatus.FORECLOSED.getValue();
-        applyAccurals(appUser);
-        return 
handleRepaymentOrRecoveryOrWaiverTransaction(repaymentTransaction, 
loanLifecycleStateMachine, null, scheduleGeneratorDTO,
-                appUser);
+        applyAccurals();
+        return 
handleRepaymentOrRecoveryOrWaiverTransaction(repaymentTransaction, 
loanLifecycleStateMachine, null, scheduleGeneratorDTO);
     }
 
     public Money retrieveAccruedAmountAfterDate(final LocalDate tillDate) {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
index f26039000..20b4ae39b 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java
@@ -178,13 +178,12 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
 
         final Money repaymentAmount = Money.of(loan.getCurrency(), 
transactionAmount);
         LoanTransaction newRepaymentTransaction = null;
-        final LocalDateTime currentDateTime = 
DateUtils.getLocalDateTimeOfTenant();
         if (isRecoveryRepayment) {
             newRepaymentTransaction = 
LoanTransaction.recoveryRepayment(loan.getOffice(), repaymentAmount, 
paymentDetail, transactionDate,
-                    txnExternalId, currentDateTime, currentUser);
+                    txnExternalId);
         } else {
             newRepaymentTransaction = 
LoanTransaction.repaymentType(repaymentTransactionType, loan.getOffice(), 
repaymentAmount,
-                    paymentDetail, transactionDate, txnExternalId, 
currentDateTime, currentUser);
+                    paymentDetail, transactionDate, txnExternalId);
         }
 
         LocalDate recalculateFrom = null;
@@ -196,7 +195,7 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
 
         final ChangedTransactionDetail changedTransactionDetail = 
loan.makeRepayment(newRepaymentTransaction,
                 defaultLoanLifecycleStateMachine(), existingTransactionIds, 
existingReversedTransactionIds, isRecoveryRepayment,
-                scheduleGeneratorDTO, currentUser, isHolidayValidationDone);
+                scheduleGeneratorDTO, isHolidayValidationDone);
 
         
saveLoanTransactionWithDataIntegrityViolationChecks(newRepaymentTransaction);
 
@@ -361,7 +360,6 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
     public LoanTransaction makeChargePayment(final Loan loan, final Long 
chargeId, final LocalDate transactionDate,
             final BigDecimal transactionAmount, final PaymentDetail 
paymentDetail, final String noteText, final String txnExternalId,
             final Integer transactionType, Integer installmentNumber) {
-        AppUser currentUser = getAppUserIfPresent();
         boolean isAccountTransfer = true;
         checkClientOrGroupActive(loan);
         businessEventNotifierService.notifyPreBusinessEvent(new 
LoanChargePaymentPreBusinessEvent(loan));
@@ -373,7 +371,7 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
         final LoanTransactionType loanTransactionType = 
LoanTransactionType.fromInt(transactionType);
 
         final LoanTransaction newPaymentTransaction = 
LoanTransaction.loanPayment(null, loan.getOffice(), paymentAmout, paymentDetail,
-                transactionDate, txnExternalId, loanTransactionType, 
DateUtils.getLocalDateTimeOfTenant(), currentUser);
+                transactionDate, txnExternalId, loanTransactionType);
 
         if (loanTransactionType.isRepaymentAtDisbursement()) {
             loan.handlePayDisbursementTransaction(chargeId, 
newPaymentTransaction, existingTransactionIds, existingReversedTransactionIds);
@@ -445,7 +443,6 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
     public LoanTransaction makeRefund(final Long accountId, final 
CommandProcessingResultBuilder builderResult,
             final LocalDate transactionDate, final BigDecimal 
transactionAmount, final PaymentDetail paymentDetail, final String noteText,
             final String txnExternalId) {
-        AppUser currentUser = getAppUserIfPresent();
         boolean isAccountTransfer = true;
         final Loan loan = this.loanAccountAssembler.assembleFrom(accountId);
         checkClientOrGroupActive(loan);
@@ -455,7 +452,7 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
 
         final Money refundAmount = Money.of(loan.getCurrency(), 
transactionAmount);
         final LoanTransaction newRefundTransaction = 
LoanTransaction.refund(loan.getOffice(), refundAmount, paymentDetail, 
transactionDate,
-                txnExternalId, DateUtils.getLocalDateTimeOfTenant(), 
currentUser);
+                txnExternalId);
         final boolean allowTransactionsOnHoliday = 
this.configurationDomainService.allowTransactionsOnHolidayEnabled();
         final List<Holiday> holidays = 
this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(),
                 
Date.from(transactionDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), 
HolidayStatusType.ACTIVE.getValue());
@@ -492,7 +489,6 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
     @Override
     public LoanTransaction makeDisburseTransaction(final Long loanId, final 
LocalDate transactionDate, final BigDecimal transactionAmount,
             final PaymentDetail paymentDetail, final String noteText, final 
String txnExternalId, final boolean isLoanToLoanTransfer) {
-        AppUser currentUser = getAppUserIfPresent();
         final Loan loan = this.loanAccountAssembler.assembleFrom(loanId);
         checkClientOrGroupActive(loan);
         boolean isAccountTransfer = true;
@@ -500,7 +496,7 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
         final List<Long> existingReversedTransactionIds = new ArrayList<>();
         final Money amount = Money.of(loan.getCurrency(), transactionAmount);
         LoanTransaction disbursementTransaction = 
LoanTransaction.disbursement(loan.getOffice(), amount, paymentDetail, 
transactionDate,
-                txnExternalId, DateUtils.getLocalDateTimeOfTenant(), 
currentUser);
+                txnExternalId);
 
         // Subtract Previous loan outstanding balance from netDisbursalAmount
         loan.deductFromNetDisbursalAmount(transactionAmount);
@@ -646,11 +642,10 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
         businessEventNotifierService.notifyPreBusinessEvent(new 
LoanCreditBalanceRefundPreBusinessEvent(loan));
         final List<Long> existingTransactionIds = new ArrayList<>();
         final List<Long> existingReversedTransactionIds = new ArrayList<>();
-        AppUser currentUser = getAppUserIfPresent();
 
         final Money refundAmount = Money.of(loan.getCurrency(), 
transactionAmount);
         final LoanTransaction newCreditBalanceRefundTransaction = 
LoanTransaction.creditBalanceRefund(loan, loan.getOffice(), refundAmount,
-                transactionDate, externalId, 
DateUtils.getLocalDateTimeOfTenant(), currentUser);
+                transactionDate, externalId);
 
         loan.creditBalanceRefund(newCreditBalanceRefundTransaction, 
defaultLoanLifecycleStateMachine(), existingTransactionIds,
                 existingReversedTransactionIds);
@@ -681,11 +676,10 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
         businessEventNotifierService.notifyPreBusinessEvent(new 
LoanRefundPreBusinessEvent(loan));
         final List<Long> existingTransactionIds = new ArrayList<>();
         final List<Long> existingReversedTransactionIds = new ArrayList<>();
-        AppUser currentUser = getAppUserIfPresent();
 
         final Money refundAmount = Money.of(loan.getCurrency(), 
transactionAmount);
         final LoanTransaction newRefundTransaction = 
LoanTransaction.refundForActiveLoan(loan.getOffice(), refundAmount, 
paymentDetail,
-                transactionDate, txnExternalId, 
DateUtils.getLocalDateTimeOfTenant(), currentUser);
+                transactionDate, txnExternalId);
         final boolean allowTransactionsOnHoliday = 
this.configurationDomainService.allowTransactionsOnHolidayEnabled();
         final List<Holiday> holidays = 
this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(),
                 
Date.from(transactionDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), 
HolidayStatusType.ACTIVE.getValue());
@@ -716,7 +710,6 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
     public Map<String, Object> foreCloseLoan(final Loan loan, final LocalDate 
foreClosureDate, final String noteText) {
         businessEventNotifierService.notifyPreBusinessEvent(new 
LoanForeClosurePreBusinessEvent(loan));
         MonetaryCurrency currency = loan.getCurrency();
-        LocalDateTime createdDate = DateUtils.getLocalDateTimeOfTenant();
         final Map<String, Object> changes = new LinkedHashMap<>();
         List<LoanTransaction> newTransactions = new ArrayList<>();
 
@@ -737,12 +730,11 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
             Money total = 
interestPortion.plus(feePortion).plus(penaltyPortion);
             if (total.isGreaterThanZero()) {
                 LoanTransaction accrualTransaction = 
LoanTransaction.accrueTransaction(loan, loan.getOffice(), foreClosureDate,
-                        total.getAmount(), interestPortion.getAmount(), 
feePortion.getAmount(), penaltyPortion.getAmount(), appUser);
+                        total.getAmount(), interestPortion.getAmount(), 
feePortion.getAmount(), penaltyPortion.getAmount());
                 LocalDate fromDate = loan.getDisbursementDate();
                 if (loan.getAccruedTill() != null) {
                     fromDate = loan.getAccruedTill();
                 }
-                createdDate = createdDate.plusSeconds(1);
                 newTransactions.add(accrualTransaction);
                 loan.addLoanTransaction(accrualTransaction);
                 Set<LoanChargePaidBy> accrualCharges = 
accrualTransaction.getLoanChargesPaid();
@@ -771,16 +763,14 @@ public class LoanAccountDomainServiceJpa implements 
LoanAccountDomainService {
             String externalId = null;
             final LocalDateTime currentDateTime = 
DateUtils.getLocalDateTimeOfTenant();
             payment = LoanTransaction.repayment(loan.getOffice(), 
payPrincipal.plus(interestPayable).plus(feePayable).plus(penaltyPayable),
-                    paymentDetail, foreClosureDate, externalId, 
currentDateTime, appUser);
-            createdDate = createdDate.plusSeconds(1);
-            
payment.updateCreatedDate(Date.from(createdDate.atZone(DateUtils.getDateTimeZoneOfTenant()).toInstant()));
+                    paymentDetail, foreClosureDate, externalId);
             payment.updateLoan(loan);
             newTransactions.add(payment);
         }
 
         List<Long> transactionIds = new ArrayList<>();
         final ChangedTransactionDetail changedTransactionDetail = 
loan.handleForeClosureTransactions(payment,
-                defaultLoanLifecycleStateMachine(), scheduleGeneratorDTO, 
appUser);
+                defaultLoanLifecycleStateMachine(), scheduleGeneratorDTO);
 
         /***
          * TODO Vishwas Batch save is giving me a 
HibernateOptimisticLockingFailureException, looping and saving for the
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
index ebb1bcc18..2bc2c881f 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
@@ -21,10 +21,8 @@ package org.apache.fineract.portfolio.loanaccount.domain;
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
-import java.time.ZoneId;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -38,10 +36,8 @@ import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
 import javax.persistence.UniqueConstraint;
-import 
org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
+import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.organisation.monetary.data.CurrencyData;
 import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
@@ -53,7 +49,6 @@ import 
org.apache.fineract.portfolio.loanaccount.data.LoanTransactionEnumData;
 import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
 import org.apache.fineract.portfolio.paymentdetail.data.PaymentDetailData;
 import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
-import org.apache.fineract.useradministration.domain.AppUser;
 
 /**
  * All monetary transactions against a loan are modelled through this entity. 
Disbursements, Repayments, Waivers,
@@ -61,7 +56,7 @@ import org.apache.fineract.useradministration.domain.AppUser;
  */
 @Entity
 @Table(name = "m_loan_transaction", uniqueConstraints = { 
@UniqueConstraint(columnNames = { "external_id" }, name = "external_id_UNIQUE") 
})
-public class LoanTransaction extends AbstractPersistableCustom {
+public class LoanTransaction extends AbstractAuditableCustom {
 
     @ManyToOne(optional = false)
     @JoinColumn(name = "loan_id", nullable = false)
@@ -78,13 +73,11 @@ public class LoanTransaction extends 
AbstractPersistableCustom {
     @Column(name = "transaction_type_enum", nullable = false)
     private Integer typeOf;
 
-    @Temporal(TemporalType.DATE)
     @Column(name = "transaction_date", nullable = false)
-    private Date dateOf;
+    private LocalDate dateOf;
 
-    @Temporal(TemporalType.DATE)
     @Column(name = "submitted_on_date", nullable = false)
-    private Date submittedOnDate;
+    private LocalDate submittedOnDate;
 
     @Column(name = "amount", scale = 6, precision = 19, nullable = false)
     private BigDecimal amount;
@@ -113,14 +106,6 @@ public class LoanTransaction extends 
AbstractPersistableCustom {
     @Column(name = "external_id", length = 100, nullable = true, unique = true)
     private String externalId;
 
-    @Temporal(TemporalType.TIMESTAMP)
-    @Column(name = "created_date", nullable = false)
-    private Date createdDate;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @JoinColumn(name = "appuser_id", nullable = true)
-    private AppUser appUser;
-
     @OneToMany(cascade = CascadeType.ALL, mappedBy = "loanTransaction", 
orphanRemoval = true, fetch = FetchType.EAGER)
     private Set<LoanChargePaidBy> loanChargesPaid = new HashSet<>();
 
@@ -136,44 +121,34 @@ public class LoanTransaction extends 
AbstractPersistableCustom {
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = 
FetchType.EAGER, mappedBy = "loanTransaction")
     private Set<LoanTransactionToRepaymentScheduleMapping> 
loanTransactionToRepaymentScheduleMappings = new HashSet<>();
 
-    protected LoanTransaction() {
-        /*
-         * this.loan = null; this.dateOf = null; this.typeOf = null; 
this.submittedOnDate = DateUtils.getDateOfTenant();
-         * this.createdDate = new Date(); this.appUser = null;
-         */
-    }
+    protected LoanTransaction() {}
 
-    public static LoanTransaction incomePosting(final Loan loan, final Office 
office, final Date dateOf, final BigDecimal amount,
-            final BigDecimal interestPortion, final BigDecimal 
feeChargesPortion, final BigDecimal penaltyChargesPortion,
-            final AppUser appUser) {
+    public static LoanTransaction incomePosting(final Loan loan, final Office 
office, final LocalDate dateOf, final BigDecimal amount,
+            final BigDecimal interestPortion, final BigDecimal 
feeChargesPortion, final BigDecimal penaltyChargesPortion) {
         final Integer typeOf = LoanTransactionType.INCOME_POSTING.getValue();
         final BigDecimal principalPortion = BigDecimal.ZERO;
         final BigDecimal overPaymentPortion = BigDecimal.ZERO;
         final boolean reversed = false;
         final PaymentDetail paymentDetail = null;
         final String externalId = null;
-        final LocalDateTime createdDate = DateUtils.getLocalDateTimeOfTenant();
         return new LoanTransaction(loan, office, typeOf, dateOf, amount, 
principalPortion, interestPortion, feeChargesPortion,
-                penaltyChargesPortion, overPaymentPortion, reversed, 
paymentDetail, externalId, createdDate, appUser);
+                penaltyChargesPortion, overPaymentPortion, reversed, 
paymentDetail, externalId);
     }
 
     public static LoanTransaction disbursement(final Office office, final 
Money amount, final PaymentDetail paymentDetail,
-            final LocalDate disbursementDate, final String externalId, final 
LocalDateTime createdDate, final AppUser appUser) {
+            final LocalDate disbursementDate, final String externalId) {
         return new LoanTransaction(null, office, 
LoanTransactionType.DISBURSEMENT, paymentDetail, amount.getAmount(), 
disbursementDate,
-                externalId, createdDate, appUser);
+                externalId);
     }
 
     public static LoanTransaction repayment(final Office office, final Money 
amount, final PaymentDetail paymentDetail,
-            final LocalDate paymentDate, final String externalId, final 
LocalDateTime createdDate, final AppUser appUser) {
-        return new LoanTransaction(null, office, 
LoanTransactionType.REPAYMENT, paymentDetail, amount.getAmount(), paymentDate, 
externalId,
-                createdDate, appUser);
+            final LocalDate paymentDate, final String externalId) {
+        return new LoanTransaction(null, office, 
LoanTransactionType.REPAYMENT, paymentDetail, amount.getAmount(), paymentDate, 
externalId);
     }
 
     public static LoanTransaction repaymentType(final LoanTransactionType 
repaymentType, final Office office, final Money amount,
-            final PaymentDetail paymentDetail, final LocalDate paymentDate, 
final String externalId, final LocalDateTime createdDate,
-            final AppUser appUser) {
-        return new LoanTransaction(null, office, repaymentType, paymentDetail, 
amount.getAmount(), paymentDate, externalId, createdDate,
-                appUser);
+            final PaymentDetail paymentDetail, final LocalDate paymentDate, 
final String externalId) {
+        return new LoanTransaction(null, office, repaymentType, paymentDetail, 
amount.getAmount(), paymentDate, externalId);
     }
 
     public void setLoanTransactionToRepaymentScheduleMappings(final Integer 
installmentId, final BigDecimal chargePerInstallment) {
@@ -189,34 +164,32 @@ public class LoanTransaction extends 
AbstractPersistableCustom {
     }
 
     public static LoanTransaction recoveryRepayment(final Office office, final 
Money amount, final PaymentDetail paymentDetail,
-            final LocalDate paymentDate, final String externalId, final 
LocalDateTime createdDate, final AppUser appUser) {
+            final LocalDate paymentDate, final String externalId) {
         return new LoanTransaction(null, office, 
LoanTransactionType.RECOVERY_REPAYMENT, paymentDetail, amount.getAmount(), 
paymentDate,
-                externalId, createdDate, appUser);
+                externalId);
     }
 
     public static LoanTransaction loanPayment(final Loan loan, final Office 
office, final Money amount, final PaymentDetail paymentDetail,
-            final LocalDate paymentDate, final String externalId, final 
LoanTransactionType transactionType,
-            final LocalDateTime createdDate, final AppUser appUser) {
-        return new LoanTransaction(loan, office, transactionType, 
paymentDetail, amount.getAmount(), paymentDate, externalId, createdDate,
-                appUser);
+            final LocalDate paymentDate, final String externalId, final 
LoanTransactionType transactionType) {
+        return new LoanTransaction(loan, office, transactionType, 
paymentDetail, amount.getAmount(), paymentDate, externalId);
     }
 
     public static LoanTransaction repaymentAtDisbursement(final Office office, 
final Money amount, final PaymentDetail paymentDetail,
-            final LocalDate paymentDate, final String externalId, final 
LocalDateTime createdDate, final AppUser appUser) {
+            final LocalDate paymentDate, final String externalId) {
         return new LoanTransaction(null, office, 
LoanTransactionType.REPAYMENT_AT_DISBURSEMENT, paymentDetail, 
amount.getAmount(),
-                paymentDate, externalId, createdDate, appUser);
+                paymentDate, externalId);
     }
 
     public static LoanTransaction waiver(final Office office, final Loan loan, 
final Money amount, final LocalDate waiveDate,
-            final Money waived, final Money unrecognizedPortion, final 
LocalDateTime createdDate, final AppUser appUser) {
+            final Money waived, final Money unrecognizedPortion) {
         LoanTransaction loanTransaction = new LoanTransaction(loan, office, 
LoanTransactionType.WAIVE_INTEREST, amount.getAmount(),
-                waiveDate, null, createdDate, appUser);
+                waiveDate, null);
         loanTransaction.updateInterestComponent(waived, unrecognizedPortion);
         return loanTransaction;
     }
 
     public static LoanTransaction accrueInterest(final Office office, final 
Loan loan, final Money amount,
-            final LocalDate interestAppliedDate, final LocalDateTime 
createdDate, final AppUser appUser) {
+            final LocalDate interestAppliedDate) {
         BigDecimal principalPortion = null;
         BigDecimal feesPortion = null;
         BigDecimal penaltiesPortion = null;
@@ -225,96 +198,80 @@ public class LoanTransaction extends 
AbstractPersistableCustom {
         boolean reversed = false;
         PaymentDetail paymentDetail = null;
         String externalId = null;
-        return new LoanTransaction(loan, office, 
LoanTransactionType.ACCRUAL.getValue(),
-                
Date.from(interestAppliedDate.atStartOfDay(ZoneId.systemDefault()).toInstant()),
 interestPortion, principalPortion,
-                interestPortion, feesPortion, penaltiesPortion, 
overPaymentPortion, reversed, paymentDetail, externalId, createdDate,
-                appUser);
+        return new LoanTransaction(loan, office, 
LoanTransactionType.ACCRUAL.getValue(), interestAppliedDate, interestPortion,
+                principalPortion, interestPortion, feesPortion, 
penaltiesPortion, overPaymentPortion, reversed, paymentDetail, externalId);
     }
 
     public static LoanTransaction accrual(final Loan loan, final Office 
office, final Money amount, final Money interest,
             final Money feeCharges, final Money penaltyCharges, final 
LocalDate transactionDate) {
-        final AppUser appUser = null;
         return accrueTransaction(loan, office, transactionDate, 
amount.getAmount(), interest.getAmount(), feeCharges.getAmount(),
-                penaltyCharges.getAmount(), appUser);
+                penaltyCharges.getAmount());
     }
 
     public static LoanTransaction accrueTransaction(final Loan loan, final 
Office office, final LocalDate dateOf, final BigDecimal amount,
-            final BigDecimal interestPortion, final BigDecimal 
feeChargesPortion, final BigDecimal penaltyChargesPortion,
-            final AppUser appUser) {
+            final BigDecimal interestPortion, final BigDecimal 
feeChargesPortion, final BigDecimal penaltyChargesPortion) {
         BigDecimal principalPortion = null;
         BigDecimal overPaymentPortion = null;
         boolean reversed = false;
         PaymentDetail paymentDetail = null;
         String externalId = null;
-        LocalDateTime createdDate = DateUtils.getLocalDateTimeOfTenant();
-        return new LoanTransaction(loan, office, 
LoanTransactionType.ACCRUAL.getValue(),
-                
Date.from(dateOf.atStartOfDay(ZoneId.systemDefault()).toInstant()), amount, 
principalPortion, interestPortion,
-                feeChargesPortion, penaltyChargesPortion, overPaymentPortion, 
reversed, paymentDetail, externalId, createdDate, appUser);
+        return new LoanTransaction(loan, office, 
LoanTransactionType.ACCRUAL.getValue(), dateOf, amount, principalPortion, 
interestPortion,
+                feeChargesPortion, penaltyChargesPortion, overPaymentPortion, 
reversed, paymentDetail, externalId);
     }
 
-    public static LoanTransaction initiateTransfer(final Office office, final 
Loan loan, final LocalDate transferDate,
-            final LocalDateTime createdDate, final AppUser appUser) {
-        return new LoanTransaction(loan, office, 
LoanTransactionType.INITIATE_TRANSFER.getValue(),
-                
Date.from(transferDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), 
loan.getSummary().getTotalOutstanding(),
-                loan.getSummary().getTotalPrincipalOutstanding(), 
loan.getSummary().getTotalInterestOutstanding(),
-                loan.getSummary().getTotalFeeChargesOutstanding(), 
loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null,
-                null, createdDate, appUser);
+    public static LoanTransaction initiateTransfer(final Office office, final 
Loan loan, final LocalDate transferDate) {
+        return new LoanTransaction(loan, office, 
LoanTransactionType.INITIATE_TRANSFER.getValue(), transferDate,
+                loan.getSummary().getTotalOutstanding(), 
loan.getSummary().getTotalPrincipalOutstanding(),
+                loan.getSummary().getTotalInterestOutstanding(), 
loan.getSummary().getTotalFeeChargesOutstanding(),
+                loan.getSummary().getTotalPenaltyChargesOutstanding(), null, 
false, null, null);
     }
 
-    public static LoanTransaction approveTransfer(final Office office, final 
Loan loan, final LocalDate transferDate,
-            final LocalDateTime createdDate, final AppUser appUser) {
-        return new LoanTransaction(loan, office, 
LoanTransactionType.APPROVE_TRANSFER.getValue(),
-                
Date.from(transferDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), 
loan.getSummary().getTotalOutstanding(),
-                loan.getSummary().getTotalPrincipalOutstanding(), 
loan.getSummary().getTotalInterestOutstanding(),
-                loan.getSummary().getTotalFeeChargesOutstanding(), 
loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null,
-                null, createdDate, appUser);
+    public static LoanTransaction approveTransfer(final Office office, final 
Loan loan, final LocalDate transferDate) {
+        return new LoanTransaction(loan, office, 
LoanTransactionType.APPROVE_TRANSFER.getValue(), transferDate,
+                loan.getSummary().getTotalOutstanding(), 
loan.getSummary().getTotalPrincipalOutstanding(),
+                loan.getSummary().getTotalInterestOutstanding(), 
loan.getSummary().getTotalFeeChargesOutstanding(),
+                loan.getSummary().getTotalPenaltyChargesOutstanding(), null, 
false, null, null);
     }
 
-    public static LoanTransaction withdrawTransfer(final Office office, final 
Loan loan, final LocalDate transferDate,
-            final LocalDateTime createdDate, final AppUser appUser) {
-        return new LoanTransaction(loan, office, 
LoanTransactionType.WITHDRAW_TRANSFER.getValue(),
-                
Date.from(transferDate.atStartOfDay(ZoneId.systemDefault()).toInstant()), 
loan.getSummary().getTotalOutstanding(),
-                loan.getSummary().getTotalPrincipalOutstanding(), 
loan.getSummary().getTotalInterestOutstanding(),
-                loan.getSummary().getTotalFeeChargesOutstanding(), 
loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null,
-                null, createdDate, appUser);
+    public static LoanTransaction withdrawTransfer(final Office office, final 
Loan loan, final LocalDate transferDate) {
+        return new LoanTransaction(loan, office, 
LoanTransactionType.WITHDRAW_TRANSFER.getValue(), transferDate,
+                loan.getSummary().getTotalOutstanding(), 
loan.getSummary().getTotalPrincipalOutstanding(),
+                loan.getSummary().getTotalInterestOutstanding(), 
loan.getSummary().getTotalFeeChargesOutstanding(),
+                loan.getSummary().getTotalPenaltyChargesOutstanding(), null, 
false, null, null);
     }
 
     public static LoanTransaction refund(final Office office, final Money 
amount, final PaymentDetail paymentDetail,
-            final LocalDate paymentDate, final String externalId, final 
LocalDateTime createdDate, final AppUser appUser) {
-        return new LoanTransaction(null, office, LoanTransactionType.REFUND, 
paymentDetail, amount.getAmount(), paymentDate, externalId,
-                createdDate, appUser);
+            final LocalDate paymentDate, final String externalId) {
+        return new LoanTransaction(null, office, LoanTransactionType.REFUND, 
paymentDetail, amount.getAmount(), paymentDate, externalId);
     }
 
     public static LoanTransaction copyTransactionProperties(final 
LoanTransaction loanTransaction) {
         return new LoanTransaction(loanTransaction.loan, 
loanTransaction.office, loanTransaction.typeOf, loanTransaction.dateOf,
                 loanTransaction.amount, loanTransaction.principalPortion, 
loanTransaction.interestPortion,
                 loanTransaction.feeChargesPortion, 
loanTransaction.penaltyChargesPortion, loanTransaction.overPaymentPortion,
-                loanTransaction.reversed, loanTransaction.paymentDetail, 
loanTransaction.externalId,
-                (loanTransaction.createdDate == null) ? 
LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant())
-                        : 
LocalDateTime.ofInstant(loanTransaction.createdDate.toInstant(), 
DateUtils.getDateTimeZoneOfTenant()),
-                loanTransaction.appUser);
+                loanTransaction.reversed, loanTransaction.paymentDetail, 
loanTransaction.externalId);
     }
 
     public static LoanTransaction accrueLoanCharge(final Loan loan, final 
Office office, final Money amount, final LocalDate applyDate,
-            final Money feeCharges, final Money penaltyCharges, final 
LocalDateTime createdDate, final AppUser appUser) {
+            final Money feeCharges, final Money penaltyCharges) {
         String externalId = null;
         final LoanTransaction applyCharge = new LoanTransaction(loan, office, 
LoanTransactionType.ACCRUAL, amount.getAmount(), applyDate,
-                externalId, createdDate, appUser);
+                externalId);
         applyCharge.updateChargesComponents(feeCharges, penaltyCharges);
         return applyCharge;
     }
 
     public static LoanTransaction creditBalanceRefund(final Loan loan, final 
Office office, final Money amount, final LocalDate paymentDate,
-            final String externalId, final LocalDateTime createdDate, final 
AppUser appUser) {
+            final String externalId) {
         final PaymentDetail paymentDetail = null;
         return new LoanTransaction(loan, office, 
LoanTransactionType.CREDIT_BALANCE_REFUND, paymentDetail, amount.getAmount(), 
paymentDate,
-                externalId, createdDate, appUser);
+                externalId);
     }
 
     public static LoanTransaction refundForActiveLoan(final Office office, 
final Money amount, final PaymentDetail paymentDetail,
-            final LocalDate paymentDate, final String externalId, final 
LocalDateTime createdDate, final AppUser appUser) {
+            final LocalDate paymentDate, final String externalId) {
         return new LoanTransaction(null, office, 
LoanTransactionType.REFUND_FOR_ACTIVE_LOAN, paymentDetail, amount.getAmount(), 
paymentDate,
-                externalId, createdDate, appUser);
+                externalId);
     }
 
     public static boolean transactionAmountsMatch(final MonetaryCurrency 
currency, final LoanTransaction loanTransaction,
@@ -330,10 +287,10 @@ public class LoanTransaction extends 
AbstractPersistableCustom {
         return false;
     }
 
-    private LoanTransaction(final Loan loan, final Office office, final 
Integer typeOf, final Date dateOf, final BigDecimal amount,
+    private LoanTransaction(final Loan loan, final Office office, final 
Integer typeOf, final LocalDate dateOf, final BigDecimal amount,
             final BigDecimal principalPortion, final BigDecimal 
interestPortion, final BigDecimal feeChargesPortion,
             final BigDecimal penaltyChargesPortion, final BigDecimal 
overPaymentPortion, final boolean reversed,
-            final PaymentDetail paymentDetail, final String externalId, final 
LocalDateTime createdDate, final AppUser appUser) {
+            final PaymentDetail paymentDetail, final String externalId) {
 
         this.loan = loan;
         this.typeOf = typeOf;
@@ -348,52 +305,43 @@ public class LoanTransaction extends 
AbstractPersistableCustom {
         this.paymentDetail = paymentDetail;
         this.office = office;
         this.externalId = externalId;
-        this.submittedOnDate = DateUtils.getBusinessDate();
-        this.createdDate = 
Date.from(createdDate.atZone(DateUtils.getDateTimeZoneOfTenant()).toInstant());
-        this.appUser = appUser;
+        this.submittedOnDate = DateUtils.getBusinessLocalDate();
     }
 
     public static LoanTransaction waiveLoanCharge(final Loan loan, final 
Office office, final Money waived, final LocalDate waiveDate,
-            final Money feeChargesWaived, final Money penaltyChargesWaived, 
final Money unrecognizedCharge, final LocalDateTime createdDate,
-            final AppUser appUser) {
+            final Money feeChargesWaived, final Money penaltyChargesWaived, 
final Money unrecognizedCharge) {
         final LoanTransaction waiver = new LoanTransaction(loan, office, 
LoanTransactionType.WAIVE_CHARGES, waived.getAmount(), waiveDate,
-                null, createdDate, appUser);
+                null);
         waiver.updateChargesComponents(feeChargesWaived, penaltyChargesWaived, 
unrecognizedCharge);
 
         return waiver;
     }
 
-    public static LoanTransaction writeoff(final Loan loan, final Office 
office, final LocalDate writeOffDate, final String externalId,
-            final LocalDateTime createdDate, final AppUser appUser) {
-        return new LoanTransaction(loan, office, LoanTransactionType.WRITEOFF, 
null, writeOffDate, externalId, createdDate, appUser);
+    public static LoanTransaction writeoff(final Loan loan, final Office 
office, final LocalDate writeOffDate, final String externalId) {
+        return new LoanTransaction(loan, office, LoanTransactionType.WRITEOFF, 
null, writeOffDate, externalId);
     }
 
     private LoanTransaction(final Loan loan, final Office office, final 
LoanTransactionType type, final BigDecimal amount,
-            final LocalDate date, final String externalId, final LocalDateTime 
createdDate, final AppUser appUser) {
+            final LocalDate date, final String externalId) {
         this.loan = loan;
         this.typeOf = type.getValue();
         this.amount = amount;
-        this.dateOf = 
Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
+        this.dateOf = date;
         this.externalId = externalId;
         this.office = office;
-        this.submittedOnDate = DateUtils.getBusinessDate();
-        this.createdDate = 
Date.from(createdDate.atZone(DateUtils.getDateTimeZoneOfTenant()).toInstant());
-        this.appUser = appUser;
+        this.submittedOnDate = DateUtils.getBusinessLocalDate();
     }
 
     private LoanTransaction(final Loan loan, final Office office, final 
LoanTransactionType type, final PaymentDetail paymentDetail,
-            final BigDecimal amount, final LocalDate date, final String 
externalId, final LocalDateTime createdDate,
-            final AppUser appUser) {
+            final BigDecimal amount, final LocalDate date, final String 
externalId) {
         this.loan = loan;
         this.typeOf = type.getValue();
         this.paymentDetail = paymentDetail;
         this.amount = amount;
-        this.dateOf = 
Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
+        this.dateOf = date;
         this.externalId = externalId;
         this.office = office;
-        this.submittedOnDate = DateUtils.getBusinessDate();
-        this.createdDate = 
Date.from(createdDate.atZone(DateUtils.getDateTimeZoneOfTenant()).toInstant());
-        this.appUser = appUser;
+        this.submittedOnDate = DateUtils.getBusinessLocalDate();
     }
 
     public void reverse() {
@@ -504,10 +452,10 @@ public class LoanTransaction extends 
AbstractPersistableCustom {
     }
 
     public LocalDate getTransactionDate() {
-        return LocalDate.ofInstant(this.dateOf.toInstant(), 
DateUtils.getDateTimeZoneOfTenant());
+        return this.dateOf;
     }
 
-    public Date getDateOf() {
+    public LocalDate getDateOf() {
         return this.dateOf;
     }
 
@@ -778,14 +726,10 @@ public class LoanTransaction extends 
AbstractPersistableCustom {
         this.manuallyAdjustedOrReversed = true;
     }
 
-    private LocalDate getCreatedDate() {
-        return (this.createdDate == null) ? 
LocalDate.now(DateUtils.getDateTimeZoneOfTenant())
-                : LocalDate.ofInstant(this.createdDate.toInstant(), 
DateUtils.getDateTimeZoneOfTenant());
-    }
-
     public LocalDateTime getCreatedDateTime() {
-        return (this.createdDate == null) ? 
LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant())
-                : LocalDateTime.ofInstant(this.createdDate.toInstant(), 
DateUtils.getDateTimeZoneOfTenant());
+        return (this.getCreatedDate().isPresent()
+                ? LocalDateTime.ofInstant(this.getCreatedDate().get(), 
DateUtils.getDateTimeZoneOfTenant())
+                : DateUtils.getLocalDateTimeOfTenant());
     }
 
     public boolean isLastTransaction(final LoanTransaction loanTransaction) {
@@ -793,7 +737,7 @@ public class LoanTransaction extends 
AbstractPersistableCustom {
         if (loanTransaction != null) {
             isLatest = 
this.getTransactionDate().isBefore(loanTransaction.getTransactionDate())
                     || 
(this.getTransactionDate().isEqual(loanTransaction.getTransactionDate())
-                            && 
this.getCreatedDate().isBefore(loanTransaction.getCreatedDate()));
+                            && 
this.getCreatedDateTime().isBefore(loanTransaction.getCreatedDateTime()));
         }
         return isLatest;
     }
@@ -801,7 +745,7 @@ public class LoanTransaction extends 
AbstractPersistableCustom {
     public boolean isLatestTransaction(final LoanTransaction loanTransaction) {
         boolean isLatest = false;
         if (loanTransaction != null) {
-            isLatest = 
this.getCreatedDate().isBefore(loanTransaction.getCreatedDate());
+            isLatest = 
this.getCreatedDateTime().isBefore(loanTransaction.getCreatedDateTime());
         }
         return isLatest;
     }
@@ -845,10 +789,6 @@ public class LoanTransaction extends 
AbstractPersistableCustom {
         return isDisbursement() || isAccrual() || isRepaymentAtDisbursement();
     }
 
-    public void updateCreatedDate(Date createdDate) {
-        this.createdDate = createdDate;
-    }
-
     public boolean isAccrualTransaction() {
         return isAccrual();
     }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
index 177451de1..c72bb2b7f 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
@@ -881,14 +881,14 @@ public abstract class AbstractLoanScheduleGenerator 
implements LoanScheduleGener
                                         
currentPeriodParams.minusEarlyPaidAmount(unprocessed);
                                         
updateMapWithAmount(scheduleParams.getPrincipalPortionMap(), 
unprocessed.negated(), applicableDate);
                                         LoanTransaction loanTransaction = 
LoanTransaction.repayment(null, unprocessed, null,
-                                                transactionDate, null, 
DateUtils.getLocalDateTimeOfTenant(), null);
+                                                transactionDate, null);
                                         RecalculationDetail 
recalculationDetail = new RecalculationDetail(transactionDate, loanTransaction);
                                         
unprocessedTransactions.add(recalculationDetail);
                                         break;
                                     }
                                 }
-                                LoanTransaction loanTransaction = 
LoanTransaction.repayment(null, unprocessed, null, scheduledDueDate, null,
-                                        DateUtils.getLocalDateTimeOfTenant(), 
null);
+                                LoanTransaction loanTransaction = 
LoanTransaction.repayment(null, unprocessed, null, scheduledDueDate,
+                                        null);
                                 RecalculationDetail recalculationDetail = new 
RecalculationDetail(scheduledDueDate, loanTransaction);
                                 
unprocessedTransactions.add(recalculationDetail);
                                 checkForOutstanding = false;
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
index 8d7432d8e..afd727050 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
@@ -116,7 +116,6 @@ import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductVariableInsta
 import 
org.apache.fineract.portfolio.loanproduct.domain.RecalculationFrequencyType;
 import 
org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException;
 import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
-import org.apache.fineract.useradministration.domain.AppUser;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -878,8 +877,7 @@ public class LoanScheduleAssembler {
         }
         final LocalDate recalculateFrom = null;
         ScheduleGeneratorDTO scheduleGeneratorDTO = 
this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
-        AppUser currentUser = this.context.getAuthenticatedUserIfPresent();
-        loan.regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
+        loan.regenerateRepaymentSchedule(scheduleGeneratorDTO);
     }
 
     private List<LoanTermVariations> 
adjustExistingVariations(List<LoanTermVariations> variations, 
List<LoanTermVariations> newVariations,
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleWritePlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleWritePlatformServiceImpl.java
index 21a67de0f..97eb2119b 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleWritePlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleWritePlatformServiceImpl.java
@@ -34,7 +34,6 @@ import 
org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariations;
 import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
 import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
-import org.apache.fineract.useradministration.domain.AppUser;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -104,8 +103,7 @@ public class LoanScheduleWritePlatformServiceImpl 
implements LoanScheduleWritePl
         loan.getLoanTermVariations().clear();
         final LocalDate recalculateFrom = null;
         ScheduleGeneratorDTO scheduleGeneratorDTO = 
this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
-        AppUser currentUser = this.context.getAuthenticatedUserIfPresent();
-        loan.regenerateRepaymentSchedule(scheduleGeneratorDTO, currentUser);
+        loan.regenerateRepaymentSchedule(scheduleGeneratorDTO);
         
this.loanAccountDomainService.saveLoanWithDataIntegrityViolationChecks(loan);
         return new CommandProcessingResultBuilder() //
                 .withLoanId(loanId) //
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
index a9aad716e..5fae22ab5 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
@@ -487,7 +487,7 @@ public class LoanRescheduleRequestWritePlatformServiceImpl 
implements LoanResche
             final LoanScheduleDTO loanSchedule = 
loanScheduleGenerator.rescheduleNextInstallments(mathContext, 
loanApplicationTerms, loan,
                     loanApplicationTerms.getHolidayDetailDTO(), 
loanRepaymentScheduleTransactionProcessor, rescheduleFromDate);
 
-            loan.updateLoanSchedule(loanSchedule.getInstallments(), appUser);
+            loan.updateLoanSchedule(loanSchedule.getInstallments());
             loan.recalculateAllCharges();
             ChangedTransactionDetail changedTransactionDetail = 
loan.processTransactions();
 
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 634376741..ec91520d8 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
@@ -499,7 +499,7 @@ public class LoanAccrualWritePlatformServiceImpl implements 
LoanAccrualWritePlat
             final List<Long> existingReversedTransactionIds = new 
ArrayList<>();
             existingTransactionIds.addAll(loan.findExistingTransactionIds());
             
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
-            
loan.processIncomeTransactions(this.userRepository.fetchSystemUser());
+            loan.processIncomeTransactions();
             this.loanRepositoryWrapper.saveAndFlush(loan);
             postJournalEntries(loan, existingTransactionIds, 
existingReversedTransactionIds);
         }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
index 606077564..fa7dcc040 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
@@ -1050,7 +1050,7 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
                 final JsonQuery query = JsonQuery.from(command.json(), 
parsedQuery, this.fromJsonHelper);
 
                 final LoanScheduleModel loanSchedule = 
this.calculationPlatformService.calculateLoanSchedule(query, false);
-                existingLoanApplication.updateLoanSchedule(loanSchedule, 
currentUser);
+                existingLoanApplication.updateLoanSchedule(loanSchedule);
                 existingLoanApplication.recalculateAllCharges();
             }
 
@@ -1449,7 +1449,7 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
                     || changes.containsKey("expectedDisbursementDate")) {
                 LocalDate recalculateFrom = null;
                 ScheduleGeneratorDTO scheduleGeneratorDTO = 
this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
-                loan.regenerateRepaymentSchedule(scheduleGeneratorDTO, 
currentUser);
+                loan.regenerateRepaymentSchedule(scheduleGeneratorDTO);
             }
 
             if (loan.isTopup() && loan.getClientId() != null) {
@@ -1553,7 +1553,7 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
                     || 
changes.containsKey(LoanApiConstants.disbursementPrincipalParameterName)) {
                 LocalDate recalculateFrom = null;
                 ScheduleGeneratorDTO scheduleGeneratorDTO = 
this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
-                loan.regenerateRepaymentSchedule(scheduleGeneratorDTO, 
currentUser);
+                loan.regenerateRepaymentSchedule(scheduleGeneratorDTO);
             }
 
             loan.adjustNetDisbursalAmount(loan.getProposedPrincipal());
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
index 4169aedb1..9d6583838 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
@@ -503,8 +503,7 @@ public class LoanReadPlatformServiceImpl implements 
LoanReadPlatformService {
         final ApplicationCurrency applicationCurrency = 
this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
         final CurrencyData currencyData = applicationCurrency.toData();
 
-        final LoanTransaction waiveOfInterest = 
loan.deriveDefaultInterestWaiverTransaction(DateUtils.getLocalDateTimeOfTenant(),
-                currentUser);
+        final LoanTransaction waiveOfInterest = 
loan.deriveDefaultInterestWaiverTransaction();
 
         final LoanTransactionEnumData transactionType = 
LoanEnumerations.transactionType(LoanTransactionType.WAIVE_INTEREST);
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
index b8651992d..6b6b5373f 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
@@ -448,7 +448,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
                 
existingTransactionIds.addAll(loan.findExistingTransactionIds());
                 
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
                 LoanTransaction disbursementTransaction = 
LoanTransaction.disbursement(loan.getOffice(), amountToDisburse, paymentDetail,
-                        actualDisbursementDate, txnExternalId, 
DateUtils.getLocalDateTimeOfTenant(), currentUser);
+                        actualDisbursementDate, txnExternalId);
                 disbursementTransaction.updateLoan(loan);
                 loan.addLoanTransaction(disbursementTransaction);
             }
@@ -713,7 +713,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
                     
existingTransactionIds.addAll(loan.findExistingTransactionIds());
                     
existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
                     LoanTransaction disbursementTransaction = 
LoanTransaction.disbursement(loan.getOffice(), disburseAmount, paymentDetail,
-                            actualDisbursementDate, txnExternalId, 
DateUtils.getLocalDateTimeOfTenant(), currentUser);
+                            actualDisbursementDate, txnExternalId);
                     disbursementTransaction.updateLoan(loan);
                     loan.addLoanTransaction(disbursementTransaction);
                 }
@@ -826,8 +826,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         // Remove post dated checks if added.
         loan.removePostDatedChecks();
 
-        final Map<String, Object> changes = 
loan.undoDisbursal(scheduleGeneratorDTO, existingTransactionIds, 
existingReversedTransactionIds,
-                currentUser);
+        final Map<String, Object> changes = 
loan.undoDisbursal(scheduleGeneratorDTO, existingTransactionIds,
+                existingReversedTransactionIds);
 
         if (!changes.isEmpty()) {
             if (loan.isTopup() && loan.getClientId() != null) {
@@ -1050,7 +1050,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         final Money transactionAmountAsMoney = Money.of(loan.getCurrency(), 
transactionAmount);
         final PaymentDetail paymentDetail = 
this.paymentDetailWritePlatformService.createPaymentDetail(command, changes);
         LoanTransaction newTransactionDetail = 
LoanTransaction.repayment(loan.getOffice(), transactionAmountAsMoney, 
paymentDetail,
-                transactionDate, txnExternalId, 
DateUtils.getLocalDateTimeOfTenant(), currentUser);
+                transactionDate, txnExternalId);
         if (transactionToAdjust.isInterestWaiver()) {
             Money unrecognizedIncome = transactionAmountAsMoney.zero();
             Money interestComponent = transactionAmountAsMoney;
@@ -1062,7 +1062,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
                 }
             }
             newTransactionDetail = LoanTransaction.waiver(loan.getOffice(), 
loan, transactionAmountAsMoney, transactionDate,
-                    interestComponent, unrecognizedIncome, 
DateUtils.getLocalDateTimeOfTenant(), currentUser);
+                    interestComponent, unrecognizedIncome);
         }
 
         LocalDate recalculateFrom = null;
@@ -1076,7 +1076,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
 
         final ChangedTransactionDetail changedTransactionDetail = 
loan.adjustExistingTransaction(newTransactionDetail,
                 defaultLoanLifecycleStateMachine(), transactionToAdjust, 
existingTransactionIds, existingReversedTransactionIds,
-                scheduleGeneratorDTO, currentUser);
+                scheduleGeneratorDTO);
 
         if 
(newTransactionDetail.isGreaterThanZero(loan.getPrincpal().getCurrency())) {
             if (paymentDetail != null) {
@@ -1176,7 +1176,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
             }
         }
         final LoanTransaction waiveInterestTransaction = 
LoanTransaction.waiver(loan.getOffice(), loan, transactionAmountAsMoney,
-                transactionDate, interestComponent, unrecognizedIncome, 
DateUtils.getLocalDateTimeOfTenant(), currentUser);
+                transactionDate, interestComponent, unrecognizedIncome);
         businessEventNotifierService.notifyPreBusinessEvent(new 
LoanWaiveInterestBusinessEvent(waiveInterestTransaction));
         LocalDate recalculateFrom = null;
         if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
@@ -1185,8 +1185,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
 
         ScheduleGeneratorDTO scheduleGeneratorDTO = 
this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
         final ChangedTransactionDetail changedTransactionDetail = 
loan.waiveInterest(waiveInterestTransaction,
-                defaultLoanLifecycleStateMachine(), existingTransactionIds, 
existingReversedTransactionIds, scheduleGeneratorDTO,
-                currentUser);
+                defaultLoanLifecycleStateMachine(), existingTransactionIds, 
existingReversedTransactionIds, scheduleGeneratorDTO);
 
         this.loanTransactionRepository.saveAndFlush(waiveInterestTransaction);
 
@@ -1312,7 +1311,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
 
         ScheduleGeneratorDTO scheduleGeneratorDTO = 
this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
         ChangedTransactionDetail changedTransactionDetail = 
loan.close(command, defaultLoanLifecycleStateMachine(), changes,
-                existingTransactionIds, existingReversedTransactionIds, 
scheduleGeneratorDTO, currentUser);
+                existingTransactionIds, existingReversedTransactionIds, 
scheduleGeneratorDTO);
         final LoanTransaction possibleClosingTransaction = 
changedTransactionDetail.getNewTransactionMappings().remove(0L);
         if (possibleClosingTransaction != null) {
             
this.loanTransactionRepository.saveAndFlush(possibleClosingTransaction);
@@ -1561,11 +1560,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
     }
 
     public void runScheduleRecalculation(final Loan loan, final LocalDate 
recalculateFrom) {
-        AppUser currentUser = getAppUserIfPresent();
         if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
             ScheduleGeneratorDTO generatorDTO = 
this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
             ChangedTransactionDetail changedTransactionDetail = loan
-                    
.handleRegenerateRepaymentScheduleWithInterestRecalculation(generatorDTO, 
currentUser);
+                    
.handleRegenerateRepaymentScheduleWithInterestRecalculation(generatorDTO);
             saveLoanWithDataIntegrityViolationChecks(loan);
             if (changedTransactionDetail != null) {
                 for (final Map.Entry<Long, LoanTransaction> mapEntry : 
changedTransactionDetail.getNewTransactionMappings().entrySet()) {
@@ -1615,7 +1613,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
          * the loan product uses Upfront Accruals
          **/
         if (loan.status().isActive() && 
loan.isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) {
-            final LoanTransaction applyLoanChargeTransaction = 
loan.handleChargeAppliedTransaction(loanCharge, null, currentUser);
+            final LoanTransaction applyLoanChargeTransaction = 
loan.handleChargeAppliedTransaction(loanCharge, null);
             
this.loanTransactionRepository.saveAndFlush(applyLoanChargeTransaction);
         }
         boolean isAppliedOnBackDate = false;
@@ -1868,8 +1866,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         }
 
         final LoanTransaction waiveTransaction = 
loan.waiveLoanCharge(loanCharge, defaultLoanLifecycleStateMachine(), changes,
-                existingTransactionIds, existingReversedTransactionIds, 
loanInstallmentNumber, scheduleGeneratorDTO, accruedCharge,
-                currentUser);
+                existingTransactionIds, existingReversedTransactionIds, 
loanInstallmentNumber, scheduleGeneratorDTO, accruedCharge);
 
         this.loanTransactionRepository.saveAndFlush(waiveTransaction);
         saveLoanWithDataIntegrityViolationChecks(loan);
@@ -2113,7 +2110,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
     @Override
     public LoanTransaction initiateLoanTransfer(final Loan loan, final 
LocalDate transferDate) {
 
-        AppUser currentUser = getAppUserIfPresent();
         this.loanAssembler.setHelpers(loan);
         checkClientOrGroupActive(loan);
         validateTransactionsForTransfer(loan, transferDate);
@@ -2123,8 +2119,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         final List<Long> existingTransactionIds = new 
ArrayList<>(loan.findExistingTransactionIds());
         final List<Long> existingReversedTransactionIds = new 
ArrayList<>(loan.findExistingReversedTransactionIds());
 
-        final LoanTransaction newTransferTransaction = 
LoanTransaction.initiateTransfer(loan.getOffice(), loan, transferDate,
-                DateUtils.getLocalDateTimeOfTenant(), currentUser);
+        final LoanTransaction newTransferTransaction = 
LoanTransaction.initiateTransfer(loan.getOffice(), loan, transferDate);
         loan.addLoanTransaction(newTransferTransaction);
         loan.setLoanStatus(LoanStatus.TRANSFER_IN_PROGRESS.getValue());
 
@@ -2140,14 +2135,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
     @Override
     public LoanTransaction acceptLoanTransfer(final Loan loan, final LocalDate 
transferDate, final Office acceptedInOffice,
             final Staff loanOfficer) {
-        AppUser currentUser = getAppUserIfPresent();
         this.loanAssembler.setHelpers(loan);
         businessEventNotifierService.notifyPreBusinessEvent(new 
LoanAcceptTransferBusinessEvent(loan));
         final List<Long> existingTransactionIds = new 
ArrayList<>(loan.findExistingTransactionIds());
         final List<Long> existingReversedTransactionIds = new 
ArrayList<>(loan.findExistingReversedTransactionIds());
 
-        final LoanTransaction newTransferAcceptanceTransaction = 
LoanTransaction.approveTransfer(acceptedInOffice, loan, transferDate,
-                DateUtils.getLocalDateTimeOfTenant(), currentUser);
+        final LoanTransaction newTransferAcceptanceTransaction = 
LoanTransaction.approveTransfer(acceptedInOffice, loan, transferDate);
         loan.addLoanTransaction(newTransferAcceptanceTransaction);
         if (loan.getTotalOverpaid() != null) {
             loan.setLoanStatus(LoanStatus.OVERPAID.getValue());
@@ -2170,15 +2163,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
     @Transactional
     @Override
     public LoanTransaction withdrawLoanTransfer(final Loan loan, final 
LocalDate transferDate) {
-        AppUser currentUser = getAppUserIfPresent();
         this.loanAssembler.setHelpers(loan);
         businessEventNotifierService.notifyPreBusinessEvent(new 
LoanWithdrawTransferBusinessEvent(loan));
 
         final List<Long> existingTransactionIds = new 
ArrayList<>(loan.findExistingTransactionIds());
         final List<Long> existingReversedTransactionIds = new 
ArrayList<>(loan.findExistingReversedTransactionIds());
 
-        final LoanTransaction newTransferAcceptanceTransaction = 
LoanTransaction.withdrawTransfer(loan.getOffice(), loan, transferDate,
-                DateUtils.getLocalDateTimeOfTenant(), currentUser);
+        final LoanTransaction newTransferAcceptanceTransaction = 
LoanTransaction.withdrawTransfer(loan.getOffice(), loan, transferDate);
         loan.addLoanTransaction(newTransferAcceptanceTransaction);
         loan.setLoanStatus(LoanStatus.ACTIVE.getValue());
 
@@ -2375,7 +2366,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
                     ScheduleGeneratorDTO scheduleGeneratorDTO = 
loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
                     loan.setHelpers(null, this.loanSummaryWrapper, 
this.transactionProcessingStrategy);
                     
loan.recalculateScheduleFromLastTransaction(scheduleGeneratorDTO, 
existingTransactionIds,
-                            existingReversedTransactionIds, currentUser);
+                            existingReversedTransactionIds);
                     createAndSaveLoanScheduleArchive(loan, 
scheduleGeneratorDTO);
                 } else if (reschedulebasedOnMeetingDates != null && 
reschedulebasedOnMeetingDates) {
                     
loan.updateLoanRepaymentScheduleDates(calendar.getStartDateLocalDate(), 
calendar.getRecurrence(), isHolidayEnabled,
@@ -2786,7 +2777,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         ScheduleGeneratorDTO scheduleGeneratorDTO = 
this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
 
         ChangedTransactionDetail changedTransactionDetail = 
loan.undoWrittenOff(existingTransactionIds, existingReversedTransactionIds,
-                scheduleGeneratorDTO, currentUser);
+                scheduleGeneratorDTO);
         if (changedTransactionDetail != null) {
             for (final Map.Entry<Long, LoanTransaction> mapEntry : 
changedTransactionDetail.getNewTransactionMappings().entrySet()) {
                 this.loanTransactionRepository.save(mapEntry.getValue());
@@ -2914,7 +2905,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         if (command.entityId() != null) {
 
             changedTransactionDetail = 
loan.updateDisbursementDateAndAmountForTranche(loanDisbursementDetails, 
command, changes,
-                    scheduleGeneratorDTO, currentUser);
+                    scheduleGeneratorDTO);
         } else {
             // BigDecimal setAmount = loan.getApprovedPrincipal();
             Collection<LoanDisbursementDetails> loanDisburseDetails = 
loan.getDisbursementDetails();
@@ -2928,9 +2919,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
             loan.repaymentScheduleDetail().setPrincipal(setAmount);
 
             if 
(loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
-                
loan.regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, 
currentUser);
+                
loan.regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
             } else {
-                loan.regenerateRepaymentSchedule(scheduleGeneratorDTO, 
currentUser);
+                loan.regenerateRepaymentSchedule(scheduleGeneratorDTO);
                 loan.processPostDisbursementTransactions();
             }
         }
@@ -3049,7 +3040,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
     public void recalculateInterest(final long loanId) {
         Loan loan = this.loanAssembler.assembleFrom(loanId);
         LocalDate recalculateFrom = loan.fetchInterestRecalculateFromDate();
-        AppUser currentUser = getAppUserIfPresent();
         businessEventNotifierService.notifyPreBusinessEvent(new 
LoanInterestRecalculationBusinessEvent(loan));
         final List<Long> existingTransactionIds = new ArrayList<>();
         final List<Long> existingReversedTransactionIds = new ArrayList<>();
@@ -3057,7 +3047,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         ScheduleGeneratorDTO generatorDTO = 
this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
 
         ChangedTransactionDetail changedTransactionDetail = 
loan.recalculateScheduleFromLastTransaction(generatorDTO,
-                existingTransactionIds, existingReversedTransactionIds, 
currentUser);
+                existingTransactionIds, existingReversedTransactionIds);
 
         saveLoanWithDataIntegrityViolationChecks(loan);
 
@@ -3101,7 +3091,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         AppUser currentUser = getAppUserIfPresent();
         final LocalDate actualDisbursementDate = 
command.localDateValueOfParameterNamed("actualDisbursementDate");
         BigDecimal emiAmount = 
command.bigDecimalValueOfParameterNamed(LoanApiConstants.emiAmountParameterName);
-        loan.regenerateScheduleOnDisbursement(scheduleGeneratorDTO, 
recalculateSchedule, actualDisbursementDate, emiAmount, currentUser,
+        loan.regenerateScheduleOnDisbursement(scheduleGeneratorDTO, 
recalculateSchedule, actualDisbursementDate, emiAmount,
                 nextPossibleRepaymentDate, rescheduledRepaymentDate);
     }
 
@@ -3213,7 +3203,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
     @Override
     @Transactional
     public CommandProcessingResult undoLastLoanDisbursal(Long loanId, 
JsonCommand command) {
-        final AppUser currentUser = getAppUserIfPresent();
 
         final Loan loan = this.loanAssembler.assembleFrom(loanId);
         final LocalDate recalculateFromDate = loan.getLastRepaymentDate();
@@ -3229,7 +3218,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         ScheduleGeneratorDTO scheduleGeneratorDTO = 
this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFromDate);
 
         final Map<String, Object> changes = 
loan.undoLastDisbursal(scheduleGeneratorDTO, existingTransactionIds,
-                existingReversedTransactionIds, currentUser, loan);
+                existingReversedTransactionIds, loan);
         if (!changes.isEmpty()) {
             saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
             String noteText = null;
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 0294b2a76..e4954526c 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
@@ -38,4 +38,5 @@
     <include file="parts/0016_changed_unique_constraint_of_ref_no.xml" 
relativeToChangelogFile="true"/>
     <include file="parts/0017_fix_stretchy_reports.xml" 
relativeToChangelogFile="true"/>
     <include file="parts/0018_pentaho_reports_to_table.xml" 
relativeToChangelogFile="true"/>
+    <include file="parts/0019_refactor_loan_transaction.xml" 
relativeToChangelogFile="true"/>
 </databaseChangeLog>
diff --git 
a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0019_refactor_loan_transaction.xml
 
b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0019_refactor_loan_transaction.xml
new file mode 100644
index 000000000..0d6bb0992
--- /dev/null
+++ 
b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0019_refactor_loan_transaction.xml
@@ -0,0 +1,59 @@
+<?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">
+        <addColumn tableName="m_loan_transaction">
+            <column name="createdby_id" type="BIGINT" 
valueComputed="appuser_id"/>
+            <column name="lastmodifiedby_id" type="BIGINT" 
valueComputed="appuser_id"/>
+            <column name="lastmodified_date" type="DATETIME" 
valueComputed="created_date"/>
+        </addColumn>
+    </changeSet>
+    <changeSet id="2" author="fineract">
+        <dropColumn tableName="m_loan_transaction">
+            <column name="appuser_id"/>
+        </dropColumn>
+    </changeSet>
+    <changeSet author="fineract" id="3" context="postgresql">
+        <update tableName="stretchy_report">
+            <column name="report_sql" value="SELECT mc.id AS id, mc.firstname 
AS firstName, mc.middlename AS middleName, mc.lastname AS lastName, 
mc.display_name AS fullName, mc.mobile_no AS mobileNo, ml.principal_amount AS 
loanAmount, (COALESCE(ml.principal_outstanding_derived, 0) + 
COALESCE(ml.interest_outstanding_derived, 0) + 
COALESCE(ml.fee_charges_outstanding_derived, 0) + 
COALESCE(ml.penalty_charges_outstanding_derived, 0)) AS loanOutstanding, 
ounder.id AS officeNumber, ml.account [...]
+            <where>id='174' AND report_name='Loan payments received (Active 
Loans)'</where>
+        </update>
+        <update tableName="stretchy_report">
+            <column name="report_sql" value="SELECT ml.id AS loanId, mc.id AS 
id, mc.firstname AS firstName, mc.middlename AS middleName, mc.lastname AS 
lastName, mc.display_name AS fullName, mc.mobile_no AS mobileNo, 
ml.principal_amount AS loanAmount, (COALESCE(ml.principal_outstanding_derived, 
0) + COALESCE(ml.interest_outstanding_derived, 0) + 
COALESCE(ml.fee_charges_outstanding_derived, 0) + 
COALESCE(ml.penalty_charges_outstanding_derived, 0)) AS loanOutstanding, 
ounder.id AS officeN [...]
+            <where>id='175' AND report_name='Loan payments received (Overdue 
Loans)'</where>
+        </update>
+    </changeSet>
+    <changeSet author="fineract" id="4" context="mysql">
+        <update tableName="stretchy_report">
+            <column name="report_sql"
+                    value="SELECT &#13;&#10;mc.id AS &quot;id&quot;, 
&#13;&#10;mc.firstname AS &quot;firstName&quot;,&#13;&#10;mc.middlename AS 
&quot;middleName&quot;,&#13;&#10;mc.lastname AS 
&quot;lastName&quot;,&#13;&#10;mc.display_name AS 
&quot;fullName&quot;,&#13;&#10;mc.mobile_no AS &quot;mobileNo&quot;, 
&#13;&#10;ml.principal_amount AS &quot;loanAmount&quot;, 
&#13;&#10;(IFNULL(ml.principal_outstanding_derived, 0) + 
IFNULL(ml.interest_outstanding_derived, 0) + IFNULL(ml.fee_charges_ [...]
+            <where>id='174' AND report_name='Loan payments received (Active 
Loans)'</where>
+        </update>
+        <update tableName="stretchy_report">
+            <column name="report_sql"
+                    value="SELECT &#13;&#10;ml.id AS &quot;loanId&quot;, 
&#13;&#10;mc.id AS &quot;id&quot;, &#13;&#10;mc.firstname AS 
&quot;firstName&quot;,&#13;&#10;mc.middlename AS 
&quot;middleName&quot;,&#13;&#10;mc.lastname AS 
&quot;lastName&quot;,&#13;&#10;mc.display_name AS 
&quot;fullName&quot;,&#13;&#10;mc.mobile_no AS &quot;mobileNo&quot;, 
&#13;&#10;ml.principal_amount AS &quot;loanAmount&quot;, 
&#13;&#10;(IFNULL(ml.principal_outstanding_derived, 0) + 
IFNULL(ml.interest_outstandi [...]
+            <where>id='175' AND report_name='Loan payments received (Overdue 
Loans)'</where>
+        </update>
+    </changeSet>
+</databaseChangeLog>

Reply via email to