Merge pull request #585 from vishwasbabu/develop

track currency with accounting
This commit is contained in:
Vishwas Babu A J
2013-09-17 08:47:08 -07:00
19 changed files with 328 additions and 161 deletions
+8
View File
@@ -17769,6 +17769,12 @@ No Request Body:
cost center) at which the financial activity
occured</td>
</tr>
<tr class=alt>
<td>currencyCode</td>
</tr>
<tr>
<td class=fielddesc>A three letter ISO code of currency.</td>
</tr>
<tr class=alt>
<td>glAccountId</td>
</tr>
@@ -18112,6 +18118,7 @@ Request Body:
"transactionDate": "06 December 2012",
"comments": "Gifts for staff",
"locale": "en" ,
"currencyCode": "USD",
"dateFormat": "dd MMMM yyyy",
"credits":[{"glAccountId":1,
"amount":5000},
@@ -18144,6 +18151,7 @@ Request Body:
"officeId": "1",
"transactionDate": "23 May 2013",
"referenceNumber": "547",
"currencyCode": "USD",
"comments": "asdf",
"accountingRule": "2",
"amount": "547"
@@ -0,0 +1,29 @@
/**Add currency code**/
ALTER TABLE `acc_gl_journal_entry`
ADD COLUMN `currency_code` VARCHAR(3) NULL DEFAULT NULL AFTER `reversal_id`;
/**Update currency codes for loans**/
UPDATE acc_gl_journal_entry journal_entry SET currency_code = (
SELECT m_loan.currency_code
FROM m_loan, m_loan_transaction
WHERE m_loan.id = m_loan_transaction.loan_id AND m_loan_transaction.id=journal_entry.transaction_id)
WHERE journal_entry.entity_type_enum=1;
/**Update currency codes for savings**/
UPDATE acc_gl_journal_entry journal_entry SET currency_code = (
SELECT m_savings_account.currency_code
FROM m_savings_account, m_savings_account_transaction
WHERE m_savings_account.id = m_savings_account_transaction.savings_account_id AND m_savings_account_transaction.id=journal_entry.transaction_id)
WHERE journal_entry.entity_type_enum=2;
/**Update currency codes for manual journal entries***/
update acc_gl_journal_entry set currency_code = (select code from m_organisation_currency limit 1)
where acc_gl_journal_entry.currency_code is NULL;
/**Make currency code not null**/
ALTER TABLE `acc_gl_journal_entry`
ALTER `currency_code` DROP DEFAULT;
ALTER TABLE `acc_gl_journal_entry`
CHANGE COLUMN `currency_code` `currency_code` VARCHAR(3) NOT NULL AFTER `reversal_id`;
@@ -13,7 +13,8 @@ import java.util.Set;
***/
public enum JournalEntryJsonInputParams {
OFFICE_ID("officeId"), TRANSACTION_DATE("transactionDate"), COMMENTS("comments"), CREDITS("credits"), DEBITS("debits"), LOCALE("locale"), DATE_FORMAT(
"dateFormat"), REFERENCE_NUMBER("referenceNumber"), USE_ACCOUNTING_RULE("useAccountingRule"), ACCOUNTING_RULE("accountingRule"), AMOUNT("amount");
"dateFormat"), REFERENCE_NUMBER("referenceNumber"), USE_ACCOUNTING_RULE("useAccountingRule"), ACCOUNTING_RULE("accountingRule"), AMOUNT(
"amount"), CURRENCY_CODE("currencyCode");
private final String value;
@@ -10,6 +10,7 @@ import java.util.ArrayList;
import java.util.List;
import org.joda.time.LocalDate;
import org.mifosplatform.accounting.journalentry.api.JournalEntryJsonInputParams;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
@@ -21,6 +22,7 @@ public class JournalEntryCommand {
private final Long officeId;
private final LocalDate transactionDate;
private final String currencyCode;
private final String comments;
private final String referenceNumber;
private final Long accountingRuleId;
@@ -29,10 +31,11 @@ public class JournalEntryCommand {
private final SingleDebitOrCreditEntryCommand[] credits;
private final SingleDebitOrCreditEntryCommand[] debits;
public JournalEntryCommand(final Long officeId, final LocalDate transactionDate, final String comments,
public JournalEntryCommand(final Long officeId, final String currencyCode, final LocalDate transactionDate, final String comments,
final SingleDebitOrCreditEntryCommand[] credits, final SingleDebitOrCreditEntryCommand[] debits, final String referenceNumber,
final Long accountingRuleId, final BigDecimal amount) {
this.officeId = officeId;
this.currencyCode = currencyCode;
this.transactionDate = transactionDate;
this.comments = comments;
this.credits = credits;
@@ -52,6 +55,8 @@ public class JournalEntryCommand {
baseDataValidator.reset().parameter("officeId").value(this.officeId).notNull().integerGreaterThanZero();
baseDataValidator.reset().parameter(JournalEntryJsonInputParams.CURRENCY_CODE.getValue()).value(this.currencyCode).notBlank();
baseDataValidator.reset().parameter("comments").value(this.comments).ignoreIfNull().notExceedingLengthOf(500);
baseDataValidator.reset().parameter("referenceNumber").value(this.referenceNumber).ignoreIfNull().notExceedingLengthOf(100);
@@ -12,18 +12,22 @@ public class LoanDTO {
private Long loanId;
private Long loanProductId;
private Long officeId;
private String currencyCode;
private boolean cashBasedAccountingEnabled;
private boolean accrualBasedAccountingEnabled;
private List<LoanTransactionDTO> newLoanTransactions;
public LoanDTO(final Long loanId, final Long loanProductId, final Long officeId, final boolean cashBasedAccountingEnabled,
final boolean accrualBasedAccountingEnabled, final List<LoanTransactionDTO> newLoanTransactions) {
public LoanDTO(final Long loanId, final Long loanProductId, final Long officeId, final String currencyCode,
final boolean cashBasedAccountingEnabled, final boolean accrualBasedAccountingEnabled,
final List<LoanTransactionDTO> newLoanTransactions) {
this.loanId = loanId;
this.loanProductId = loanProductId;
this.officeId = officeId;
this.cashBasedAccountingEnabled = cashBasedAccountingEnabled;
this.accrualBasedAccountingEnabled = accrualBasedAccountingEnabled;
this.newLoanTransactions = newLoanTransactions;
this.currencyCode = currencyCode;
}
public Long getLoanId() {
@@ -74,4 +78,12 @@ public class LoanDTO {
this.newLoanTransactions = newLoanTransactions;
}
public String getCurrencyCode() {
return this.currencyCode;
}
public void setCurrencyCode(String currencyCode) {
this.currencyCode = currencyCode;
}
}
@@ -12,18 +12,21 @@ public class SavingsDTO {
private Long savingsId;
private Long savingsProductId;
private Long officeId;
private String currencyCode;
private boolean cashBasedAccountingEnabled;
private boolean accrualBasedAccountingEnabled;
private List<SavingsTransactionDTO> newSavingsTransactions;
public SavingsDTO(final Long savingsId, final Long savingsProductId, final Long officeId, final boolean cashBasedAccountingEnabled,
final boolean accrualBasedAccountingEnabled, final List<SavingsTransactionDTO> newSavingsTransactions) {
public SavingsDTO(final Long savingsId, final Long savingsProductId, final Long officeId, final String currencyCode,
final boolean cashBasedAccountingEnabled, final boolean accrualBasedAccountingEnabled,
final List<SavingsTransactionDTO> newSavingsTransactions) {
this.savingsId = savingsId;
this.savingsProductId = savingsProductId;
this.officeId = officeId;
this.cashBasedAccountingEnabled = cashBasedAccountingEnabled;
this.accrualBasedAccountingEnabled = accrualBasedAccountingEnabled;
this.newSavingsTransactions = newSavingsTransactions;
this.currencyCode = currencyCode;
}
public Long getSavingsId() {
@@ -74,4 +77,12 @@ public class SavingsDTO {
this.newSavingsTransactions = newSavingsTransactions;
}
public String getCurrencyCode() {
return this.currencyCode;
}
public void setCurrencyCode(String currencyCode) {
this.currencyCode = currencyCode;
}
}
@@ -35,6 +35,9 @@ public class JournalEntry extends AbstractAuditableCustom<AppUser, Long> {
@JoinColumn(name = "account_id", nullable = false)
private GLAccount glAccount;
@Column(name = "currency_code", length = 3, nullable = false)
private String currencyCode;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "reversal_id")
private JournalEntry reversalJournalEntry;
@@ -70,20 +73,20 @@ public class JournalEntry extends AbstractAuditableCustom<AppUser, Long> {
@Column(name = "ref_num")
private String referenceNumber;
public static JournalEntry createNew(final Office office, final GLAccount glAccount, final String transactionId,
final boolean manualEntry, final Date transactionDate, final JournalEntryType journalEntryType, final BigDecimal amount,
final String description, final Integer entityType, final Long entityId, final String referenceNumber) {
return new JournalEntry(office, glAccount, transactionId, manualEntry, transactionDate, journalEntryType.getValue(), amount,
description, entityType, entityId, referenceNumber);
public static JournalEntry createNew(final Office office, final GLAccount glAccount, final String currencyCode,
final String transactionId, final boolean manualEntry, final Date transactionDate, final JournalEntryType journalEntryType,
final BigDecimal amount, final String description, final Integer entityType, final Long entityId, final String referenceNumber) {
return new JournalEntry(office, glAccount, currencyCode, transactionId, manualEntry, transactionDate, journalEntryType.getValue(),
amount, description, entityType, entityId, referenceNumber);
}
protected JournalEntry() {
//
}
public JournalEntry(final Office office, final GLAccount glAccount, final String transactionId, final boolean manualEntry,
final Date transactionDate, final Integer type, final BigDecimal amount, final String description, final Integer entityType,
final Long entityId, final String referenceNumber) {
public JournalEntry(final Office office, final GLAccount glAccount, final String currencyCode, final String transactionId,
final boolean manualEntry, final Date transactionDate, final Integer type, final BigDecimal amount, final String description,
final Integer entityType, final Long entityId, final String referenceNumber) {
this.office = office;
this.glAccount = glAccount;
this.reversalJournalEntry = null;
@@ -97,6 +100,7 @@ public class JournalEntry extends AbstractAuditableCustom<AppUser, Long> {
this.entityType = entityType;
this.entityId = entityId;
this.referenceNumber = referenceNumber;
this.currencyCode = currencyCode;
}
@@ -136,4 +140,8 @@ public class JournalEntry extends AbstractAuditableCustom<AppUser, Long> {
return this.referenceNumber;
}
public String getCurrencyCode() {
return this.currencyCode;
}
}
@@ -54,6 +54,8 @@ public final class JournalEntryCommandFromApiJsonDeserializer extends AbstractFr
final JsonElement element = this.fromApiJsonHelper.parse(json);
final Long officeId = this.fromApiJsonHelper.extractLongNamed(JournalEntryJsonInputParams.OFFICE_ID.getValue(), element);
final String currencyCode = this.fromApiJsonHelper
.extractStringNamed(JournalEntryJsonInputParams.CURRENCY_CODE.getValue(), element);
final String comments = this.fromApiJsonHelper.extractStringNamed(JournalEntryJsonInputParams.COMMENTS.getValue(), element);
final LocalDate transactionDate = this.fromApiJsonHelper.extractLocalDateNamed(
JournalEntryJsonInputParams.TRANSACTION_DATE.getValue(), element);
@@ -64,7 +66,8 @@ public final class JournalEntryCommandFromApiJsonDeserializer extends AbstractFr
final JsonObject topLevelJsonElement = element.getAsJsonObject();
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
final BigDecimal amount = this.fromApiJsonHelper.extractBigDecimalNamed(JournalEntryJsonInputParams.AMOUNT.getValue(), element, locale);
final BigDecimal amount = this.fromApiJsonHelper.extractBigDecimalNamed(JournalEntryJsonInputParams.AMOUNT.getValue(), element,
locale);
SingleDebitOrCreditEntryCommand[] credits = null;
SingleDebitOrCreditEntryCommand[] debits = null;
@@ -78,7 +81,8 @@ public final class JournalEntryCommandFromApiJsonDeserializer extends AbstractFr
debits = populateCreditsOrDebitsArray(topLevelJsonElement, locale, debits, JournalEntryJsonInputParams.DEBITS.getValue());
}
}
return new JournalEntryCommand(officeId, transactionDate, comments, credits, debits, referenceNumber, accountingRuleId, amount);
return new JournalEntryCommand(officeId, currencyCode, transactionDate, comments, credits, debits, referenceNumber,
accountingRuleId, amount);
}
/**
@@ -33,6 +33,7 @@ import org.mifosplatform.accounting.producttoaccountmapping.domain.PortfolioProd
import org.mifosplatform.accounting.producttoaccountmapping.domain.ProductToGLAccountMapping;
import org.mifosplatform.accounting.producttoaccountmapping.domain.ProductToGLAccountMappingRepository;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.office.domain.OfficeRepository;
import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionEnumData;
@@ -63,6 +64,8 @@ public class AccountingProcessorHelper {
final Long loanId = (Long) accountingBridgeData.get("loanId");
final Long loanProductId = (Long) accountingBridgeData.get("loanProductId");
final Long officeId = (Long) accountingBridgeData.get("officeId");
final CurrencyData currencyData = (CurrencyData) accountingBridgeData.get("currency");
final List<LoanTransactionDTO> newLoanTransactions = new ArrayList<LoanTransactionDTO>();
@SuppressWarnings("unchecked")
@@ -108,7 +111,8 @@ public class AccountingProcessorHelper {
}
return new LoanDTO(loanId, loanProductId, officeId, cashBasedAccountingEnabled, accrualBasedAccountingEnabled, newLoanTransactions);
return new LoanDTO(loanId, loanProductId, officeId, currencyData.code(), cashBasedAccountingEnabled, accrualBasedAccountingEnabled,
newLoanTransactions);
}
public SavingsDTO populateSavingsDtoFromMap(final Map<String, Object> accountingBridgeData, final boolean cashBasedAccountingEnabled,
@@ -116,6 +120,7 @@ public class AccountingProcessorHelper {
final Long loanId = (Long) accountingBridgeData.get("savingsId");
final Long loanProductId = (Long) accountingBridgeData.get("savingsProductId");
final Long officeId = (Long) accountingBridgeData.get("officeId");
final CurrencyData currencyData = (CurrencyData) accountingBridgeData.get("currency");
final List<SavingsTransactionDTO> newSavingsTransactions = new ArrayList<SavingsTransactionDTO>();
@SuppressWarnings("unchecked")
@@ -137,8 +142,8 @@ public class AccountingProcessorHelper {
}
return new SavingsDTO(loanId, loanProductId, officeId, cashBasedAccountingEnabled, accrualBasedAccountingEnabled,
newSavingsTransactions);
return new SavingsDTO(loanId, loanProductId, officeId, currencyData.code(), cashBasedAccountingEnabled,
accrualBasedAccountingEnabled, newSavingsTransactions);
}
/**
@@ -161,7 +166,7 @@ public class AccountingProcessorHelper {
* @param amount
* @param isReversal
*/
public void createAccrualBasedJournalEntriesAndReversalsForLoan(final Office office,
public void createAccrualBasedJournalEntriesAndReversalsForLoan(final Office office, final String currencyCode,
final ACCRUAL_ACCOUNTS_FOR_LOAN accountTypeToBeDebited, final ACCRUAL_ACCOUNTS_FOR_LOAN accountTypeToBeCredited,
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate,
final BigDecimal amount, final Boolean isReversal) {
@@ -172,8 +177,8 @@ public class AccountingProcessorHelper {
accountTypeToDebitId = accountTypeToBeCredited.getValue();
accountTypeToCreditId = accountTypeToBeDebited.getValue();
}
createJournalEntriesForLoan(office, accountTypeToDebitId, accountTypeToCreditId, loanProductId, paymentTypeId, loanId,
transactionId, transactionDate, amount);
createJournalEntriesForLoan(office, currencyCode, accountTypeToDebitId, accountTypeToCreditId, loanProductId, paymentTypeId,
loanId, transactionId, transactionDate, amount);
}
/**
@@ -196,7 +201,7 @@ public class AccountingProcessorHelper {
* @param amount
* @param isReversal
*/
public void createCashBasedJournalEntriesAndReversalsForSavings(final Office office,
public void createCashBasedJournalEntriesAndReversalsForSavings(final Office office, final String currencyCode,
final CASH_ACCOUNTS_FOR_SAVINGS accountTypeToBeDebited, final CASH_ACCOUNTS_FOR_SAVINGS accountTypeToBeCredited,
final Long savingsProductId, final Long paymentTypeId, final Long loanId, final String transactionId,
final Date transactionDate, final BigDecimal amount, final Boolean isReversal) {
@@ -207,8 +212,8 @@ public class AccountingProcessorHelper {
accountTypeToDebitId = accountTypeToBeCredited.getValue();
accountTypeToCreditId = accountTypeToBeDebited.getValue();
}
createJournalEntriesForSavings(office, accountTypeToDebitId, accountTypeToCreditId, savingsProductId, paymentTypeId, loanId,
transactionId, transactionDate, amount);
createJournalEntriesForSavings(office, currencyCode, accountTypeToDebitId, accountTypeToCreditId, savingsProductId, paymentTypeId,
loanId, transactionId, transactionDate, amount);
}
/**
@@ -231,9 +236,10 @@ public class AccountingProcessorHelper {
* @param amount
* @param isReversal
*/
public void createCashBasedJournalEntriesAndReversalsForLoan(final Office office, final CASH_ACCOUNTS_FOR_LOAN accountTypeToBeDebited,
final CASH_ACCOUNTS_FOR_LOAN accountTypeToBeCredited, final Long loanProductId, final Long paymentTypeId, final Long loanId,
final String transactionId, final Date transactionDate, final BigDecimal amount, final Boolean isReversal) {
public void createCashBasedJournalEntriesAndReversalsForLoan(final Office office, final String currencyCode,
final CASH_ACCOUNTS_FOR_LOAN accountTypeToBeDebited, final CASH_ACCOUNTS_FOR_LOAN accountTypeToBeCredited,
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate,
final BigDecimal amount, final Boolean isReversal) {
int accountTypeToDebitId = accountTypeToBeDebited.getValue();
int accountTypeToCreditId = accountTypeToBeCredited.getValue();
// reverse debits and credits for reversals
@@ -241,40 +247,40 @@ public class AccountingProcessorHelper {
accountTypeToDebitId = accountTypeToBeCredited.getValue();
accountTypeToCreditId = accountTypeToBeDebited.getValue();
}
createJournalEntriesForLoan(office, accountTypeToDebitId, accountTypeToCreditId, loanProductId, paymentTypeId, loanId,
transactionId, transactionDate, amount);
createJournalEntriesForLoan(office, currencyCode, accountTypeToDebitId, accountTypeToCreditId, loanProductId, paymentTypeId,
loanId, transactionId, transactionDate, amount);
}
public void createCreditJournalEntryOrReversalForLoan(final Office office, final CASH_ACCOUNTS_FOR_LOAN accountMappingType,
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate,
final BigDecimal amount, final Boolean isReversal) {
public void createCreditJournalEntryOrReversalForLoan(final Office office, final String currencyCode,
final CASH_ACCOUNTS_FOR_LOAN accountMappingType, final Long loanProductId, final Long paymentTypeId, final Long loanId,
final String transactionId, final Date transactionDate, final BigDecimal amount, final Boolean isReversal) {
int accountMappingTypeId = accountMappingType.getValue();
createCreditJournalEntryOrReversalForLoan(office, accountMappingTypeId, loanProductId, paymentTypeId, loanId, transactionId,
transactionDate, amount, isReversal);
createCreditJournalEntryOrReversalForLoan(office, currencyCode, accountMappingTypeId, loanProductId, paymentTypeId, loanId,
transactionId, transactionDate, amount, isReversal);
}
public void createCreditJournalEntryOrReversalForLoan(final Office office, final ACCRUAL_ACCOUNTS_FOR_LOAN accountMappingType,
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate,
final BigDecimal amount, final Boolean isReversal) {
public void createCreditJournalEntryOrReversalForLoan(final Office office, final String currencyCode,
final ACCRUAL_ACCOUNTS_FOR_LOAN accountMappingType, final Long loanProductId, final Long paymentTypeId, final Long loanId,
final String transactionId, final Date transactionDate, final BigDecimal amount, final Boolean isReversal) {
int accountMappingTypeId = accountMappingType.getValue();
createCreditJournalEntryOrReversalForLoan(office, accountMappingTypeId, loanProductId, paymentTypeId, loanId, transactionId,
transactionDate, amount, isReversal);
createCreditJournalEntryOrReversalForLoan(office, currencyCode, accountMappingTypeId, loanProductId, paymentTypeId, loanId,
transactionId, transactionDate, amount, isReversal);
}
public void createDebitJournalEntryOrReversalForLoan(final Office office, final CASH_ACCOUNTS_FOR_LOAN accountMappingType,
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate,
final BigDecimal amount, final Boolean isReversal) {
public void createDebitJournalEntryOrReversalForLoan(final Office office, final String currencyCode,
final CASH_ACCOUNTS_FOR_LOAN accountMappingType, final Long loanProductId, final Long paymentTypeId, final Long loanId,
final String transactionId, final Date transactionDate, final BigDecimal amount, final Boolean isReversal) {
int accountMappingTypeId = accountMappingType.getValue();
createDebitJournalEntryOrReversalForLoan(office, accountMappingTypeId, loanProductId, paymentTypeId, loanId, transactionId,
transactionDate, amount, isReversal);
createDebitJournalEntryOrReversalForLoan(office, currencyCode, accountMappingTypeId, loanProductId, paymentTypeId, loanId,
transactionId, transactionDate, amount, isReversal);
}
public void createDebitJournalEntryOrReversalForLoan(final Office office, final ACCRUAL_ACCOUNTS_FOR_LOAN accountMappingType,
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate,
final BigDecimal amount, final Boolean isReversal) {
public void createDebitJournalEntryOrReversalForLoan(final Office office, final String currencyCode,
final ACCRUAL_ACCOUNTS_FOR_LOAN accountMappingType, final Long loanProductId, final Long paymentTypeId, final Long loanId,
final String transactionId, final Date transactionDate, final BigDecimal amount, final Boolean isReversal) {
int accountMappingTypeId = accountMappingType.getValue();
createDebitJournalEntryOrReversalForLoan(office, accountMappingTypeId, loanProductId, paymentTypeId, loanId, transactionId,
transactionDate, amount, isReversal);
createDebitJournalEntryOrReversalForLoan(office, currencyCode, accountMappingTypeId, loanProductId, paymentTypeId, loanId,
transactionId, transactionDate, amount, isReversal);
}
/**
@@ -300,38 +306,39 @@ public class AccountingProcessorHelper {
return this.officeRepository.findOne(officeId);
}
private void createJournalEntriesForLoan(final Office office, final int accountTypeToDebitId, final int accountTypeToCreditId,
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate,
final BigDecimal amount) {
private void createJournalEntriesForLoan(final Office office, final String currencyCode, final int accountTypeToDebitId,
final int accountTypeToCreditId, final Long loanProductId, final Long paymentTypeId, final Long loanId,
final String transactionId, final Date transactionDate, final BigDecimal amount) {
GLAccount debitAccount = getLinkedGLAccountForLoanProduct(loanProductId, accountTypeToDebitId, paymentTypeId);
GLAccount creditAccount = getLinkedGLAccountForLoanProduct(loanProductId, accountTypeToCreditId, paymentTypeId);
createDebitJournalEntryForLoan(office, debitAccount, loanId, transactionId, transactionDate, amount);
createCreditJournalEntryForLoan(office, creditAccount, loanId, transactionId, transactionDate, amount);
createDebitJournalEntryForLoan(office, currencyCode, debitAccount, loanId, transactionId, transactionDate, amount);
createCreditJournalEntryForLoan(office, currencyCode, creditAccount, loanId, transactionId, transactionDate, amount);
}
private void createJournalEntriesForSavings(final Office office, final int accountTypeToDebitId, final int accountTypeToCreditId,
final Long savingsProductId, final Long paymentTypeId, final Long savingsId, final String transactionId,
final Date transactionDate, final BigDecimal amount) {
private void createJournalEntriesForSavings(final Office office, final String currencyCode, final int accountTypeToDebitId,
final int accountTypeToCreditId, final Long savingsProductId, final Long paymentTypeId, final Long savingsId,
final String transactionId, final Date transactionDate, final BigDecimal amount) {
GLAccount debitAccount = getLinkedGLAccountForSavingsProduct(savingsProductId, accountTypeToDebitId, paymentTypeId);
GLAccount creditAccount = getLinkedGLAccountForSavingsProduct(savingsProductId, accountTypeToCreditId, paymentTypeId);
createDebitJournalEntryForSavings(office, debitAccount, savingsId, transactionId, transactionDate, amount);
createCreditJournalEntryForSavings(office, creditAccount, savingsId, transactionId, transactionDate, amount);
createDebitJournalEntryForSavings(office, currencyCode, debitAccount, savingsId, transactionId, transactionDate, amount);
createCreditJournalEntryForSavings(office, currencyCode, creditAccount, savingsId, transactionId, transactionDate, amount);
}
private void createDebitJournalEntryOrReversalForLoan(final Office office, final int accountMappingTypeId, final Long loanProductId,
final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate, final BigDecimal amount,
final Boolean isReversal) {
private void createDebitJournalEntryOrReversalForLoan(final Office office, final String currencyCode, final int accountMappingTypeId,
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate,
final BigDecimal amount, final Boolean isReversal) {
GLAccount account = getLinkedGLAccountForLoanProduct(loanProductId, accountMappingTypeId, paymentTypeId);
if (isReversal) {
createCreditJournalEntryForLoan(office, account, loanId, transactionId, transactionDate, amount);
createCreditJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
} else {
createDebitJournalEntryForLoan(office, account, loanId, transactionId, transactionDate, amount);
createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
}
}
public void createCreditJournalEntryOrReversalForLoanCharges(final Office office, final int accountMappingTypeId,
final Long loanProductId, final Long loanId, final String transactionId, final Date transactionDate,
final BigDecimal totalAmount, final Boolean isReversal, final List<ChargePaymentDTO> chargePaymentDTOs) {
public void createCreditJournalEntryOrReversalForLoanCharges(final Office office, final String currencyCode,
final int accountMappingTypeId, final Long loanProductId, final Long loanId, final String transactionId,
final Date transactionDate, final BigDecimal totalAmount, final Boolean isReversal,
final List<ChargePaymentDTO> chargePaymentDTOs) {
/***
* Map to track each account and the net credit to be made for a
* particular account
@@ -357,9 +364,9 @@ public class AccountingProcessorHelper {
BigDecimal amount = entry.getValue();
totalCreditedAmount = totalCreditedAmount.add(amount);
if (isReversal) {
createDebitJournalEntryForLoan(office, account, loanId, transactionId, transactionDate, amount);
createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
} else {
createCreditJournalEntryForLoan(office, account, loanId, transactionId, transactionDate, amount);
createCreditJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
}
}
@@ -371,46 +378,46 @@ public class AccountingProcessorHelper {
totalCreditedAmount, totalAmount); }
}
private void createCreditJournalEntryOrReversalForLoan(final Office office, final int accountMappingTypeId, final Long loanProductId,
final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate, final BigDecimal amount,
final Boolean isReversal) {
private void createCreditJournalEntryOrReversalForLoan(final Office office, final String currencyCode, final int accountMappingTypeId,
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate,
final BigDecimal amount, final Boolean isReversal) {
GLAccount account = getLinkedGLAccountForLoanProduct(loanProductId, accountMappingTypeId, paymentTypeId);
if (isReversal) {
createDebitJournalEntryForLoan(office, account, loanId, transactionId, transactionDate, amount);
createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
} else {
createCreditJournalEntryForLoan(office, account, loanId, transactionId, transactionDate, amount);
createCreditJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
}
}
private void createCreditJournalEntryForLoan(final Office office, final GLAccount account, final Long loanId,
final String transactionId, final Date transactionDate, final BigDecimal amount) {
private void createCreditJournalEntryForLoan(final Office office, final String currencyCode, final GLAccount account,
final Long loanId, final String transactionId, final Date transactionDate, final BigDecimal amount) {
final boolean manualEntry = false;
final JournalEntry journalEntry = JournalEntry.createNew(office, account, transactionId, manualEntry, transactionDate,
JournalEntryType.CREDIT, amount, null, PortfolioProductType.LOAN.getValue(), loanId, null);
final JournalEntry journalEntry = JournalEntry.createNew(office, account, currencyCode, transactionId, manualEntry,
transactionDate, JournalEntryType.CREDIT, amount, null, PortfolioProductType.LOAN.getValue(), loanId, null);
this.glJournalEntryRepository.saveAndFlush(journalEntry);
}
private void createCreditJournalEntryForSavings(final Office office, final GLAccount account, final Long savingsId,
final String transactionId, final Date transactionDate, final BigDecimal amount) {
private void createCreditJournalEntryForSavings(final Office office, final String currencyCode, final GLAccount account,
final Long savingsId, final String transactionId, final Date transactionDate, final BigDecimal amount) {
final boolean manualEntry = false;
final JournalEntry journalEntry = JournalEntry.createNew(office, account, transactionId, manualEntry, transactionDate,
JournalEntryType.CREDIT, amount, null, PortfolioProductType.SAVING.getValue(), savingsId, null);
final JournalEntry journalEntry = JournalEntry.createNew(office, account, currencyCode, transactionId, manualEntry,
transactionDate, JournalEntryType.CREDIT, amount, null, PortfolioProductType.SAVING.getValue(), savingsId, null);
this.glJournalEntryRepository.saveAndFlush(journalEntry);
}
private void createDebitJournalEntryForLoan(final Office office, final GLAccount account, final Long loanId,
private void createDebitJournalEntryForLoan(final Office office, final String currencyCode, final GLAccount account, final Long loanId,
final String transactionId, final Date transactionDate, final BigDecimal amount) {
final boolean manualEntry = false;
final JournalEntry journalEntry = JournalEntry.createNew(office, account, transactionId, manualEntry, transactionDate,
JournalEntryType.DEBIT, amount, null, PortfolioProductType.LOAN.getValue(), loanId, null);
final JournalEntry journalEntry = JournalEntry.createNew(office, account, currencyCode, transactionId, manualEntry,
transactionDate, JournalEntryType.DEBIT, amount, null, PortfolioProductType.LOAN.getValue(), loanId, null);
this.glJournalEntryRepository.saveAndFlush(journalEntry);
}
private void createDebitJournalEntryForSavings(final Office office, final GLAccount account, final Long savingsId,
final String transactionId, final Date transactionDate, final BigDecimal amount) {
private void createDebitJournalEntryForSavings(final Office office, final String currencyCode, final GLAccount account,
final Long savingsId, final String transactionId, final Date transactionDate, final BigDecimal amount) {
final boolean manualEntry = false;
final JournalEntry journalEntry = JournalEntry.createNew(office, account, transactionId, manualEntry, transactionDate,
JournalEntryType.DEBIT, amount, null, PortfolioProductType.SAVING.getValue(), savingsId, null);
final JournalEntry journalEntry = JournalEntry.createNew(office, account, currencyCode, transactionId, manualEntry,
transactionDate, JournalEntryType.DEBIT, amount, null, PortfolioProductType.SAVING.getValue(), savingsId, null);
this.glJournalEntryRepository.saveAndFlush(journalEntry);
}
@@ -80,6 +80,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// loan properties
final Long loanProductId = loanDTO.getLoanProductId();
final Long loanId = loanDTO.getLoanId();
final String currencyCode = loanDTO.getCurrencyCode();
// transaction properties
final String transactionId = loanTransactionDTO.getTransactionId();
@@ -90,7 +91,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// create journal entries for the disbursement (or disbursement
// reversal)
helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO,
helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO,
ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE, loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
disbursalAmount, isReversed);
@@ -110,6 +111,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// loan properties
final Long loanProductId = loanDTO.getLoanProductId();
final Long loanId = loanDTO.getLoanId();
final String currencyCode = loanDTO.getCurrencyCode();
// transaction properties
final String transactionId = loanTransactionDTO.getTransactionId();
@@ -120,7 +122,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// create journal entries for recognising interest (or reversal)
if (amount != null && !(amount.compareTo(BigDecimal.ZERO) == 0)) {
helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE,
helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE,
ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS, loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
amount, isReversed);
}
@@ -172,6 +174,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// loan properties
final Long loanProductId = loanDTO.getLoanProductId();
final Long loanId = loanDTO.getLoanId();
final String currencyCode = loanDTO.getCurrencyCode();
// transaction properties
final String transactionId = loanTransactionDTO.getTransactionId();
@@ -188,15 +191,15 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// handle principal payment or writeOff (and reversals)
if (principalAmount != null && !(principalAmount.compareTo(BigDecimal.ZERO) == 0)) {
totalDebitAmount = totalDebitAmount.add(principalAmount);
helper.createCreditJournalEntryOrReversalForLoan(office, ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO, loanProductId,
helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO, loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, principalAmount, isReversal);
}
// handle interest payment of writeOff (and reversals)
if (interestAmount != null && !(interestAmount.compareTo(BigDecimal.ZERO) == 0)) {
totalDebitAmount = totalDebitAmount.add(interestAmount);
helper.createCreditJournalEntryOrReversalForLoan(office, ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE, loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, interestAmount, isReversal);
helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE,
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, interestAmount, isReversal);
}
// handle fees payment of writeOff (and reversals)
@@ -209,15 +212,15 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
feeAccountToCredit = ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES;
}
helper.createCreditJournalEntryOrReversalForLoan(office, feeAccountToCredit, loanProductId, paymentTypeId, loanId,
transactionId, transactionDate, feesAmount, isReversal);
helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, feeAccountToCredit, loanProductId, paymentTypeId,
loanId, transactionId, transactionDate, feesAmount, isReversal);
}
// handle penalties payment of writeOff (and reversals)
if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) {
totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
helper.createCreditJournalEntryOrReversalForLoan(office, ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE, loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, penaltiesAmount, isReversal);
helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE,
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, penaltiesAmount, isReversal);
}
/**
@@ -225,11 +228,11 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
* reversals)
***/
if (writeOff) {
helper.createDebitJournalEntryOrReversalForLoan(office, ACCRUAL_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF, loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF,
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
} else {
helper.createDebitJournalEntryOrReversalForLoan(office, ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE, loanProductId, paymentTypeId,
loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE, loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
}
}
@@ -254,6 +257,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// loan properties
final Long loanProductId = loanDTO.getLoanProductId();
final Long loanId = loanDTO.getLoanId();
final String currencyCode = loanDTO.getCurrencyCode();
// transaction properties
final String transactionId = loanTransactionDTO.getTransactionId();
@@ -265,15 +269,15 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// create journal entries for the fees application (or reversal)
if (feesAmount != null && !(feesAmount.compareTo(BigDecimal.ZERO) == 0)) {
helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, ACCRUAL_ACCOUNTS_FOR_LOAN.FEES_RECEIVABLE,
helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.FEES_RECEIVABLE,
ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES, loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
feesAmount, isReversed);
}
// create journal entries for the penalties application (or reversal)
else if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) {
helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE,
ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES, loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
penaltiesAmount, isReversed);
helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE, ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES, loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, penaltiesAmount, isReversed);
}
}
}
@@ -32,6 +32,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
// final Office office =
// this.helper.getOfficeById(loanDTO.getOfficeId());
final Long loanProductId = loanDTO.getLoanProductId();
final String currencyCode = loanDTO.getCurrencyCode();
for (final LoanTransactionDTO loanTransactionDTO : loanDTO.getNewLoanTransactions()) {
final Date transactionDate = loanTransactionDTO.getTransactionDate();
final String transactionId = loanTransactionDTO.getTransactionId();
@@ -60,7 +61,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
**/
else if (loanTransactionDTO.getTransactionType().isWriteOff() && !loanTransactionDTO.isReversed()) {
final BigDecimal principalAmount = loanTransactionDTO.getPrincipal();
helper.createCashBasedJournalEntriesAndReversalsForLoan(office, CASH_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF,
helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF,
CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO, loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
principalAmount, false);
} else if (loanTransactionDTO.getTransactionType().isInitiateTransfer()
@@ -87,6 +88,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
// loan properties
final Long loanProductId = loanDTO.getLoanProductId();
final Long loanId = loanDTO.getLoanId();
final String currencyCode = loanDTO.getCurrencyCode();
// transaction properties
final String transactionId = loanTransactionDTO.getTransactionId();
@@ -95,7 +97,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
helper.createCashBasedJournalEntriesAndReversalsForLoan(office, CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO,
helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO,
CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE, loanProductId, paymentTypeId, loanId, transactionId, transactionDate, disbursalAmount,
isReversal);
}
@@ -113,6 +115,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
// loan properties
final Long loanProductId = loanDTO.getLoanProductId();
final Long loanId = loanDTO.getLoanId();
final String currencyCode = loanDTO.getCurrencyCode();
// transaction properties
final String transactionId = loanTransactionDTO.getTransactionId();
@@ -128,32 +131,33 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
if (principalAmount != null && !(principalAmount.compareTo(BigDecimal.ZERO) == 0)) {
totalDebitAmount = totalDebitAmount.add(principalAmount);
helper.createCreditJournalEntryOrReversalForLoan(office, CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO, loanProductId, paymentTypeId,
loanId, transactionId, transactionDate, principalAmount, isReversal);
helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO, loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, principalAmount, isReversal);
}
if (interestAmount != null && !(interestAmount.compareTo(BigDecimal.ZERO) == 0)) {
totalDebitAmount = totalDebitAmount.add(interestAmount);
helper.createCreditJournalEntryOrReversalForLoan(office, CASH_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS, loanProductId,
helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS, loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, interestAmount, isReversal);
}
if (feesAmount != null && !(feesAmount.compareTo(BigDecimal.ZERO) == 0)) {
totalDebitAmount = totalDebitAmount.add(feesAmount);
helper.createCreditJournalEntryOrReversalForLoanCharges(office, CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue(),
loanProductId, loanId, transactionId, transactionDate, feesAmount, isReversal, loanTransactionDTO.getFeePayments());
helper.createCreditJournalEntryOrReversalForLoanCharges(office, currencyCode,
CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue(), loanProductId, loanId, transactionId, transactionDate, feesAmount,
isReversal, loanTransactionDTO.getFeePayments());
}
if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) {
totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
helper.createCreditJournalEntryOrReversalForLoanCharges(office, CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue(),
loanProductId, loanId, transactionId, transactionDate, penaltiesAmount, isReversal,
loanTransactionDTO.getPenaltyPayments());
helper.createCreditJournalEntryOrReversalForLoanCharges(office, currencyCode,
CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue(), loanProductId, loanId, transactionId, transactionDate,
penaltiesAmount, isReversal, loanTransactionDTO.getPenaltyPayments());
}
/*** create a single debit entry (or reversal) for the entire amount **/
helper.createDebitJournalEntryOrReversalForLoan(office, CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE, loanProductId, paymentTypeId, loanId,
transactionId, transactionDate, totalDebitAmount, isReversal);
helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE, loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
}
/**
@@ -173,6 +177,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
// loan properties
final Long loanProductId = loanDTO.getLoanProductId();
final Long loanId = loanDTO.getLoanId();
final String currencyCode = loanDTO.getCurrencyCode();
// transaction properties
final String transactionId = loanTransactionDTO.getTransactionId();
@@ -182,12 +187,12 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
// final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
if (loanTransactionDTO.getTransactionType().isInitiateTransfer()) {
helper.createCashBasedJournalEntriesAndReversalsForLoan(office, CASH_ACCOUNTS_FOR_LOAN.TRANSFERS_SUSPENSE,
helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.TRANSFERS_SUSPENSE,
CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO, loanProductId, null, loanId, transactionId, transactionDate, principalAmount,
isReversal);
} else if (loanTransactionDTO.getTransactionType().isApproveTransfer()
|| loanTransactionDTO.getTransactionType().isWithdrawTransfer()) {
helper.createCashBasedJournalEntriesAndReversalsForLoan(office, CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO,
helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO,
CASH_ACCOUNTS_FOR_LOAN.TRANSFERS_SUSPENSE, loanProductId, null, loanId, transactionId, transactionDate,
principalAmount, isReversal);
}
@@ -31,6 +31,7 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
final GLClosure latestGLClosure = this.helper.getLatestClosureByBranch(savingsDTO.getOfficeId());
final Long savingsProductId = savingsDTO.getSavingsProductId();
final Long savingsId = savingsDTO.getSavingsId();
final String currencyCode = savingsDTO.getCurrencyCode();
for (final SavingsTransactionDTO savingsTransactionDTO : savingsDTO.getNewSavingsTransactions()) {
final Date transactionDate = savingsTransactionDTO.getTransactionDate();
final String transactionId = savingsTransactionDTO.getTransactionId();
@@ -43,14 +44,14 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
/** Handle Deposits and reversals of deposits **/
if (savingsTransactionDTO.getTransactionType().isDeposit()) {
helper.createCashBasedJournalEntriesAndReversalsForSavings(office, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId, paymentTypeId, savingsId, transactionId,
transactionDate, amount, isReversal);
helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
}
/** Handle withdrawals and reversals of withdrawals **/
else if (savingsTransactionDTO.getTransactionType().isWithdrawal()) {
helper.createCashBasedJournalEntriesAndReversalsForSavings(office, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL,
helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, savingsProductId, paymentTypeId, savingsId, transactionId,
transactionDate, amount, isReversal);
}
@@ -60,21 +61,21 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
* Applications
**/
else if (savingsTransactionDTO.getTransactionType().isInterestPosting()) {
helper.createCashBasedJournalEntriesAndReversalsForSavings(office, CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId, paymentTypeId, savingsId, transactionId,
transactionDate, amount, isReversal);
helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
}
/** Handle Fees Deductions and reversals of Fees Deductions **/
else if (savingsTransactionDTO.getTransactionType().isFeeDeduction()) {
helper.createCashBasedJournalEntriesAndReversalsForSavings(office, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL,
helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL,
CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_FEES, savingsProductId, paymentTypeId, savingsId, transactionId,
transactionDate, amount, isReversal);
}
/** Handle Transfers proposal **/
else if (savingsTransactionDTO.getTransactionType().isInitiateTransfer()) {
helper.createCashBasedJournalEntriesAndReversalsForSavings(office, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL,
helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL,
CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE, savingsProductId, paymentTypeId, savingsId, transactionId,
transactionDate, amount, isReversal);
}
@@ -82,9 +83,9 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
/** Handle Transfer Withdrawal or Acceptance **/
else if (savingsTransactionDTO.getTransactionType().isWithdrawTransfer()
|| savingsTransactionDTO.getTransactionType().isApproveTransfer()) {
helper.createCashBasedJournalEntriesAndReversalsForSavings(office, CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId, paymentTypeId, savingsId, transactionId,
transactionDate, amount, isReversal);
helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
}
}
@@ -42,6 +42,7 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.office.domain.OfficeRepository;
import org.mifosplatform.organisation.office.domain.OrganisationCurrencyRepositoryWrapper;
import org.mifosplatform.organisation.office.exception.OfficeNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -65,6 +66,7 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
private final JournalEntryCommandFromApiJsonDeserializer fromApiJsonDeserializer;
private final AccountingRuleRepository accountingRuleRepository;
private final GLAccountReadPlatformService glAccountReadPlatformService;
private final OrganisationCurrencyRepositoryWrapper organisationCurrencyRepository;
@Autowired
public JournalEntryWritePlatformServiceJpaRepositoryImpl(final GLClosureRepository glClosureRepository,
@@ -73,7 +75,8 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
final AccountingProcessorHelper accountingProcessorHelper, final AccountingRuleRepository accountingRuleRepository,
final AccountingProcessorForLoanFactory accountingProcessorForLoanFactory,
final AccountingProcessorForSavingsFactory accountingProcessorForSavingsFactory,
final GLAccountReadPlatformService glAccountReadPlatformService) {
final GLAccountReadPlatformService glAccountReadPlatformService,
final OrganisationCurrencyRepositoryWrapper organisationCurrencyRepository) {
this.glClosureRepository = glClosureRepository;
this.officeRepository = officeRepository;
this.glJournalEntryRepository = glJournalEntryRepository;
@@ -84,6 +87,7 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
this.helper = accountingProcessorHelper;
this.accountingRuleRepository = accountingRuleRepository;
this.glAccountReadPlatformService = glAccountReadPlatformService;
this.organisationCurrencyRepository = organisationCurrencyRepository;
}
@Transactional
@@ -99,6 +103,7 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
if (office == null) { throw new OfficeNotFoundException(officeId); }
final Long accountRuleId = command.longValueOfParameterNamed(JournalEntryJsonInputParams.ACCOUNTING_RULE.getValue());
final String currencyCode = command.stringValueOfParameterNamed(JournalEntryJsonInputParams.CURRENCY_CODE.getValue());
validateBusinessRulesForJournalEntries(journalEntryCommand);
@@ -121,14 +126,14 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
checkDebitAndCreditAmounts(journalEntryCommand.getCredits(), journalEntryCommand.getDebits());
}
saveAllDebitOrCreditEntries(journalEntryCommand, office, transactionDate, journalEntryCommand.getCredits(),
transactionId, JournalEntryType.CREDIT, referenceNumber);
saveAllDebitOrCreditEntries(journalEntryCommand, office, currencyCode, transactionDate,
journalEntryCommand.getCredits(), transactionId, JournalEntryType.CREDIT, referenceNumber);
} else {
final GLAccount creditAccountHead = accountingRule.getAccountToCredit();
validateGLAccountForTransaction(creditAccountHead);
validateDebitOrCreditArrayForExistingGLAccount(creditAccountHead,journalEntryCommand.getCredits());
saveAllDebitOrCreditEntries(journalEntryCommand, office, transactionDate, journalEntryCommand.getCredits(),
transactionId, JournalEntryType.CREDIT, referenceNumber);
validateDebitOrCreditArrayForExistingGLAccount(creditAccountHead, journalEntryCommand.getCredits());
saveAllDebitOrCreditEntries(journalEntryCommand, office, currencyCode, transactionDate,
journalEntryCommand.getCredits(), transactionId, JournalEntryType.CREDIT, referenceNumber);
}
if (accountingRule.getAccountToDebit() == null) {
@@ -140,22 +145,22 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
checkDebitAndCreditAmounts(journalEntryCommand.getCredits(), journalEntryCommand.getDebits());
}
saveAllDebitOrCreditEntries(journalEntryCommand, office, transactionDate, journalEntryCommand.getDebits(),
transactionId, JournalEntryType.DEBIT, referenceNumber);
saveAllDebitOrCreditEntries(journalEntryCommand, office, currencyCode, transactionDate,
journalEntryCommand.getDebits(), transactionId, JournalEntryType.DEBIT, referenceNumber);
} else {
final GLAccount debitAccountHead = accountingRule.getAccountToDebit();
validateGLAccountForTransaction(debitAccountHead);
validateDebitOrCreditArrayForExistingGLAccount(debitAccountHead,journalEntryCommand.getDebits());
saveAllDebitOrCreditEntries(journalEntryCommand, office, transactionDate, journalEntryCommand.getDebits(),
transactionId, JournalEntryType.DEBIT, referenceNumber);
validateDebitOrCreditArrayForExistingGLAccount(debitAccountHead, journalEntryCommand.getDebits());
saveAllDebitOrCreditEntries(journalEntryCommand, office, currencyCode, transactionDate,
journalEntryCommand.getDebits(), transactionId, JournalEntryType.DEBIT, referenceNumber);
}
} else {
saveAllDebitOrCreditEntries(journalEntryCommand, office, transactionDate, journalEntryCommand.getDebits(), transactionId,
JournalEntryType.DEBIT, referenceNumber);
saveAllDebitOrCreditEntries(journalEntryCommand, office, currencyCode, transactionDate, journalEntryCommand.getDebits(),
transactionId, JournalEntryType.DEBIT, referenceNumber);
saveAllDebitOrCreditEntries(journalEntryCommand, office, transactionDate, journalEntryCommand.getCredits(), transactionId,
JournalEntryType.CREDIT, referenceNumber);
saveAllDebitOrCreditEntries(journalEntryCommand, office, currencyCode, transactionDate, journalEntryCommand.getCredits(),
transactionId, JournalEntryType.CREDIT, referenceNumber);
}
@@ -266,13 +271,13 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
final String reversalComment = "Reversal entry for Journal Entry with Entry Id :" + journalEntry.getId()
+ " and transaction Id " + command.getTransactionId();
if (journalEntry.isDebitEntry()) {
reversalJournalEntry = JournalEntry.createNew(journalEntry.getOffice(), journalEntry.getGlAccount(), reversalTransactionId,
manualEntry, journalEntry.getTransactionDate(), JournalEntryType.CREDIT, journalEntry.getAmount(), reversalComment,
null, null, journalEntry.getReferenceNumber());
reversalJournalEntry = JournalEntry.createNew(journalEntry.getOffice(), journalEntry.getGlAccount(),
journalEntry.getCurrencyCode(), reversalTransactionId, manualEntry, journalEntry.getTransactionDate(),
JournalEntryType.CREDIT, journalEntry.getAmount(), reversalComment, null, null, journalEntry.getReferenceNumber());
} else {
reversalJournalEntry = JournalEntry.createNew(journalEntry.getOffice(), journalEntry.getGlAccount(), reversalTransactionId,
manualEntry, journalEntry.getTransactionDate(), JournalEntryType.DEBIT, journalEntry.getAmount(), reversalComment,
null, null, journalEntry.getReferenceNumber());
reversalJournalEntry = JournalEntry.createNew(journalEntry.getOffice(), journalEntry.getGlAccount(),
journalEntry.getCurrencyCode(), reversalTransactionId, manualEntry, journalEntry.getTransactionDate(),
JournalEntryType.DEBIT, journalEntry.getAmount(), reversalComment, null, null, journalEntry.getReferenceNumber());
}
// save the reversal entry
this.glJournalEntryRepository.saveAndFlush(reversalJournalEntry);
@@ -343,9 +348,9 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
checkDebitAndCreditAmounts(credits, debits);
}
private void saveAllDebitOrCreditEntries(final JournalEntryCommand command, final Office office, final Date transactionDate,
final SingleDebitOrCreditEntryCommand[] singleDebitOrCreditEntryCommands, final String transactionId,
final JournalEntryType type, final String referenceNumber) {
private void saveAllDebitOrCreditEntries(final JournalEntryCommand command, final Office office, final String currencyCode,
final Date transactionDate, final SingleDebitOrCreditEntryCommand[] singleDebitOrCreditEntryCommands,
final String transactionId, final JournalEntryType type, final String referenceNumber) {
final boolean manualEntry = true;
for (final SingleDebitOrCreditEntryCommand singleDebitOrCreditEntryCommand : singleDebitOrCreditEntryCommands) {
final GLAccount glAccount = this.glAccountRepository.findOne(singleDebitOrCreditEntryCommand.getGlAccountId());
@@ -357,8 +362,12 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
if (!StringUtils.isBlank(singleDebitOrCreditEntryCommand.getComments())) {
comments = singleDebitOrCreditEntryCommand.getComments();
}
final JournalEntry glJournalEntry = JournalEntry.createNew(office, glAccount, transactionId, manualEntry, transactionDate,
type, singleDebitOrCreditEntryCommand.getAmount(), comments, null, null, referenceNumber);
/** Validate current code is appropriate **/
this.organisationCurrencyRepository.findOneWithNotFoundDetection(currencyCode);
final JournalEntry glJournalEntry = JournalEntry.createNew(office, glAccount, currencyCode, transactionId, manualEntry,
transactionDate, type, singleDebitOrCreditEntryCommand.getAmount(), comments, null, null, referenceNumber);
this.glJournalEntryRepository.saveAndFlush(glJournalEntry);
}
}
@@ -0,0 +1,20 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.organisation.monetary.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
/**
* A {@link RuntimeException} thrown when urrency is not supported by an
* Organization.
*/
public class OrganizationalCurrencyNotFoundException extends AbstractPlatformResourceNotFoundException {
public OrganizationalCurrencyNotFoundException(final String currencyCode) {
super("error.msg.currency.currencyCode.invalid.or.not.supported", "Currency with identifier " + currencyCode
+ " does not exist or is not supported by the Organization", currencyCode);
}
}
@@ -8,6 +8,8 @@ package org.mifosplatform.organisation.office.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface OrganisationCurrencyRepository extends JpaRepository<OrganisationCurrency, Long>, JpaSpecificationExecutor<OrganisationCurrency> {
// no added behaviour
public interface OrganisationCurrencyRepository extends JpaRepository<OrganisationCurrency, Long>,
JpaSpecificationExecutor<OrganisationCurrency> {
OrganisationCurrency findOneByCode(String currencyCode);
}
@@ -0,0 +1,39 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.organisation.office.domain;
import org.mifosplatform.organisation.monetary.exception.OrganizationalCurrencyNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* <p>
* Wrapper for {@link OrganisationCurrency} that is responsible for checking if
* {@link OrganisationCurrency} is returned when using <code>findOne</code>
* repository method and throwing an appropriate not found exception.
* </p>
*
* <p>
* This is to avoid need for checking and throwing in multiple areas of code
* base where {@link OrganisationCurrency} is required.
* </p>
*/
@Service
public class OrganisationCurrencyRepositoryWrapper {
private final OrganisationCurrencyRepository repository;
@Autowired
public OrganisationCurrencyRepositoryWrapper(final OrganisationCurrencyRepository repository) {
this.repository = repository;
}
public OrganisationCurrency findOneWithNotFoundDetection(final String currencyCode) {
final OrganisationCurrency organisationCurrency = this.repository.findOneByCode(currencyCode);
if (organisationCurrency == null) { throw new OrganizationalCurrencyNotFoundException(currencyCode); }
return organisationCurrency;
}
}
@@ -2454,6 +2454,7 @@ public class Loan extends AbstractPersistable<Long> {
accountingBridgeData.put("loanId", getId());
accountingBridgeData.put("loanProductId", productId());
accountingBridgeData.put("officeId", getOfficeId());
accountingBridgeData.put("currency", currencyData);
accountingBridgeData.put("calculatedInterest", this.summary.getTotalInterestCharged());
accountingBridgeData.put("cashBasedAccountingEnabled", isCashBasedAccountingEnabledOnLoanProduct());
accountingBridgeData.put("accrualBasedAccountingEnabled", isAccrualBasedAccountingEnabledOnLoanProduct());
@@ -1161,6 +1161,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
final Map<String, Object> accountingBridgeData = new LinkedHashMap<String, Object>();
accountingBridgeData.put("savingsId", getId());
accountingBridgeData.put("savingsProductId", productId());
accountingBridgeData.put("currency", currencyData);
accountingBridgeData.put("officeId", officeId());
accountingBridgeData.put("cashBasedAccountingEnabled", isCashBasedAccountingEnabledOnSavingsProduct());
accountingBridgeData.put("accrualBasedAccountingEnabled", isAccrualBasedAccountingEnabledOnSavingsProduct());