adamsaghy commented on code in PR #2953:
URL: https://github.com/apache/fineract/pull/2953#discussion_r1102679859


##########
fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java:
##########
@@ -104,10 +105,208 @@ else if 
(loanTransactionDTO.getTransactionType().isChargeback()) {
             else if 
(loanTransactionDTO.getTransactionType().isChargeAdjustment()) {
                 createJournalEntriesForChargeAdjustment(loanDTO, 
loanTransactionDTO, office);
             }
+            // Logic for Charge-Off
+            else if (loanTransactionDTO.getTransactionType().isChargeoff()) {
+                createJournalEntriesForChargeOff(loanDTO, loanTransactionDTO, 
office);
+            }
+        }
+    }
+
+    private void createJournalEntriesForChargeOff(LoanDTO loanDTO, 
LoanTransactionDTO loanTransactionDTO, Office office) {
+        // loan properties
+        final Long loanProductId = loanDTO.getLoanProductId();
+        final Long loanId = loanDTO.getLoanId();
+        final String currencyCode = loanDTO.getCurrencyCode();
+        final boolean isMarkedFraud = loanDTO.isMarkedAsFraud();
+
+        // transaction properties
+        final String transactionId = loanTransactionDTO.getTransactionId();
+        final LocalDate transactionDate = 
loanTransactionDTO.getTransactionDate();
+        final BigDecimal principalAmount = loanTransactionDTO.getPrincipal();
+        final BigDecimal interestAmount = loanTransactionDTO.getInterest();
+        final BigDecimal feesAmount = loanTransactionDTO.getFees();
+        final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
+        final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
+        final boolean isReversal = loanTransactionDTO.isReversed();
+
+        Map<GLAccount, BigDecimal> accountMapForCredit = new HashMap<>();
+
+        Map<Integer, BigDecimal> accountMapForDebit = new HashMap<>();
+
+        // principal payment
+        if (principalAmount != null && 
principalAmount.compareTo(BigDecimal.ZERO) > 0) {
+            if (isMarkedFraud) {
+                populateCreditDebitMaps(loanProductId, principalAmount, 
paymentTypeId, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
+                        
AccrualAccountsForLoan.CHARGE_OFF_FRAUD_EXPENSE.getValue(), 
accountMapForCredit, accountMapForDebit);
+            } else {
+                populateCreditDebitMaps(loanProductId, principalAmount, 
paymentTypeId, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
+                        AccrualAccountsForLoan.CHARGE_OFF_EXPENSE.getValue(), 
accountMapForCredit, accountMapForDebit);
+            }
+        }
+
+        // interest payment
+        if (interestAmount != null && 
interestAmount.compareTo(BigDecimal.ZERO) > 0) {
+
+            populateCreditDebitMaps(loanProductId, interestAmount, 
paymentTypeId, AccrualAccountsForLoan.INTEREST_RECEIVABLE.getValue(),
+                    
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_INTEREST.getValue(), 
accountMapForCredit, accountMapForDebit);
+        }
+
+        // handle fees payment
+        if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
+            populateCreditDebitMaps(loanProductId, feesAmount, paymentTypeId, 
AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(),
+                    
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_FEES.getValue(), 
accountMapForCredit, accountMapForDebit);
+        }
+
+        // handle penalty payment
+        if (penaltiesAmount != null && 
penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
+            populateCreditDebitMaps(loanProductId, penaltiesAmount, 
paymentTypeId, AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(),
+                    
AccrualAccountsForLoan.INCOME_FROM_CHARGE_OFF_PENALTY.getValue(), 
accountMapForCredit, accountMapForDebit);
+        }
+
+        // create credit entries
+        for (Map.Entry<GLAccount, BigDecimal> creditEntry : 
accountMapForCredit.entrySet()) {
+            this.helper.createCreditJournalEntryOrReversalForLoan(office, 
currencyCode, loanId, transactionId, transactionDate,
+                    creditEntry.getValue(), isReversal, creditEntry.getKey());
+        }
+
+        // create debit entries
+        for (Map.Entry<Integer, BigDecimal> debitEntry : 
accountMapForDebit.entrySet()) {
+            this.helper.createDebitJournalEntryOrReversalForLoan(office, 
currencyCode, debitEntry.getKey().intValue(), loanProductId,
+                    paymentTypeId, loanId, transactionId, transactionDate, 
debitEntry.getValue(), isReversal);
+        }
+
+    }
+
+    private void populateCreditDebitMaps(Long loanProductId, BigDecimal 
transactionPartAmount, Long paymentTypeId,
+            Integer creditAccountType, Integer debitAccountType, 
Map<GLAccount, BigDecimal> accountMapForCredit,
+            Map<Integer, BigDecimal> accountMapForDebit) {
+        GLAccount accountCredit = 
this.helper.getLinkedGLAccountForLoanProduct(loanProductId, creditAccountType, 
paymentTypeId);
+        if (accountMapForCredit.containsKey(accountCredit)) {
+            BigDecimal amount = 
accountMapForCredit.get(accountCredit).add(transactionPartAmount);
+            accountMapForCredit.put(accountCredit, amount);
+        } else {
+            accountMapForCredit.put(accountCredit, transactionPartAmount);
+        }
+        Integer accountDebit = debitAccountType;
+        if (accountMapForDebit.containsKey(accountDebit)) {
+            BigDecimal amount = 
accountMapForDebit.get(accountDebit).add(transactionPartAmount);
+            accountMapForDebit.put(accountDebit, amount);
+        } else {
+            accountMapForDebit.put(accountDebit, transactionPartAmount);
         }
     }
 
     private void createJournalEntriesForChargeAdjustment(LoanDTO loanDTO, 
LoanTransactionDTO loanTransactionDTO, Office office) {
+        final boolean isMarkedAsChargeOff = loanDTO.isMarkedAsChargeOff();
+        if (isMarkedAsChargeOff) {
+            createJournalEntriesForChargeOffLoanChargeAdjustment(loanDTO, 
loanTransactionDTO, office);
+        } else {
+            createJournalEntriesForLoanChargeAdjustment(loanDTO, 
loanTransactionDTO, office);
+        }
+    }
+
+    private void createJournalEntriesForChargeOffLoanChargeAdjustment(LoanDTO 
loanDTO, LoanTransactionDTO loanTransactionDTO,
+            Office office) {
+        // loan properties
+        final Long loanProductId = loanDTO.getLoanProductId();
+        final Long loanId = loanDTO.getLoanId();
+        final String currencyCode = loanDTO.getCurrencyCode();
+
+        // transaction properties
+        final String transactionId = loanTransactionDTO.getTransactionId();
+        final LocalDate transactionDate = 
loanTransactionDTO.getTransactionDate();
+        final BigDecimal principalAmount = loanTransactionDTO.getPrincipal();
+        final BigDecimal interestAmount = loanTransactionDTO.getInterest();
+        final BigDecimal feesAmount = loanTransactionDTO.getFees();
+        final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
+        final BigDecimal overPaymentAmount = 
loanTransactionDTO.getOverPayment();
+        final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
+        final boolean isReversal = loanTransactionDTO.isReversed();
+
+        BigDecimal totalDebitAmount = new BigDecimal(0);
+
+        Map<GLAccount, BigDecimal> accountMap = new HashMap<>();

Review Comment:
   Please use LinkedHashmap for keeping a consistent ordering



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to