track currency with accounting

This commit is contained in:
Vishwas Babu A J
2013-09-17 21:13:45 +05:30
parent 658d38a3fa
commit 2b8da96474
19 changed files with 328 additions and 161 deletions
+8
View File
@@ -17683,6 +17683,12 @@ No Request Body:
cost center) at which the financial activity cost center) at which the financial activity
occured</td> occured</td>
</tr> </tr>
<tr class=alt>
<td>currencyCode</td>
</tr>
<tr>
<td class=fielddesc>A three letter ISO code of currency.</td>
</tr>
<tr class=alt> <tr class=alt>
<td>glAccountId</td> <td>glAccountId</td>
</tr> </tr>
@@ -18026,6 +18032,7 @@ Request Body:
"transactionDate": "06 December 2012", "transactionDate": "06 December 2012",
"comments": "Gifts for staff", "comments": "Gifts for staff",
"locale": "en" , "locale": "en" ,
"currencyCode": "USD",
"dateFormat": "dd MMMM yyyy", "dateFormat": "dd MMMM yyyy",
"credits":[{"glAccountId":1, "credits":[{"glAccountId":1,
"amount":5000}, "amount":5000},
@@ -18058,6 +18065,7 @@ Request Body:
"officeId": "1", "officeId": "1",
"transactionDate": "23 May 2013", "transactionDate": "23 May 2013",
"referenceNumber": "547", "referenceNumber": "547",
"currencyCode": "USD",
"comments": "asdf", "comments": "asdf",
"accountingRule": "2", "accountingRule": "2",
"amount": "547" "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 { public enum JournalEntryJsonInputParams {
OFFICE_ID("officeId"), TRANSACTION_DATE("transactionDate"), COMMENTS("comments"), CREDITS("credits"), DEBITS("debits"), LOCALE("locale"), DATE_FORMAT( 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; private final String value;
@@ -10,6 +10,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.joda.time.LocalDate; 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.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder; import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
@@ -21,6 +22,7 @@ public class JournalEntryCommand {
private final Long officeId; private final Long officeId;
private final LocalDate transactionDate; private final LocalDate transactionDate;
private final String currencyCode;
private final String comments; private final String comments;
private final String referenceNumber; private final String referenceNumber;
private final Long accountingRuleId; private final Long accountingRuleId;
@@ -29,10 +31,11 @@ public class JournalEntryCommand {
private final SingleDebitOrCreditEntryCommand[] credits; private final SingleDebitOrCreditEntryCommand[] credits;
private final SingleDebitOrCreditEntryCommand[] debits; 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 SingleDebitOrCreditEntryCommand[] credits, final SingleDebitOrCreditEntryCommand[] debits, final String referenceNumber,
final Long accountingRuleId, final BigDecimal amount) { final Long accountingRuleId, final BigDecimal amount) {
this.officeId = officeId; this.officeId = officeId;
this.currencyCode = currencyCode;
this.transactionDate = transactionDate; this.transactionDate = transactionDate;
this.comments = comments; this.comments = comments;
this.credits = credits; this.credits = credits;
@@ -52,6 +55,8 @@ public class JournalEntryCommand {
baseDataValidator.reset().parameter("officeId").value(this.officeId).notNull().integerGreaterThanZero(); 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("comments").value(this.comments).ignoreIfNull().notExceedingLengthOf(500);
baseDataValidator.reset().parameter("referenceNumber").value(this.referenceNumber).ignoreIfNull().notExceedingLengthOf(100); baseDataValidator.reset().parameter("referenceNumber").value(this.referenceNumber).ignoreIfNull().notExceedingLengthOf(100);
@@ -12,18 +12,22 @@ public class LoanDTO {
private Long loanId; private Long loanId;
private Long loanProductId; private Long loanProductId;
private Long officeId; private Long officeId;
private String currencyCode;
private boolean cashBasedAccountingEnabled; private boolean cashBasedAccountingEnabled;
private boolean accrualBasedAccountingEnabled; private boolean accrualBasedAccountingEnabled;
private List<LoanTransactionDTO> newLoanTransactions; private List<LoanTransactionDTO> newLoanTransactions;
public LoanDTO(final Long loanId, final Long loanProductId, final Long officeId, final boolean cashBasedAccountingEnabled, public LoanDTO(final Long loanId, final Long loanProductId, final Long officeId, final String currencyCode,
final boolean accrualBasedAccountingEnabled, final List<LoanTransactionDTO> newLoanTransactions) { final boolean cashBasedAccountingEnabled, final boolean accrualBasedAccountingEnabled,
final List<LoanTransactionDTO> newLoanTransactions) {
this.loanId = loanId; this.loanId = loanId;
this.loanProductId = loanProductId; this.loanProductId = loanProductId;
this.officeId = officeId; this.officeId = officeId;
this.cashBasedAccountingEnabled = cashBasedAccountingEnabled; this.cashBasedAccountingEnabled = cashBasedAccountingEnabled;
this.accrualBasedAccountingEnabled = accrualBasedAccountingEnabled; this.accrualBasedAccountingEnabled = accrualBasedAccountingEnabled;
this.newLoanTransactions = newLoanTransactions; this.newLoanTransactions = newLoanTransactions;
this.currencyCode = currencyCode;
} }
public Long getLoanId() { public Long getLoanId() {
@@ -74,4 +78,12 @@ public class LoanDTO {
this.newLoanTransactions = newLoanTransactions; 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 savingsId;
private Long savingsProductId; private Long savingsProductId;
private Long officeId; private Long officeId;
private String currencyCode;
private boolean cashBasedAccountingEnabled; private boolean cashBasedAccountingEnabled;
private boolean accrualBasedAccountingEnabled; private boolean accrualBasedAccountingEnabled;
private List<SavingsTransactionDTO> newSavingsTransactions; private List<SavingsTransactionDTO> newSavingsTransactions;
public SavingsDTO(final Long savingsId, final Long savingsProductId, final Long officeId, final boolean cashBasedAccountingEnabled, public SavingsDTO(final Long savingsId, final Long savingsProductId, final Long officeId, final String currencyCode,
final boolean accrualBasedAccountingEnabled, final List<SavingsTransactionDTO> newSavingsTransactions) { final boolean cashBasedAccountingEnabled, final boolean accrualBasedAccountingEnabled,
final List<SavingsTransactionDTO> newSavingsTransactions) {
this.savingsId = savingsId; this.savingsId = savingsId;
this.savingsProductId = savingsProductId; this.savingsProductId = savingsProductId;
this.officeId = officeId; this.officeId = officeId;
this.cashBasedAccountingEnabled = cashBasedAccountingEnabled; this.cashBasedAccountingEnabled = cashBasedAccountingEnabled;
this.accrualBasedAccountingEnabled = accrualBasedAccountingEnabled; this.accrualBasedAccountingEnabled = accrualBasedAccountingEnabled;
this.newSavingsTransactions = newSavingsTransactions; this.newSavingsTransactions = newSavingsTransactions;
this.currencyCode = currencyCode;
} }
public Long getSavingsId() { public Long getSavingsId() {
@@ -74,4 +77,12 @@ public class SavingsDTO {
this.newSavingsTransactions = newSavingsTransactions; 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) @JoinColumn(name = "account_id", nullable = false)
private GLAccount glAccount; private GLAccount glAccount;
@Column(name = "currency_code", length = 3, nullable = false)
private String currencyCode;
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "reversal_id") @JoinColumn(name = "reversal_id")
private JournalEntry reversalJournalEntry; private JournalEntry reversalJournalEntry;
@@ -70,20 +73,20 @@ public class JournalEntry extends AbstractAuditableCustom<AppUser, Long> {
@Column(name = "ref_num") @Column(name = "ref_num")
private String referenceNumber; private String referenceNumber;
public static JournalEntry createNew(final Office office, final GLAccount glAccount, final String transactionId, public static JournalEntry createNew(final Office office, final GLAccount glAccount, final String currencyCode,
final boolean manualEntry, final Date transactionDate, final JournalEntryType journalEntryType, final BigDecimal amount, final String transactionId, final boolean manualEntry, final Date transactionDate, final JournalEntryType journalEntryType,
final String description, final Integer entityType, final Long entityId, final String referenceNumber) { 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, return new JournalEntry(office, glAccount, currencyCode, transactionId, manualEntry, transactionDate, journalEntryType.getValue(),
description, entityType, entityId, referenceNumber); amount, description, entityType, entityId, referenceNumber);
} }
protected JournalEntry() { protected JournalEntry() {
// //
} }
public JournalEntry(final Office office, final GLAccount glAccount, final String transactionId, final boolean manualEntry, public JournalEntry(final Office office, final GLAccount glAccount, final String currencyCode, final String transactionId,
final Date transactionDate, final Integer type, final BigDecimal amount, final String description, final Integer entityType, final boolean manualEntry, final Date transactionDate, final Integer type, final BigDecimal amount, final String description,
final Long entityId, final String referenceNumber) { final Integer entityType, final Long entityId, final String referenceNumber) {
this.office = office; this.office = office;
this.glAccount = glAccount; this.glAccount = glAccount;
this.reversalJournalEntry = null; this.reversalJournalEntry = null;
@@ -97,6 +100,7 @@ public class JournalEntry extends AbstractAuditableCustom<AppUser, Long> {
this.entityType = entityType; this.entityType = entityType;
this.entityId = entityId; this.entityId = entityId;
this.referenceNumber = referenceNumber; this.referenceNumber = referenceNumber;
this.currencyCode = currencyCode;
} }
@@ -136,4 +140,8 @@ public class JournalEntry extends AbstractAuditableCustom<AppUser, Long> {
return this.referenceNumber; 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 JsonElement element = this.fromApiJsonHelper.parse(json);
final Long officeId = this.fromApiJsonHelper.extractLongNamed(JournalEntryJsonInputParams.OFFICE_ID.getValue(), element); 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 String comments = this.fromApiJsonHelper.extractStringNamed(JournalEntryJsonInputParams.COMMENTS.getValue(), element);
final LocalDate transactionDate = this.fromApiJsonHelper.extractLocalDateNamed( final LocalDate transactionDate = this.fromApiJsonHelper.extractLocalDateNamed(
JournalEntryJsonInputParams.TRANSACTION_DATE.getValue(), element); JournalEntryJsonInputParams.TRANSACTION_DATE.getValue(), element);
@@ -64,7 +66,8 @@ public final class JournalEntryCommandFromApiJsonDeserializer extends AbstractFr
final JsonObject topLevelJsonElement = element.getAsJsonObject(); final JsonObject topLevelJsonElement = element.getAsJsonObject();
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement); 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[] credits = null;
SingleDebitOrCreditEntryCommand[] debits = null; SingleDebitOrCreditEntryCommand[] debits = null;
@@ -78,7 +81,8 @@ public final class JournalEntryCommandFromApiJsonDeserializer extends AbstractFr
debits = populateCreditsOrDebitsArray(topLevelJsonElement, locale, debits, JournalEntryJsonInputParams.DEBITS.getValue()); 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.ProductToGLAccountMapping;
import org.mifosplatform.accounting.producttoaccountmapping.domain.ProductToGLAccountMappingRepository; import org.mifosplatform.accounting.producttoaccountmapping.domain.ProductToGLAccountMappingRepository;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException; 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.Office;
import org.mifosplatform.organisation.office.domain.OfficeRepository; import org.mifosplatform.organisation.office.domain.OfficeRepository;
import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionEnumData; import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionEnumData;
@@ -63,6 +64,8 @@ public class AccountingProcessorHelper {
final Long loanId = (Long) accountingBridgeData.get("loanId"); final Long loanId = (Long) accountingBridgeData.get("loanId");
final Long loanProductId = (Long) accountingBridgeData.get("loanProductId"); final Long loanProductId = (Long) accountingBridgeData.get("loanProductId");
final Long officeId = (Long) accountingBridgeData.get("officeId"); final Long officeId = (Long) accountingBridgeData.get("officeId");
final CurrencyData currencyData = (CurrencyData) accountingBridgeData.get("currency");
final List<LoanTransactionDTO> newLoanTransactions = new ArrayList<LoanTransactionDTO>(); final List<LoanTransactionDTO> newLoanTransactions = new ArrayList<LoanTransactionDTO>();
@SuppressWarnings("unchecked") @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, 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 loanId = (Long) accountingBridgeData.get("savingsId");
final Long loanProductId = (Long) accountingBridgeData.get("savingsProductId"); final Long loanProductId = (Long) accountingBridgeData.get("savingsProductId");
final Long officeId = (Long) accountingBridgeData.get("officeId"); final Long officeId = (Long) accountingBridgeData.get("officeId");
final CurrencyData currencyData = (CurrencyData) accountingBridgeData.get("currency");
final List<SavingsTransactionDTO> newSavingsTransactions = new ArrayList<SavingsTransactionDTO>(); final List<SavingsTransactionDTO> newSavingsTransactions = new ArrayList<SavingsTransactionDTO>();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@@ -137,8 +142,8 @@ public class AccountingProcessorHelper {
} }
return new SavingsDTO(loanId, loanProductId, officeId, cashBasedAccountingEnabled, accrualBasedAccountingEnabled, return new SavingsDTO(loanId, loanProductId, officeId, currencyData.code(), cashBasedAccountingEnabled,
newSavingsTransactions); accrualBasedAccountingEnabled, newSavingsTransactions);
} }
/** /**
@@ -161,7 +166,7 @@ public class AccountingProcessorHelper {
* @param amount * @param amount
* @param isReversal * @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 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 Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate,
final BigDecimal amount, final Boolean isReversal) { final BigDecimal amount, final Boolean isReversal) {
@@ -172,8 +177,8 @@ public class AccountingProcessorHelper {
accountTypeToDebitId = accountTypeToBeCredited.getValue(); accountTypeToDebitId = accountTypeToBeCredited.getValue();
accountTypeToCreditId = accountTypeToBeDebited.getValue(); accountTypeToCreditId = accountTypeToBeDebited.getValue();
} }
createJournalEntriesForLoan(office, accountTypeToDebitId, accountTypeToCreditId, loanProductId, paymentTypeId, loanId, createJournalEntriesForLoan(office, currencyCode, accountTypeToDebitId, accountTypeToCreditId, loanProductId, paymentTypeId,
transactionId, transactionDate, amount); loanId, transactionId, transactionDate, amount);
} }
/** /**
@@ -196,7 +201,7 @@ public class AccountingProcessorHelper {
* @param amount * @param amount
* @param isReversal * @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 CASH_ACCOUNTS_FOR_SAVINGS accountTypeToBeDebited, final CASH_ACCOUNTS_FOR_SAVINGS accountTypeToBeCredited,
final Long savingsProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Long savingsProductId, final Long paymentTypeId, final Long loanId, final String transactionId,
final Date transactionDate, final BigDecimal amount, final Boolean isReversal) { final Date transactionDate, final BigDecimal amount, final Boolean isReversal) {
@@ -207,8 +212,8 @@ public class AccountingProcessorHelper {
accountTypeToDebitId = accountTypeToBeCredited.getValue(); accountTypeToDebitId = accountTypeToBeCredited.getValue();
accountTypeToCreditId = accountTypeToBeDebited.getValue(); accountTypeToCreditId = accountTypeToBeDebited.getValue();
} }
createJournalEntriesForSavings(office, accountTypeToDebitId, accountTypeToCreditId, savingsProductId, paymentTypeId, loanId, createJournalEntriesForSavings(office, currencyCode, accountTypeToDebitId, accountTypeToCreditId, savingsProductId, paymentTypeId,
transactionId, transactionDate, amount); loanId, transactionId, transactionDate, amount);
} }
/** /**
@@ -231,9 +236,10 @@ public class AccountingProcessorHelper {
* @param amount * @param amount
* @param isReversal * @param isReversal
*/ */
public void createCashBasedJournalEntriesAndReversalsForLoan(final Office office, final CASH_ACCOUNTS_FOR_LOAN accountTypeToBeDebited, public void createCashBasedJournalEntriesAndReversalsForLoan(final Office office, final String currencyCode,
final CASH_ACCOUNTS_FOR_LOAN accountTypeToBeCredited, final Long loanProductId, final Long paymentTypeId, final Long loanId, final CASH_ACCOUNTS_FOR_LOAN accountTypeToBeDebited, final CASH_ACCOUNTS_FOR_LOAN accountTypeToBeCredited,
final String transactionId, final Date transactionDate, final BigDecimal amount, final Boolean isReversal) { 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 accountTypeToDebitId = accountTypeToBeDebited.getValue();
int accountTypeToCreditId = accountTypeToBeCredited.getValue(); int accountTypeToCreditId = accountTypeToBeCredited.getValue();
// reverse debits and credits for reversals // reverse debits and credits for reversals
@@ -241,40 +247,40 @@ public class AccountingProcessorHelper {
accountTypeToDebitId = accountTypeToBeCredited.getValue(); accountTypeToDebitId = accountTypeToBeCredited.getValue();
accountTypeToCreditId = accountTypeToBeDebited.getValue(); accountTypeToCreditId = accountTypeToBeDebited.getValue();
} }
createJournalEntriesForLoan(office, accountTypeToDebitId, accountTypeToCreditId, loanProductId, paymentTypeId, loanId, createJournalEntriesForLoan(office, currencyCode, accountTypeToDebitId, accountTypeToCreditId, loanProductId, paymentTypeId,
transactionId, transactionDate, amount); loanId, transactionId, transactionDate, amount);
} }
public void createCreditJournalEntryOrReversalForLoan(final Office office, final CASH_ACCOUNTS_FOR_LOAN accountMappingType, public void createCreditJournalEntryOrReversalForLoan(final Office office, final String currencyCode,
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate, final CASH_ACCOUNTS_FOR_LOAN accountMappingType, final Long loanProductId, final Long paymentTypeId, final Long loanId,
final BigDecimal amount, final Boolean isReversal) { final String transactionId, final Date transactionDate, final BigDecimal amount, final Boolean isReversal) {
int accountMappingTypeId = accountMappingType.getValue(); int accountMappingTypeId = accountMappingType.getValue();
createCreditJournalEntryOrReversalForLoan(office, accountMappingTypeId, loanProductId, paymentTypeId, loanId, transactionId, createCreditJournalEntryOrReversalForLoan(office, currencyCode, accountMappingTypeId, loanProductId, paymentTypeId, loanId,
transactionDate, amount, isReversal); transactionId, transactionDate, amount, isReversal);
} }
public void createCreditJournalEntryOrReversalForLoan(final Office office, final ACCRUAL_ACCOUNTS_FOR_LOAN accountMappingType, public void createCreditJournalEntryOrReversalForLoan(final Office office, final String currencyCode,
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate, final ACCRUAL_ACCOUNTS_FOR_LOAN accountMappingType, final Long loanProductId, final Long paymentTypeId, final Long loanId,
final BigDecimal amount, final Boolean isReversal) { final String transactionId, final Date transactionDate, final BigDecimal amount, final Boolean isReversal) {
int accountMappingTypeId = accountMappingType.getValue(); int accountMappingTypeId = accountMappingType.getValue();
createCreditJournalEntryOrReversalForLoan(office, accountMappingTypeId, loanProductId, paymentTypeId, loanId, transactionId, createCreditJournalEntryOrReversalForLoan(office, currencyCode, accountMappingTypeId, loanProductId, paymentTypeId, loanId,
transactionDate, amount, isReversal); transactionId, transactionDate, amount, isReversal);
} }
public void createDebitJournalEntryOrReversalForLoan(final Office office, final CASH_ACCOUNTS_FOR_LOAN accountMappingType, public void createDebitJournalEntryOrReversalForLoan(final Office office, final String currencyCode,
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate, final CASH_ACCOUNTS_FOR_LOAN accountMappingType, final Long loanProductId, final Long paymentTypeId, final Long loanId,
final BigDecimal amount, final Boolean isReversal) { final String transactionId, final Date transactionDate, final BigDecimal amount, final Boolean isReversal) {
int accountMappingTypeId = accountMappingType.getValue(); int accountMappingTypeId = accountMappingType.getValue();
createDebitJournalEntryOrReversalForLoan(office, accountMappingTypeId, loanProductId, paymentTypeId, loanId, transactionId, createDebitJournalEntryOrReversalForLoan(office, currencyCode, accountMappingTypeId, loanProductId, paymentTypeId, loanId,
transactionDate, amount, isReversal); transactionId, transactionDate, amount, isReversal);
} }
public void createDebitJournalEntryOrReversalForLoan(final Office office, final ACCRUAL_ACCOUNTS_FOR_LOAN accountMappingType, public void createDebitJournalEntryOrReversalForLoan(final Office office, final String currencyCode,
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate, final ACCRUAL_ACCOUNTS_FOR_LOAN accountMappingType, final Long loanProductId, final Long paymentTypeId, final Long loanId,
final BigDecimal amount, final Boolean isReversal) { final String transactionId, final Date transactionDate, final BigDecimal amount, final Boolean isReversal) {
int accountMappingTypeId = accountMappingType.getValue(); int accountMappingTypeId = accountMappingType.getValue();
createDebitJournalEntryOrReversalForLoan(office, accountMappingTypeId, loanProductId, paymentTypeId, loanId, transactionId, createDebitJournalEntryOrReversalForLoan(office, currencyCode, accountMappingTypeId, loanProductId, paymentTypeId, loanId,
transactionDate, amount, isReversal); transactionId, transactionDate, amount, isReversal);
} }
/** /**
@@ -300,38 +306,39 @@ public class AccountingProcessorHelper {
return this.officeRepository.findOne(officeId); return this.officeRepository.findOne(officeId);
} }
private void createJournalEntriesForLoan(final Office office, final int accountTypeToDebitId, final int accountTypeToCreditId, private void createJournalEntriesForLoan(final Office office, final String currencyCode, final int accountTypeToDebitId,
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate, final int accountTypeToCreditId, final Long loanProductId, final Long paymentTypeId, final Long loanId,
final BigDecimal amount) { final String transactionId, final Date transactionDate, final BigDecimal amount) {
GLAccount debitAccount = getLinkedGLAccountForLoanProduct(loanProductId, accountTypeToDebitId, paymentTypeId); GLAccount debitAccount = getLinkedGLAccountForLoanProduct(loanProductId, accountTypeToDebitId, paymentTypeId);
GLAccount creditAccount = getLinkedGLAccountForLoanProduct(loanProductId, accountTypeToCreditId, paymentTypeId); GLAccount creditAccount = getLinkedGLAccountForLoanProduct(loanProductId, accountTypeToCreditId, paymentTypeId);
createDebitJournalEntryForLoan(office, debitAccount, loanId, transactionId, transactionDate, amount); createDebitJournalEntryForLoan(office, currencyCode, debitAccount, loanId, transactionId, transactionDate, amount);
createCreditJournalEntryForLoan(office, creditAccount, loanId, transactionId, transactionDate, amount); createCreditJournalEntryForLoan(office, currencyCode, creditAccount, loanId, transactionId, transactionDate, amount);
} }
private void createJournalEntriesForSavings(final Office office, final int accountTypeToDebitId, final int accountTypeToCreditId, private void createJournalEntriesForSavings(final Office office, final String currencyCode, final int accountTypeToDebitId,
final Long savingsProductId, final Long paymentTypeId, final Long savingsId, final String transactionId, final int accountTypeToCreditId, final Long savingsProductId, final Long paymentTypeId, final Long savingsId,
final Date transactionDate, final BigDecimal amount) { final String transactionId, final Date transactionDate, final BigDecimal amount) {
GLAccount debitAccount = getLinkedGLAccountForSavingsProduct(savingsProductId, accountTypeToDebitId, paymentTypeId); GLAccount debitAccount = getLinkedGLAccountForSavingsProduct(savingsProductId, accountTypeToDebitId, paymentTypeId);
GLAccount creditAccount = getLinkedGLAccountForSavingsProduct(savingsProductId, accountTypeToCreditId, paymentTypeId); GLAccount creditAccount = getLinkedGLAccountForSavingsProduct(savingsProductId, accountTypeToCreditId, paymentTypeId);
createDebitJournalEntryForSavings(office, debitAccount, savingsId, transactionId, transactionDate, amount); createDebitJournalEntryForSavings(office, currencyCode, debitAccount, savingsId, transactionId, transactionDate, amount);
createCreditJournalEntryForSavings(office, creditAccount, savingsId, transactionId, transactionDate, amount); createCreditJournalEntryForSavings(office, currencyCode, creditAccount, savingsId, transactionId, transactionDate, amount);
} }
private void createDebitJournalEntryOrReversalForLoan(final Office office, final int accountMappingTypeId, final Long loanProductId, private void createDebitJournalEntryOrReversalForLoan(final Office office, final String currencyCode, final int accountMappingTypeId,
final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate, final BigDecimal amount, final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate,
final Boolean isReversal) { final BigDecimal amount, final Boolean isReversal) {
GLAccount account = getLinkedGLAccountForLoanProduct(loanProductId, accountMappingTypeId, paymentTypeId); GLAccount account = getLinkedGLAccountForLoanProduct(loanProductId, accountMappingTypeId, paymentTypeId);
if (isReversal) { if (isReversal) {
createCreditJournalEntryForLoan(office, account, loanId, transactionId, transactionDate, amount); createCreditJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
} else { } 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, public void createCreditJournalEntryOrReversalForLoanCharges(final Office office, final String currencyCode,
final Long loanProductId, final Long loanId, final String transactionId, final Date transactionDate, final int accountMappingTypeId, final Long loanProductId, final Long loanId, final String transactionId,
final BigDecimal totalAmount, final Boolean isReversal, final List<ChargePaymentDTO> chargePaymentDTOs) { 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 * Map to track each account and the net credit to be made for a
* particular account * particular account
@@ -357,9 +364,9 @@ public class AccountingProcessorHelper {
BigDecimal amount = entry.getValue(); BigDecimal amount = entry.getValue();
totalCreditedAmount = totalCreditedAmount.add(amount); totalCreditedAmount = totalCreditedAmount.add(amount);
if (isReversal) { if (isReversal) {
createDebitJournalEntryForLoan(office, account, loanId, transactionId, transactionDate, amount); createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
} else { } 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); } totalCreditedAmount, totalAmount); }
} }
private void createCreditJournalEntryOrReversalForLoan(final Office office, final int accountMappingTypeId, final Long loanProductId, private void createCreditJournalEntryOrReversalForLoan(final Office office, final String currencyCode, final int accountMappingTypeId,
final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate, final BigDecimal amount, final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate,
final Boolean isReversal) { final BigDecimal amount, final Boolean isReversal) {
GLAccount account = getLinkedGLAccountForLoanProduct(loanProductId, accountMappingTypeId, paymentTypeId); GLAccount account = getLinkedGLAccountForLoanProduct(loanProductId, accountMappingTypeId, paymentTypeId);
if (isReversal) { if (isReversal) {
createDebitJournalEntryForLoan(office, account, loanId, transactionId, transactionDate, amount); createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
} else { } 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, private void createCreditJournalEntryForLoan(final Office office, final String currencyCode, final GLAccount account,
final String transactionId, final Date transactionDate, final BigDecimal amount) { final Long loanId, final String transactionId, final Date transactionDate, final BigDecimal amount) {
final boolean manualEntry = false; final boolean manualEntry = false;
final JournalEntry journalEntry = JournalEntry.createNew(office, account, transactionId, manualEntry, transactionDate, final JournalEntry journalEntry = JournalEntry.createNew(office, account, currencyCode, transactionId, manualEntry,
JournalEntryType.CREDIT, amount, null, PortfolioProductType.LOAN.getValue(), loanId, null); transactionDate, JournalEntryType.CREDIT, amount, null, PortfolioProductType.LOAN.getValue(), loanId, null);
this.glJournalEntryRepository.saveAndFlush(journalEntry); this.glJournalEntryRepository.saveAndFlush(journalEntry);
} }
private void createCreditJournalEntryForSavings(final Office office, final GLAccount account, final Long savingsId, private void createCreditJournalEntryForSavings(final Office office, final String currencyCode, final GLAccount account,
final String transactionId, final Date transactionDate, final BigDecimal amount) { final Long savingsId, final String transactionId, final Date transactionDate, final BigDecimal amount) {
final boolean manualEntry = false; final boolean manualEntry = false;
final JournalEntry journalEntry = JournalEntry.createNew(office, account, transactionId, manualEntry, transactionDate, final JournalEntry journalEntry = JournalEntry.createNew(office, account, currencyCode, transactionId, manualEntry,
JournalEntryType.CREDIT, amount, null, PortfolioProductType.SAVING.getValue(), savingsId, null); transactionDate, JournalEntryType.CREDIT, amount, null, PortfolioProductType.SAVING.getValue(), savingsId, null);
this.glJournalEntryRepository.saveAndFlush(journalEntry); 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 String transactionId, final Date transactionDate, final BigDecimal amount) {
final boolean manualEntry = false; final boolean manualEntry = false;
final JournalEntry journalEntry = JournalEntry.createNew(office, account, transactionId, manualEntry, transactionDate, final JournalEntry journalEntry = JournalEntry.createNew(office, account, currencyCode, transactionId, manualEntry,
JournalEntryType.DEBIT, amount, null, PortfolioProductType.LOAN.getValue(), loanId, null); transactionDate, JournalEntryType.DEBIT, amount, null, PortfolioProductType.LOAN.getValue(), loanId, null);
this.glJournalEntryRepository.saveAndFlush(journalEntry); this.glJournalEntryRepository.saveAndFlush(journalEntry);
} }
private void createDebitJournalEntryForSavings(final Office office, final GLAccount account, final Long savingsId, private void createDebitJournalEntryForSavings(final Office office, final String currencyCode, final GLAccount account,
final String transactionId, final Date transactionDate, final BigDecimal amount) { final Long savingsId, final String transactionId, final Date transactionDate, final BigDecimal amount) {
final boolean manualEntry = false; final boolean manualEntry = false;
final JournalEntry journalEntry = JournalEntry.createNew(office, account, transactionId, manualEntry, transactionDate, final JournalEntry journalEntry = JournalEntry.createNew(office, account, currencyCode, transactionId, manualEntry,
JournalEntryType.DEBIT, amount, null, PortfolioProductType.SAVING.getValue(), savingsId, null); transactionDate, JournalEntryType.DEBIT, amount, null, PortfolioProductType.SAVING.getValue(), savingsId, null);
this.glJournalEntryRepository.saveAndFlush(journalEntry); this.glJournalEntryRepository.saveAndFlush(journalEntry);
} }
@@ -80,6 +80,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// loan properties // loan properties
final Long loanProductId = loanDTO.getLoanProductId(); final Long loanProductId = loanDTO.getLoanProductId();
final Long loanId = loanDTO.getLoanId(); final Long loanId = loanDTO.getLoanId();
final String currencyCode = loanDTO.getCurrencyCode();
// transaction properties // transaction properties
final String transactionId = loanTransactionDTO.getTransactionId(); final String transactionId = loanTransactionDTO.getTransactionId();
@@ -90,7 +91,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// create journal entries for the disbursement (or disbursement // create journal entries for the disbursement (or disbursement
// reversal) // 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, ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE, loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
disbursalAmount, isReversed); disbursalAmount, isReversed);
@@ -110,6 +111,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// loan properties // loan properties
final Long loanProductId = loanDTO.getLoanProductId(); final Long loanProductId = loanDTO.getLoanProductId();
final Long loanId = loanDTO.getLoanId(); final Long loanId = loanDTO.getLoanId();
final String currencyCode = loanDTO.getCurrencyCode();
// transaction properties // transaction properties
final String transactionId = loanTransactionDTO.getTransactionId(); final String transactionId = loanTransactionDTO.getTransactionId();
@@ -120,7 +122,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// create journal entries for recognising interest (or reversal) // create journal entries for recognising interest (or reversal)
if (amount != null && !(amount.compareTo(BigDecimal.ZERO) == 0)) { 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, ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS, loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
amount, isReversed); amount, isReversed);
} }
@@ -172,6 +174,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// loan properties // loan properties
final Long loanProductId = loanDTO.getLoanProductId(); final Long loanProductId = loanDTO.getLoanProductId();
final Long loanId = loanDTO.getLoanId(); final Long loanId = loanDTO.getLoanId();
final String currencyCode = loanDTO.getCurrencyCode();
// transaction properties // transaction properties
final String transactionId = loanTransactionDTO.getTransactionId(); final String transactionId = loanTransactionDTO.getTransactionId();
@@ -188,15 +191,15 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// handle principal payment or writeOff (and reversals) // handle principal payment or writeOff (and reversals)
if (principalAmount != null && !(principalAmount.compareTo(BigDecimal.ZERO) == 0)) { if (principalAmount != null && !(principalAmount.compareTo(BigDecimal.ZERO) == 0)) {
totalDebitAmount = totalDebitAmount.add(principalAmount); 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); paymentTypeId, loanId, transactionId, transactionDate, principalAmount, isReversal);
} }
// handle interest payment of writeOff (and reversals) // handle interest payment of writeOff (and reversals)
if (interestAmount != null && !(interestAmount.compareTo(BigDecimal.ZERO) == 0)) { if (interestAmount != null && !(interestAmount.compareTo(BigDecimal.ZERO) == 0)) {
totalDebitAmount = totalDebitAmount.add(interestAmount); totalDebitAmount = totalDebitAmount.add(interestAmount);
helper.createCreditJournalEntryOrReversalForLoan(office, ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE, loanProductId, helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE,
paymentTypeId, loanId, transactionId, transactionDate, interestAmount, isReversal); loanProductId, paymentTypeId, loanId, transactionId, transactionDate, interestAmount, isReversal);
} }
// handle fees payment of writeOff (and reversals) // handle fees payment of writeOff (and reversals)
@@ -209,15 +212,15 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
feeAccountToCredit = ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES; feeAccountToCredit = ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES;
} }
helper.createCreditJournalEntryOrReversalForLoan(office, feeAccountToCredit, loanProductId, paymentTypeId, loanId, helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, feeAccountToCredit, loanProductId, paymentTypeId,
transactionId, transactionDate, feesAmount, isReversal); loanId, transactionId, transactionDate, feesAmount, isReversal);
} }
// handle penalties payment of writeOff (and reversals) // handle penalties payment of writeOff (and reversals)
if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) { if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) {
totalDebitAmount = totalDebitAmount.add(penaltiesAmount); totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
helper.createCreditJournalEntryOrReversalForLoan(office, ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE, loanProductId, helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE,
paymentTypeId, loanId, transactionId, transactionDate, penaltiesAmount, isReversal); loanProductId, paymentTypeId, loanId, transactionId, transactionDate, penaltiesAmount, isReversal);
} }
/** /**
@@ -225,11 +228,11 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
* reversals) * reversals)
***/ ***/
if (writeOff) { if (writeOff) {
helper.createDebitJournalEntryOrReversalForLoan(office, ACCRUAL_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF, loanProductId, helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF,
paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal); loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
} else { } else {
helper.createDebitJournalEntryOrReversalForLoan(office, ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE, loanProductId, paymentTypeId, helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE, loanProductId,
loanId, transactionId, transactionDate, totalDebitAmount, isReversal); paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
} }
} }
@@ -254,6 +257,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// loan properties // loan properties
final Long loanProductId = loanDTO.getLoanProductId(); final Long loanProductId = loanDTO.getLoanProductId();
final Long loanId = loanDTO.getLoanId(); final Long loanId = loanDTO.getLoanId();
final String currencyCode = loanDTO.getCurrencyCode();
// transaction properties // transaction properties
final String transactionId = loanTransactionDTO.getTransactionId(); final String transactionId = loanTransactionDTO.getTransactionId();
@@ -265,15 +269,15 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// create journal entries for the fees application (or reversal) // create journal entries for the fees application (or reversal)
if (feesAmount != null && !(feesAmount.compareTo(BigDecimal.ZERO) == 0)) { 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, ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES, loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
feesAmount, isReversed); feesAmount, isReversed);
} }
// create journal entries for the penalties application (or reversal) // create journal entries for the penalties application (or reversal)
else if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) { else if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) {
helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE, helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES, loanProductId, paymentTypeId, loanId, transactionId, transactionDate, ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE, ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES, loanProductId,
penaltiesAmount, isReversed); paymentTypeId, loanId, transactionId, transactionDate, penaltiesAmount, isReversed);
} }
} }
} }
@@ -32,6 +32,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
// final Office office = // final Office office =
// this.helper.getOfficeById(loanDTO.getOfficeId()); // this.helper.getOfficeById(loanDTO.getOfficeId());
final Long loanProductId = loanDTO.getLoanProductId(); final Long loanProductId = loanDTO.getLoanProductId();
final String currencyCode = loanDTO.getCurrencyCode();
for (final LoanTransactionDTO loanTransactionDTO : loanDTO.getNewLoanTransactions()) { for (final LoanTransactionDTO loanTransactionDTO : loanDTO.getNewLoanTransactions()) {
final Date transactionDate = loanTransactionDTO.getTransactionDate(); final Date transactionDate = loanTransactionDTO.getTransactionDate();
final String transactionId = loanTransactionDTO.getTransactionId(); final String transactionId = loanTransactionDTO.getTransactionId();
@@ -60,7 +61,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
**/ **/
else if (loanTransactionDTO.getTransactionType().isWriteOff() && !loanTransactionDTO.isReversed()) { else if (loanTransactionDTO.getTransactionType().isWriteOff() && !loanTransactionDTO.isReversed()) {
final BigDecimal principalAmount = loanTransactionDTO.getPrincipal(); 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, CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO, loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
principalAmount, false); principalAmount, false);
} else if (loanTransactionDTO.getTransactionType().isInitiateTransfer() } else if (loanTransactionDTO.getTransactionType().isInitiateTransfer()
@@ -87,6 +88,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
// loan properties // loan properties
final Long loanProductId = loanDTO.getLoanProductId(); final Long loanProductId = loanDTO.getLoanProductId();
final Long loanId = loanDTO.getLoanId(); final Long loanId = loanDTO.getLoanId();
final String currencyCode = loanDTO.getCurrencyCode();
// transaction properties // transaction properties
final String transactionId = loanTransactionDTO.getTransactionId(); final String transactionId = loanTransactionDTO.getTransactionId();
@@ -95,7 +97,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
final boolean isReversal = loanTransactionDTO.isReversed(); final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId(); 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, CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE, loanProductId, paymentTypeId, loanId, transactionId, transactionDate, disbursalAmount,
isReversal); isReversal);
} }
@@ -113,6 +115,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
// loan properties // loan properties
final Long loanProductId = loanDTO.getLoanProductId(); final Long loanProductId = loanDTO.getLoanProductId();
final Long loanId = loanDTO.getLoanId(); final Long loanId = loanDTO.getLoanId();
final String currencyCode = loanDTO.getCurrencyCode();
// transaction properties // transaction properties
final String transactionId = loanTransactionDTO.getTransactionId(); final String transactionId = loanTransactionDTO.getTransactionId();
@@ -128,32 +131,33 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
if (principalAmount != null && !(principalAmount.compareTo(BigDecimal.ZERO) == 0)) { if (principalAmount != null && !(principalAmount.compareTo(BigDecimal.ZERO) == 0)) {
totalDebitAmount = totalDebitAmount.add(principalAmount); totalDebitAmount = totalDebitAmount.add(principalAmount);
helper.createCreditJournalEntryOrReversalForLoan(office, CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO, loanProductId, paymentTypeId, helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO, loanProductId,
loanId, transactionId, transactionDate, principalAmount, isReversal); paymentTypeId, loanId, transactionId, transactionDate, principalAmount, isReversal);
} }
if (interestAmount != null && !(interestAmount.compareTo(BigDecimal.ZERO) == 0)) { if (interestAmount != null && !(interestAmount.compareTo(BigDecimal.ZERO) == 0)) {
totalDebitAmount = totalDebitAmount.add(interestAmount); 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); paymentTypeId, loanId, transactionId, transactionDate, interestAmount, isReversal);
} }
if (feesAmount != null && !(feesAmount.compareTo(BigDecimal.ZERO) == 0)) { if (feesAmount != null && !(feesAmount.compareTo(BigDecimal.ZERO) == 0)) {
totalDebitAmount = totalDebitAmount.add(feesAmount); totalDebitAmount = totalDebitAmount.add(feesAmount);
helper.createCreditJournalEntryOrReversalForLoanCharges(office, CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue(), helper.createCreditJournalEntryOrReversalForLoanCharges(office, currencyCode,
loanProductId, loanId, transactionId, transactionDate, feesAmount, isReversal, loanTransactionDTO.getFeePayments()); CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue(), loanProductId, loanId, transactionId, transactionDate, feesAmount,
isReversal, loanTransactionDTO.getFeePayments());
} }
if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) { if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) {
totalDebitAmount = totalDebitAmount.add(penaltiesAmount); totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
helper.createCreditJournalEntryOrReversalForLoanCharges(office, CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue(), helper.createCreditJournalEntryOrReversalForLoanCharges(office, currencyCode,
loanProductId, loanId, transactionId, transactionDate, penaltiesAmount, isReversal, CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue(), loanProductId, loanId, transactionId, transactionDate,
loanTransactionDTO.getPenaltyPayments()); penaltiesAmount, isReversal, loanTransactionDTO.getPenaltyPayments());
} }
/*** create a single debit entry (or reversal) for the entire amount **/ /*** create a single debit entry (or reversal) for the entire amount **/
helper.createDebitJournalEntryOrReversalForLoan(office, CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE, loanProductId, paymentTypeId, loanId, helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE, loanProductId,
transactionId, transactionDate, totalDebitAmount, isReversal); paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
} }
/** /**
@@ -173,6 +177,7 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
// loan properties // loan properties
final Long loanProductId = loanDTO.getLoanProductId(); final Long loanProductId = loanDTO.getLoanProductId();
final Long loanId = loanDTO.getLoanId(); final Long loanId = loanDTO.getLoanId();
final String currencyCode = loanDTO.getCurrencyCode();
// transaction properties // transaction properties
final String transactionId = loanTransactionDTO.getTransactionId(); final String transactionId = loanTransactionDTO.getTransactionId();
@@ -182,12 +187,12 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
// final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId(); // final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
if (loanTransactionDTO.getTransactionType().isInitiateTransfer()) { 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, CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO, loanProductId, null, loanId, transactionId, transactionDate, principalAmount,
isReversal); isReversal);
} else if (loanTransactionDTO.getTransactionType().isApproveTransfer() } else if (loanTransactionDTO.getTransactionType().isApproveTransfer()
|| loanTransactionDTO.getTransactionType().isWithdrawTransfer()) { || 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, CASH_ACCOUNTS_FOR_LOAN.TRANSFERS_SUSPENSE, loanProductId, null, loanId, transactionId, transactionDate,
principalAmount, isReversal); principalAmount, isReversal);
} }
@@ -31,6 +31,7 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
final GLClosure latestGLClosure = this.helper.getLatestClosureByBranch(savingsDTO.getOfficeId()); final GLClosure latestGLClosure = this.helper.getLatestClosureByBranch(savingsDTO.getOfficeId());
final Long savingsProductId = savingsDTO.getSavingsProductId(); final Long savingsProductId = savingsDTO.getSavingsProductId();
final Long savingsId = savingsDTO.getSavingsId(); final Long savingsId = savingsDTO.getSavingsId();
final String currencyCode = savingsDTO.getCurrencyCode();
for (final SavingsTransactionDTO savingsTransactionDTO : savingsDTO.getNewSavingsTransactions()) { for (final SavingsTransactionDTO savingsTransactionDTO : savingsDTO.getNewSavingsTransactions()) {
final Date transactionDate = savingsTransactionDTO.getTransactionDate(); final Date transactionDate = savingsTransactionDTO.getTransactionDate();
final String transactionId = savingsTransactionDTO.getTransactionId(); final String transactionId = savingsTransactionDTO.getTransactionId();
@@ -43,14 +44,14 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
/** Handle Deposits and reversals of deposits **/ /** Handle Deposits and reversals of deposits **/
if (savingsTransactionDTO.getTransactionType().isDeposit()) { if (savingsTransactionDTO.getTransactionType().isDeposit()) {
helper.createCashBasedJournalEntriesAndReversalsForSavings(office, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId, paymentTypeId, savingsId, transactionId, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId,
transactionDate, amount, isReversal); paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
} }
/** Handle withdrawals and reversals of withdrawals **/ /** Handle withdrawals and reversals of withdrawals **/
else if (savingsTransactionDTO.getTransactionType().isWithdrawal()) { 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, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, savingsProductId, paymentTypeId, savingsId, transactionId,
transactionDate, amount, isReversal); transactionDate, amount, isReversal);
} }
@@ -60,21 +61,21 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
* Applications * Applications
**/ **/
else if (savingsTransactionDTO.getTransactionType().isInterestPosting()) { else if (savingsTransactionDTO.getTransactionType().isInterestPosting()) {
helper.createCashBasedJournalEntriesAndReversalsForSavings(office, CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS, helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId, paymentTypeId, savingsId, transactionId, CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId,
transactionDate, amount, isReversal); paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
} }
/** Handle Fees Deductions and reversals of Fees Deductions **/ /** Handle Fees Deductions and reversals of Fees Deductions **/
else if (savingsTransactionDTO.getTransactionType().isFeeDeduction()) { 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, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_FEES, savingsProductId, paymentTypeId, savingsId, transactionId,
transactionDate, amount, isReversal); transactionDate, amount, isReversal);
} }
/** Handle Transfers proposal **/ /** Handle Transfers proposal **/
else if (savingsTransactionDTO.getTransactionType().isInitiateTransfer()) { 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, CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE, savingsProductId, paymentTypeId, savingsId, transactionId,
transactionDate, amount, isReversal); transactionDate, amount, isReversal);
} }
@@ -82,9 +83,9 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
/** Handle Transfer Withdrawal or Acceptance **/ /** Handle Transfer Withdrawal or Acceptance **/
else if (savingsTransactionDTO.getTransactionType().isWithdrawTransfer() else if (savingsTransactionDTO.getTransactionType().isWithdrawTransfer()
|| savingsTransactionDTO.getTransactionType().isApproveTransfer()) { || savingsTransactionDTO.getTransactionType().isApproveTransfer()) {
helper.createCashBasedJournalEntriesAndReversalsForSavings(office, CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE, helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId, paymentTypeId, savingsId, transactionId, CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId,
transactionDate, amount, isReversal); 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.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.organisation.office.domain.Office; import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.office.domain.OfficeRepository; import org.mifosplatform.organisation.office.domain.OfficeRepository;
import org.mifosplatform.organisation.office.domain.OrganisationCurrencyRepositoryWrapper;
import org.mifosplatform.organisation.office.exception.OfficeNotFoundException; import org.mifosplatform.organisation.office.exception.OfficeNotFoundException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -65,6 +66,7 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
private final JournalEntryCommandFromApiJsonDeserializer fromApiJsonDeserializer; private final JournalEntryCommandFromApiJsonDeserializer fromApiJsonDeserializer;
private final AccountingRuleRepository accountingRuleRepository; private final AccountingRuleRepository accountingRuleRepository;
private final GLAccountReadPlatformService glAccountReadPlatformService; private final GLAccountReadPlatformService glAccountReadPlatformService;
private final OrganisationCurrencyRepositoryWrapper organisationCurrencyRepository;
@Autowired @Autowired
public JournalEntryWritePlatformServiceJpaRepositoryImpl(final GLClosureRepository glClosureRepository, public JournalEntryWritePlatformServiceJpaRepositoryImpl(final GLClosureRepository glClosureRepository,
@@ -73,7 +75,8 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
final AccountingProcessorHelper accountingProcessorHelper, final AccountingRuleRepository accountingRuleRepository, final AccountingProcessorHelper accountingProcessorHelper, final AccountingRuleRepository accountingRuleRepository,
final AccountingProcessorForLoanFactory accountingProcessorForLoanFactory, final AccountingProcessorForLoanFactory accountingProcessorForLoanFactory,
final AccountingProcessorForSavingsFactory accountingProcessorForSavingsFactory, final AccountingProcessorForSavingsFactory accountingProcessorForSavingsFactory,
final GLAccountReadPlatformService glAccountReadPlatformService) { final GLAccountReadPlatformService glAccountReadPlatformService,
final OrganisationCurrencyRepositoryWrapper organisationCurrencyRepository) {
this.glClosureRepository = glClosureRepository; this.glClosureRepository = glClosureRepository;
this.officeRepository = officeRepository; this.officeRepository = officeRepository;
this.glJournalEntryRepository = glJournalEntryRepository; this.glJournalEntryRepository = glJournalEntryRepository;
@@ -84,6 +87,7 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
this.helper = accountingProcessorHelper; this.helper = accountingProcessorHelper;
this.accountingRuleRepository = accountingRuleRepository; this.accountingRuleRepository = accountingRuleRepository;
this.glAccountReadPlatformService = glAccountReadPlatformService; this.glAccountReadPlatformService = glAccountReadPlatformService;
this.organisationCurrencyRepository = organisationCurrencyRepository;
} }
@Transactional @Transactional
@@ -99,6 +103,7 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
if (office == null) { throw new OfficeNotFoundException(officeId); } if (office == null) { throw new OfficeNotFoundException(officeId); }
final Long accountRuleId = command.longValueOfParameterNamed(JournalEntryJsonInputParams.ACCOUNTING_RULE.getValue()); final Long accountRuleId = command.longValueOfParameterNamed(JournalEntryJsonInputParams.ACCOUNTING_RULE.getValue());
final String currencyCode = command.stringValueOfParameterNamed(JournalEntryJsonInputParams.CURRENCY_CODE.getValue());
validateBusinessRulesForJournalEntries(journalEntryCommand); validateBusinessRulesForJournalEntries(journalEntryCommand);
@@ -121,14 +126,14 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
checkDebitAndCreditAmounts(journalEntryCommand.getCredits(), journalEntryCommand.getDebits()); checkDebitAndCreditAmounts(journalEntryCommand.getCredits(), journalEntryCommand.getDebits());
} }
saveAllDebitOrCreditEntries(journalEntryCommand, office, transactionDate, journalEntryCommand.getCredits(), saveAllDebitOrCreditEntries(journalEntryCommand, office, currencyCode, transactionDate,
transactionId, JournalEntryType.CREDIT, referenceNumber); journalEntryCommand.getCredits(), transactionId, JournalEntryType.CREDIT, referenceNumber);
} else { } else {
final GLAccount creditAccountHead = accountingRule.getAccountToCredit(); final GLAccount creditAccountHead = accountingRule.getAccountToCredit();
validateGLAccountForTransaction(creditAccountHead); validateGLAccountForTransaction(creditAccountHead);
validateDebitOrCreditArrayForExistingGLAccount(creditAccountHead,journalEntryCommand.getCredits()); validateDebitOrCreditArrayForExistingGLAccount(creditAccountHead, journalEntryCommand.getCredits());
saveAllDebitOrCreditEntries(journalEntryCommand, office, transactionDate, journalEntryCommand.getCredits(), saveAllDebitOrCreditEntries(journalEntryCommand, office, currencyCode, transactionDate,
transactionId, JournalEntryType.CREDIT, referenceNumber); journalEntryCommand.getCredits(), transactionId, JournalEntryType.CREDIT, referenceNumber);
} }
if (accountingRule.getAccountToDebit() == null) { if (accountingRule.getAccountToDebit() == null) {
@@ -140,22 +145,22 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
checkDebitAndCreditAmounts(journalEntryCommand.getCredits(), journalEntryCommand.getDebits()); checkDebitAndCreditAmounts(journalEntryCommand.getCredits(), journalEntryCommand.getDebits());
} }
saveAllDebitOrCreditEntries(journalEntryCommand, office, transactionDate, journalEntryCommand.getDebits(), saveAllDebitOrCreditEntries(journalEntryCommand, office, currencyCode, transactionDate,
transactionId, JournalEntryType.DEBIT, referenceNumber); journalEntryCommand.getDebits(), transactionId, JournalEntryType.DEBIT, referenceNumber);
} else { } else {
final GLAccount debitAccountHead = accountingRule.getAccountToDebit(); final GLAccount debitAccountHead = accountingRule.getAccountToDebit();
validateGLAccountForTransaction(debitAccountHead); validateGLAccountForTransaction(debitAccountHead);
validateDebitOrCreditArrayForExistingGLAccount(debitAccountHead,journalEntryCommand.getDebits()); validateDebitOrCreditArrayForExistingGLAccount(debitAccountHead, journalEntryCommand.getDebits());
saveAllDebitOrCreditEntries(journalEntryCommand, office, transactionDate, journalEntryCommand.getDebits(), saveAllDebitOrCreditEntries(journalEntryCommand, office, currencyCode, transactionDate,
transactionId, JournalEntryType.DEBIT, referenceNumber); journalEntryCommand.getDebits(), transactionId, JournalEntryType.DEBIT, referenceNumber);
} }
} else { } else {
saveAllDebitOrCreditEntries(journalEntryCommand, office, transactionDate, journalEntryCommand.getDebits(), transactionId, saveAllDebitOrCreditEntries(journalEntryCommand, office, currencyCode, transactionDate, journalEntryCommand.getDebits(),
JournalEntryType.DEBIT, referenceNumber); transactionId, JournalEntryType.DEBIT, referenceNumber);
saveAllDebitOrCreditEntries(journalEntryCommand, office, transactionDate, journalEntryCommand.getCredits(), transactionId, saveAllDebitOrCreditEntries(journalEntryCommand, office, currencyCode, transactionDate, journalEntryCommand.getCredits(),
JournalEntryType.CREDIT, referenceNumber); 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() final String reversalComment = "Reversal entry for Journal Entry with Entry Id :" + journalEntry.getId()
+ " and transaction Id " + command.getTransactionId(); + " and transaction Id " + command.getTransactionId();
if (journalEntry.isDebitEntry()) { if (journalEntry.isDebitEntry()) {
reversalJournalEntry = JournalEntry.createNew(journalEntry.getOffice(), journalEntry.getGlAccount(), reversalTransactionId, reversalJournalEntry = JournalEntry.createNew(journalEntry.getOffice(), journalEntry.getGlAccount(),
manualEntry, journalEntry.getTransactionDate(), JournalEntryType.CREDIT, journalEntry.getAmount(), reversalComment, journalEntry.getCurrencyCode(), reversalTransactionId, manualEntry, journalEntry.getTransactionDate(),
null, null, journalEntry.getReferenceNumber()); JournalEntryType.CREDIT, journalEntry.getAmount(), reversalComment, null, null, journalEntry.getReferenceNumber());
} else { } else {
reversalJournalEntry = JournalEntry.createNew(journalEntry.getOffice(), journalEntry.getGlAccount(), reversalTransactionId, reversalJournalEntry = JournalEntry.createNew(journalEntry.getOffice(), journalEntry.getGlAccount(),
manualEntry, journalEntry.getTransactionDate(), JournalEntryType.DEBIT, journalEntry.getAmount(), reversalComment, journalEntry.getCurrencyCode(), reversalTransactionId, manualEntry, journalEntry.getTransactionDate(),
null, null, journalEntry.getReferenceNumber()); JournalEntryType.DEBIT, journalEntry.getAmount(), reversalComment, null, null, journalEntry.getReferenceNumber());
} }
// save the reversal entry // save the reversal entry
this.glJournalEntryRepository.saveAndFlush(reversalJournalEntry); this.glJournalEntryRepository.saveAndFlush(reversalJournalEntry);
@@ -343,9 +348,9 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
checkDebitAndCreditAmounts(credits, debits); checkDebitAndCreditAmounts(credits, debits);
} }
private void saveAllDebitOrCreditEntries(final JournalEntryCommand command, final Office office, final Date transactionDate, private void saveAllDebitOrCreditEntries(final JournalEntryCommand command, final Office office, final String currencyCode,
final SingleDebitOrCreditEntryCommand[] singleDebitOrCreditEntryCommands, final String transactionId, final Date transactionDate, final SingleDebitOrCreditEntryCommand[] singleDebitOrCreditEntryCommands,
final JournalEntryType type, final String referenceNumber) { final String transactionId, final JournalEntryType type, final String referenceNumber) {
final boolean manualEntry = true; final boolean manualEntry = true;
for (final SingleDebitOrCreditEntryCommand singleDebitOrCreditEntryCommand : singleDebitOrCreditEntryCommands) { for (final SingleDebitOrCreditEntryCommand singleDebitOrCreditEntryCommand : singleDebitOrCreditEntryCommands) {
final GLAccount glAccount = this.glAccountRepository.findOne(singleDebitOrCreditEntryCommand.getGlAccountId()); final GLAccount glAccount = this.glAccountRepository.findOne(singleDebitOrCreditEntryCommand.getGlAccountId());
@@ -357,8 +362,12 @@ public class JournalEntryWritePlatformServiceJpaRepositoryImpl implements Journa
if (!StringUtils.isBlank(singleDebitOrCreditEntryCommand.getComments())) { if (!StringUtils.isBlank(singleDebitOrCreditEntryCommand.getComments())) {
comments = 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); 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.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface OrganisationCurrencyRepository extends JpaRepository<OrganisationCurrency, Long>, JpaSpecificationExecutor<OrganisationCurrency> { public interface OrganisationCurrencyRepository extends JpaRepository<OrganisationCurrency, Long>,
// no added behaviour 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("loanId", getId());
accountingBridgeData.put("loanProductId", productId()); accountingBridgeData.put("loanProductId", productId());
accountingBridgeData.put("officeId", getOfficeId()); accountingBridgeData.put("officeId", getOfficeId());
accountingBridgeData.put("currency", currencyData);
accountingBridgeData.put("calculatedInterest", this.summary.getTotalInterestCharged()); accountingBridgeData.put("calculatedInterest", this.summary.getTotalInterestCharged());
accountingBridgeData.put("cashBasedAccountingEnabled", isCashBasedAccountingEnabledOnLoanProduct()); accountingBridgeData.put("cashBasedAccountingEnabled", isCashBasedAccountingEnabledOnLoanProduct());
accountingBridgeData.put("accrualBasedAccountingEnabled", isAccrualBasedAccountingEnabledOnLoanProduct()); accountingBridgeData.put("accrualBasedAccountingEnabled", isAccrualBasedAccountingEnabledOnLoanProduct());
@@ -1161,6 +1161,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
final Map<String, Object> accountingBridgeData = new LinkedHashMap<String, Object>(); final Map<String, Object> accountingBridgeData = new LinkedHashMap<String, Object>();
accountingBridgeData.put("savingsId", getId()); accountingBridgeData.put("savingsId", getId());
accountingBridgeData.put("savingsProductId", productId()); accountingBridgeData.put("savingsProductId", productId());
accountingBridgeData.put("currency", currencyData);
accountingBridgeData.put("officeId", officeId()); accountingBridgeData.put("officeId", officeId());
accountingBridgeData.put("cashBasedAccountingEnabled", isCashBasedAccountingEnabledOnSavingsProduct()); accountingBridgeData.put("cashBasedAccountingEnabled", isCashBasedAccountingEnabledOnSavingsProduct());
accountingBridgeData.put("accrualBasedAccountingEnabled", isAccrualBasedAccountingEnabledOnSavingsProduct()); accountingBridgeData.put("accrualBasedAccountingEnabled", isAccrualBasedAccountingEnabledOnSavingsProduct());