merging pramods pr around account transfers accounting clean up

This commit is contained in:
Vishwas Babu A J
2014-06-04 18:07:24 -07:00
51 changed files with 2146 additions and 320 deletions
+244
View File
@@ -1369,6 +1369,24 @@
<td><a href="#accountingrules_update">Update a Accounting Rule</a></td>
<td><a href="#accountingrules_delete">Delete a Accounting Rule</a></td>
</tr>
<tr>
<td><a href="#officeglaccount">Office GL Account Mappings</a></td>
<td>officeglaccounts</td>
<td><a href="#officeglaccounts_create">Create Office GL Account Mapping</a><br> </td>
<td><a href="#officeglaccounts_list">List Journal Entries</a></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>officeglaccounts/{entryId}</td>
<td></td>
<td><a href="#officeglaccounts_retrieve">Retrieve a single Entry</a></td>
<td><a href="#officeglaccounts_update">Update Office GL Account Mapping</a></td>
<td><a href="#officeglaccounts_delete">Delete Office GL Account Mapping</a></td>
</tr>
</table>
</div>
</div>
@@ -28241,6 +28259,232 @@ Content-Type: application/json
</div>
</div>
<!-- start office gl accout mappings-->
<a id="officeglaccount" name="officeglaccount" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h3>Office GL Accounting Mappings</h3>
<p>
These are the Branch level intermediate accounts to move funds between banches
</p>
<table class=matrixHeading>
<tr class="matrixHeadingBG">
<td><div class="mifosXHeading2">Field Descriptions</div></td>
</tr>
<tr class=alt>
<td>officeId</td>
</tr>
<tr>
<td class=fielddesc>The identifier of the office (
cost center) at which the financial activity
occurs</td>
</tr>
<tr class=alt>
<td>liabilityTransferInSuspenseAccountId</td>
</tr>
<tr>
<td class=fielddesc>The identifier of the liability account (
Ledger Account) against which transfer journal entry
should made
</td>
</tr>
</table>
</div>
</div>
<a id="officeglaccounts_list" name="officeglaccounts_list" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>List Office Level GL Account Mappings</h4>
<p>The <i>list</i> of Account Mapping entries through <b>pagination</b> and <b>sorting</b>.</p>
<h5>Optional Arguments</h5>
<dl class="argument-list">
<dt>offset</dt>
<dd>
Integer <span>optional</span>, defaults to 0
</dd>
<dd>Indicates from what result to start from.</dd>
<dt>limit</dt>
<dd>
Integer <span>optional</span>, defaults to 200
</dd>
<dd>Restricts the size of results returned. To override the default and return all entries you must explicitly pass a non-positive integer value for limit e.g. limit=0, or limit=-1</dd>
<dt>orderBy</dt>
<dd>
String <span>optional</span>, one of <span>displayName, accountNo, officeId, officeName</span>
</dd>
<dd>Orders the results by the field indicated.</dd>
<dt>sortBy</dt>
<dd>
String <span>optional</span>, one of <span>ASC, DESC</span>
</dd>
<dd>Indicates what way to order results if <i>orderBy</i> is used.</dd>
<dt>officeId</dt>
<dd>
Integer <span>optional</span>
</dd>
<dd>Provides ability to restrict list of centers returned based on the office there associated with.</dd>
</dl>
<p>Example Requests:</p>
<div class=apiClick>officeglaccounts</div>
<br>
<div class=apiClick>officeglaccounts?orderBy=id&sortOrder=DESC</div>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/api/v1/officeglaccounts
</code>
<code class="method-response">
{
"totalFilteredRecords": 1,
"pageItems": [
{
"id": 1,
"officeData": {
"id": 2,
"name": "Office_BX38"
},
"glAccountData": {
"id": 29,
"name": "ACCOUNT_NAME_P9UWO",
"glCode": "LIABILITY_7E1401198314394"
}
}]}
</code>
</div>
</div>
<a id="officeglaccounts_create" name="officeglaccounts_create" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Create Office GL Account</h4>
<table class=matrixHeading>
<tr class="matrixHeadingBG">
<td><div class="mifosXHeading2">Mandatory Fields</div></td>
</tr>
<tr class=alt>
<td>officeId, liabilityTransferInSuspenseAccountId
</td>
</tr>
</table>
<br />
</div>
<div class="method-example">
<code class="method-declaration">
POST https://DomainName/api/v1/officeglaccounts
</code>
<code class="method-request">
POST officeglaccounts
Content-Type: application/json
Request Body:
{
"officeId": 1,
"liabilityTransferInSuspenseAccountId" : 2
}
</code>
<code class="method-response">
{
"resourceId": 1
}
</code>
</div>
</div>
<a id="officeglaccounts_update" name="officeglaccounts_update" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Update Office GL Account Mappings</h4>
<p>
the API Updates the mapping GL Accoiunt for office.
<br>
</p>
</div>
<div class="method-example">
<code class="method-declaration">
POST https://DomainName/api/v1/officeglaccounts/1
</code>
<code class="method-request">
POST officeglaccounts
Content-Type: application/json
Request Body:
{
"liabilityTransferInSuspenseAccountId": 2
}
</code>
<code class="method-response">
{
"liabilityTransferInSuspenseAccountId": 2
}
</code>
</div>
</div>
<a id="officeglaccounts_retrieve" name="officeglaccounts_retrieve"
class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Retrieve a single Entry</h4>
<p>Example Requests:</p>
<div class=apiClick>officeglaccounts/1</div>
<br>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/api/v1/officeglaccounts/{entryId}
</code>
<code class="method-response">
{
"id": 1,
"officeData": {
"id": 2,
"name": "Office_BX38"
},
"glAccountData": {
"id": 29,
"name": "ACCOUNT_NAME_P9UWO",
"glCode": "LIABILITY_7E1401198314394"
}
}
</code>
</div>
</div>
<a id="officeglaccounts_delete" name="officeglaccounts_delete"
class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Delete Office GL Mapping</h4>
</div>
<div class="method-example">
<code class="method-declaration">
GET https://DomainName/api/v1/officeglaccounts/{mappingId}
</code>
<code class="method-request">
POST officeglaccounts/C1MAE935K0IAEYA?command=reverse
Content-Type: application/json
</code>
<code class="method-response">
{
"resourceId": "2"
}
</code>
</div>
</div>
<!-- start of Search API doc -->
<a id="search" name="search" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
@@ -0,0 +1,21 @@
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('accounting', 'READ_OFFICEGLACCOUNT', 'OFFICEGLACCOUNT', 'READ', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('accounting', 'CREATE_OFFICEGLACCOUNT', 'OFFICEGLACCOUNT', 'CREATE', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('accounting', 'DELETE_OFFICEGLACCOUNT', 'OFFICEGLACCOUNT', 'DELETE', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('accounting', 'UPDATE_OFFICEGLACCOUNT', 'OFFICEGLACCOUNT', 'UPDATE', 0);
CREATE TABLE `acc_gl_office_mapping` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`gl_account_id` BIGINT(20) NOT NULL DEFAULT '0',
`office_id` BIGINT(20) NOT NULL,
`financial_account_type` SMALLINT(5) NOT NULL,
PRIMARY KEY (`id`),
INDEX `FK_office_mapping_acc_gl_account` (`gl_account_id`),
INDEX `FK_office_mapping_office` (`office_id`),
CONSTRAINT `FK_office_mapping_acc_gl_account` FOREIGN KEY (`gl_account_id`) REFERENCES `acc_gl_account` (`id`),
CONSTRAINT `FK_office_mapping_office` FOREIGN KEY (`office_id`) REFERENCES `m_office` (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
@@ -13,7 +13,13 @@ import org.junit.Before;
import org.junit.Test;
import org.mifosplatform.integrationtests.common.ClientHelper;
import org.mifosplatform.integrationtests.common.CommonConstants;
import org.mifosplatform.integrationtests.common.OfficeHelper;
import org.mifosplatform.integrationtests.common.Utils;
import org.mifosplatform.integrationtests.common.accounting.Account;
import org.mifosplatform.integrationtests.common.accounting.AccountHelper;
import org.mifosplatform.integrationtests.common.accounting.JournalEntry;
import org.mifosplatform.integrationtests.common.accounting.JournalEntryHelper;
import org.mifosplatform.integrationtests.common.accounting.OfficeAccountMappingHelper;
import org.mifosplatform.integrationtests.common.charges.ChargesHelper;
import org.mifosplatform.integrationtests.common.loans.LoanApplicationTestBuilder;
import org.mifosplatform.integrationtests.common.loans.LoanProductTestBuilder;
@@ -54,6 +60,8 @@ public class AccountTransferTest {
private SavingsAccountHelper savingsAccountHelper;
private AccountTransferHelper accountTransferHelper;
private LoanTransactionHelper loanTransactionHelper;
private AccountHelper accountHelper;
private JournalEntryHelper journalEntryHelper;
Float TRANSFER_AMOUNT = new Float(ACCOUNT_TRANSFER_AMOUNT);
Float TRANSFER_AMOUNT_ADJUST = new Float(ACCOUNT_TRANSFER_AMOUNT_ADJUST);
@@ -64,6 +72,8 @@ public class AccountTransferTest {
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec);
this.journalEntryHelper = new JournalEntryHelper(this.requestSpec, this.responseSpec);
}
@Test
@@ -71,11 +81,31 @@ public class AccountTransferTest {
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
this.accountTransferHelper = new AccountTransferHelper(this.requestSpec, this.responseSpec);
final Account assetAccount = this.accountHelper.createAssetAccount();
final Account incomeAccount = this.accountHelper.createIncomeAccount();
final Account expenseAccount = this.accountHelper.createExpenseAccount();
final Account liabilityAccount = this.accountHelper.createLiabilityAccount();
OfficeHelper officeHelper = new OfficeHelper(this.requestSpec, this.responseSpec);
Integer toOfficeId = officeHelper.createOffice("01 January 2011");
Assert.assertNotNull(toOfficeId);
// Creating Savings Account to which fund to be Transferred
final Integer toClientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
final Integer toClientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2011",
String.valueOf(toOfficeId));
Assert.assertNotNull(toClientID);
final Integer toSavingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE);
Account toTransferAccount = accountHelper.createLiabilityAccount();
Assert.assertNotNull(toTransferAccount);
OfficeAccountMappingHelper accountMappingHelper = new OfficeAccountMappingHelper(this.requestSpec,
new ResponseSpecBuilder().build());
Integer toTransferAccountMappingId = (Integer) accountMappingHelper.createOfficeAccountMapping(toOfficeId,
toTransferAccount.getAccountID(), CommonConstants.RESPONSE_RESOURCE_ID);
Assert.assertNotNull(toTransferAccountMappingId);
final Integer toSavingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, assetAccount,
incomeAccount, expenseAccount, liabilityAccount);
Assert.assertNotNull(toSavingsProductID);
final Integer toSavingsID = this.savingsAccountHelper.applyForSavingsApplication(toClientID, toSavingsProductID,
@@ -93,11 +123,23 @@ public class AccountTransferTest {
final HashMap toSavingsSummaryBefore = this.savingsAccountHelper.getSavingsSummary(toSavingsID);
Integer fromOfficeId = officeHelper.createOffice("01 January 2011");
Assert.assertNotNull(fromOfficeId);
// Creating Savings Account from which the Fund has to be Transferred
final Integer fromClientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
final Integer fromClientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2011",
String.valueOf(fromOfficeId));
Assert.assertNotNull(fromClientID);
final Integer fromSavingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE);
Account fromTransferAccount = accountHelper.createLiabilityAccount();
Assert.assertNotNull(fromTransferAccount);
Integer fromTransferAccountMappingId = (Integer) accountMappingHelper.createOfficeAccountMapping(fromOfficeId,
fromTransferAccount.getAccountID(), CommonConstants.RESPONSE_RESOURCE_ID);
Assert.assertNotNull(fromTransferAccountMappingId);
final Integer fromSavingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE,
assetAccount, incomeAccount, expenseAccount, liabilityAccount);
Assert.assertNotNull(fromSavingsProductID);
final Integer fromSavingsID = this.savingsAccountHelper.applyForSavingsApplication(fromClientID, fromSavingsProductID,
@@ -118,7 +160,7 @@ public class AccountTransferTest {
Float fromSavingsBalance = new Float(MINIMUM_OPENING_BALANCE);
Float toSavingsBalance = new Float(MINIMUM_OPENING_BALANCE);
this.accountTransferHelper.accountTransfer(fromClientID, fromSavingsID, toClientID, toSavingsID, FROM_SAVINGS_ACCOUNT_TYPE,
this.accountTransferHelper.accountTransfer(fromClientID, fromSavingsID, fromClientID, toSavingsID, FROM_SAVINGS_ACCOUNT_TYPE,
TO_SAVINGS_ACCOUNT_TYPE, ACCOUNT_TRANSFER_AMOUNT);
fromSavingsBalance -= new Float(ACCOUNT_TRANSFER_AMOUNT);
@@ -131,19 +173,53 @@ public class AccountTransferTest {
HashMap toSavingsSummaryAfter = this.savingsAccountHelper.getSavingsSummary(toSavingsID);
assertEquals("Verifying To Savings Account Balance after Account Transfer", toSavingsBalance,
toSavingsSummaryAfter.get("accountBalance"));
final JournalEntry[] office1LiabilityEntries = { new JournalEntry(new Float(ACCOUNT_TRANSFER_AMOUNT),
JournalEntry.TransactionType.CREDIT) };
final JournalEntry[] office2LiabilityEntries = { new JournalEntry(new Float(ACCOUNT_TRANSFER_AMOUNT),
JournalEntry.TransactionType.DEBIT) };
this.journalEntryHelper.checkJournalEntryForAssetAccount(fromTransferAccount, AccountTransferHelper.ACCOUNT_TRANSFER_DATE,
office1LiabilityEntries);
this.journalEntryHelper.checkJournalEntryForAssetAccount(toTransferAccount, AccountTransferHelper.ACCOUNT_TRANSFER_DATE,
office2LiabilityEntries);
}
@Test
public void testFromSavingsToLoanAccountTransfer() {
final Account assetAccount = this.accountHelper.createAssetAccount();
final Account incomeAccount = this.accountHelper.createIncomeAccount();
final Account expenseAccount = this.accountHelper.createExpenseAccount();
final Account liabilityAccount = this.accountHelper.createLiabilityAccount();
final Account loanAssetAccount = this.accountHelper.createAssetAccount();
final Account loanIncomeAccount = this.accountHelper.createIncomeAccount();
final Account loanExpenseAccount = this.accountHelper.createExpenseAccount();
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
this.accountTransferHelper = new AccountTransferHelper(this.requestSpec, this.responseSpec);
// Creating Loan Account to which Fund to be Transferred.
final Integer toClientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
OfficeHelper officeHelper = new OfficeHelper(this.requestSpec, this.responseSpec);
Integer toOfficeId = officeHelper.createOffice("01 January 2011");
Assert.assertNotNull(toOfficeId);
// Creating Loan Account to which fund to be Transferred
final Integer toClientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2011",
String.valueOf(toOfficeId));
Assert.assertNotNull(toClientID);
final Integer toLoanProductID = createLoanProduct();
Account toTransferAccount = accountHelper.createLiabilityAccount();
Assert.assertNotNull(toTransferAccount);
OfficeAccountMappingHelper accountMappingHelper = new OfficeAccountMappingHelper(this.requestSpec,
new ResponseSpecBuilder().build());
Integer toTransferAccountMappingId = (Integer) accountMappingHelper.createOfficeAccountMapping(toOfficeId,
toTransferAccount.getAccountID(), CommonConstants.RESPONSE_RESOURCE_ID);
Assert.assertNotNull(toTransferAccountMappingId);
final Integer toLoanProductID = createLoanProduct(loanAssetAccount, loanIncomeAccount, loanExpenseAccount, overpaymentAccount);
Assert.assertNotNull(toLoanProductID);
final Integer toLoanID = applyForLoanApplication(toClientID, toLoanProductID);
@@ -158,11 +234,23 @@ public class AccountTransferTest {
toLoanStatusHashMap = this.loanTransactionHelper.disburseLoan(LOAN_DISBURSAL_DATE, toLoanID);
LoanStatusChecker.verifyLoanIsActive(toLoanStatusHashMap);
// Creating Savings Account from which Fund to be Transferred
final Integer fromClientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Integer fromOfficeId = officeHelper.createOffice("01 January 2011");
Assert.assertNotNull(fromOfficeId);
// Creating Savings Account from which the Fund has to be Transferred
final Integer fromClientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2011",
String.valueOf(fromOfficeId));
Assert.assertNotNull(fromClientID);
final Integer fromSavingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE);
Account fromTransferAccount = accountHelper.createLiabilityAccount();
Assert.assertNotNull(fromTransferAccount);
Integer fromTransferAccountMappingId = (Integer) accountMappingHelper.createOfficeAccountMapping(fromOfficeId,
fromTransferAccount.getAccountID(), CommonConstants.RESPONSE_RESOURCE_ID);
Assert.assertNotNull(fromTransferAccountMappingId);
final Integer fromSavingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE,
assetAccount, incomeAccount, expenseAccount, liabilityAccount);
Assert.assertNotNull(fromSavingsProductID);
final Integer fromSavingsID = this.savingsAccountHelper.applyForSavingsApplication(fromClientID, fromSavingsProductID,
@@ -192,20 +280,56 @@ public class AccountTransferTest {
fromSavingsSummaryAfter.get("accountBalance"));
HashMap toLoanSummaryAfter = this.loanTransactionHelper.getLoanSummary(requestSpec, responseSpec, toLoanID);
assertEquals("Verifying To Loan Repayment Amount after Account Transfer", TRANSFER_AMOUNT_ADJUST, toLoanSummaryAfter.get("totalRepayment"));
assertEquals("Verifying To Loan Repayment Amount after Account Transfer", TRANSFER_AMOUNT_ADJUST,
toLoanSummaryAfter.get("totalRepayment"));
final JournalEntry[] office1LiabilityEntries = { new JournalEntry(new Float(ACCOUNT_TRANSFER_AMOUNT_ADJUST),
JournalEntry.TransactionType.CREDIT) };
final JournalEntry[] office2LiabilityEntries = { new JournalEntry(new Float(ACCOUNT_TRANSFER_AMOUNT_ADJUST),
JournalEntry.TransactionType.DEBIT) };
this.journalEntryHelper.checkJournalEntryForAssetAccount(fromTransferAccount, AccountTransferHelper.ACCOUNT_TRANSFER_DATE,
office1LiabilityEntries);
this.journalEntryHelper.checkJournalEntryForAssetAccount(toTransferAccount, AccountTransferHelper.ACCOUNT_TRANSFER_DATE,
office2LiabilityEntries);
}
@Test
public void testFromLoanToSavingsAccountTransfer() {
final Account assetAccount = this.accountHelper.createAssetAccount();
final Account incomeAccount = this.accountHelper.createIncomeAccount();
final Account expenseAccount = this.accountHelper.createExpenseAccount();
final Account liabilityAccount = this.accountHelper.createLiabilityAccount();
final Account loanAssetAccount = this.accountHelper.createAssetAccount();
final Account loanIncomeAccount = this.accountHelper.createIncomeAccount();
final Account loanExpenseAccount = this.accountHelper.createExpenseAccount();
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
this.accountTransferHelper = new AccountTransferHelper(this.requestSpec, this.responseSpec);
// Creating Savings Account to which Fund to be Transferred
final Integer toClientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
OfficeHelper officeHelper = new OfficeHelper(this.requestSpec, this.responseSpec);
Integer toOfficeId = officeHelper.createOffice("01 January 2011");
Assert.assertNotNull(toOfficeId);
// Creating Loan Account to which fund to be Transferred
final Integer toClientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2011",
String.valueOf(toOfficeId));
Assert.assertNotNull(toClientID);
final Integer toSavingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE);
Account toTransferAccount = accountHelper.createLiabilityAccount();
Assert.assertNotNull(toTransferAccount);
OfficeAccountMappingHelper accountMappingHelper = new OfficeAccountMappingHelper(this.requestSpec,
new ResponseSpecBuilder().build());
Integer toTransferAccountMappingId = (Integer) accountMappingHelper.createOfficeAccountMapping(toOfficeId,
toTransferAccount.getAccountID(), CommonConstants.RESPONSE_RESOURCE_ID);
Assert.assertNotNull(toTransferAccountMappingId);
final Integer toSavingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, assetAccount,
incomeAccount, expenseAccount, liabilityAccount);
Assert.assertNotNull(toSavingsProductID);
final Integer toSavingsID = this.savingsAccountHelper.applyForSavingsApplication(toClientID, toSavingsProductID,
@@ -221,14 +345,25 @@ public class AccountTransferTest {
toSavingsStatusHashMap = this.savingsAccountHelper.activateSavings(toSavingsID);
SavingsStatusChecker.verifySavingsIsActive(toSavingsStatusHashMap);
// Creating Loan Account to or from which Fund to be Transferred.
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assert.assertNotNull(clientID);
Integer fromOfficeId = officeHelper.createOffice("01 January 2011");
Assert.assertNotNull(fromOfficeId);
final Integer loanProductID = createLoanProduct();
// Creating Savings Account from which the Fund has to be Transferred
final Integer fromClientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2011",
String.valueOf(fromOfficeId));
Assert.assertNotNull(fromClientID);
Account fromTransferAccount = accountHelper.createLiabilityAccount();
Assert.assertNotNull(fromTransferAccount);
Integer fromTransferAccountMappingId = (Integer) accountMappingHelper.createOfficeAccountMapping(fromOfficeId,
fromTransferAccount.getAccountID(), CommonConstants.RESPONSE_RESOURCE_ID);
Assert.assertNotNull(fromTransferAccountMappingId);
final Integer loanProductID = createLoanProduct(loanAssetAccount, loanIncomeAccount, loanExpenseAccount, overpaymentAccount);
Assert.assertNotNull(loanProductID);
final Integer loanID = applyForLoanApplication(clientID, loanProductID);
final Integer loanID = applyForLoanApplication(fromClientID, loanProductID);
Assert.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
@@ -240,14 +375,12 @@ public class AccountTransferTest {
loanStatusHashMap = this.loanTransactionHelper.disburseLoan(LOAN_DISBURSAL_DATE, loanID);
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
// Creating Savings Account from which Fund to be Transferred
final Integer fromClientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assert.assertNotNull(fromClientId);
final Integer fromSavingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE);
final Integer fromSavingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE,
assetAccount, incomeAccount, expenseAccount, liabilityAccount);
Assert.assertNotNull(fromSavingsProductID);
final Integer fromSavingsID = this.savingsAccountHelper.applyForSavingsApplication(fromClientId, fromSavingsProductID,
final Integer fromSavingsID = this.savingsAccountHelper.applyForSavingsApplication(fromClientID, fromSavingsProductID,
ACCOUNT_TYPE_INDIVIDUAL);
Assert.assertNotNull(fromSavingsID);
@@ -264,7 +397,7 @@ public class AccountTransferTest {
Float fromSavingsBalance = new Float(MINIMUM_OPENING_BALANCE);
this.accountTransferHelper.accountTransfer(fromClientId, fromSavingsID, clientID, loanID, FROM_SAVINGS_ACCOUNT_TYPE,
this.accountTransferHelper.accountTransfer(fromClientID, fromSavingsID, fromClientID, loanID, FROM_SAVINGS_ACCOUNT_TYPE,
TO_LOAN_ACCOUNT_TYPE, ACCOUNT_TRANSFER_AMOUNT);
fromSavingsBalance -= TRANSFER_AMOUNT;
@@ -277,7 +410,7 @@ public class AccountTransferTest {
Float toSavingsBalance = new Float(MINIMUM_OPENING_BALANCE);
this.accountTransferHelper.accountTransfer(clientID, loanID, toClientID, toSavingsID, FROM_LOAN_ACCOUNT_TYPE,
this.accountTransferHelper.accountTransfer(fromClientID, loanID, toClientID, toSavingsID, FROM_LOAN_ACCOUNT_TYPE,
TO_SAVINGS_ACCOUNT_TYPE, ACCOUNT_TRANSFER_AMOUNT_ADJUST);
toSavingsBalance += TRANSFER_AMOUNT_ADJUST;
@@ -287,21 +420,32 @@ public class AccountTransferTest {
// Verifying toSavings Account Balance after Account Transfer
assertEquals("Verifying From Savings Account Balance after Account Transfer", toSavingsBalance,
toSavingsSummaryAfter.get("accountBalance"));
final JournalEntry[] office1LiabilityEntries = { new JournalEntry(new Float(ACCOUNT_TRANSFER_AMOUNT_ADJUST),
JournalEntry.TransactionType.CREDIT) };
final JournalEntry[] office2LiabilityEntries = { new JournalEntry(new Float(ACCOUNT_TRANSFER_AMOUNT_ADJUST),
JournalEntry.TransactionType.DEBIT) };
this.journalEntryHelper.checkJournalEntryForAssetAccount(fromTransferAccount, AccountTransferHelper.ACCOUNT_TRANSFER_DATE,
office1LiabilityEntries);
this.journalEntryHelper.checkJournalEntryForAssetAccount(toTransferAccount, AccountTransferHelper.ACCOUNT_TRANSFER_DATE,
office2LiabilityEntries);
}
private Integer createSavingsProduct(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
final String minOpenningBalance) {
final String minOpenningBalance, final Account... accounts) {
System.out.println("------------------------------CREATING NEW SAVINGS PRODUCT ---------------------------------------");
SavingsProductHelper savingsProductHelper = new SavingsProductHelper();
final String savingsProductJSON = savingsProductHelper //
.withInterestCompoundingPeriodTypeAsDaily() //
.withInterestPostingPeriodTypeAsMonthly() //
.withInterestCalculationPeriodTypeAsDailyBalance() //
.withMinimumOpenningBalance(minOpenningBalance).build();
.withMinimumOpenningBalance(minOpenningBalance).withAccountingRuleAsCashBased(accounts).build();
return SavingsProductHelper.createSavingsProduct(savingsProductJSON, requestSpec, responseSpec);
}
private Integer createLoanProduct() {
private Integer createLoanProduct(final Account... accounts) {
System.out.println("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
final String loanProductJSON = new LoanProductTestBuilder() //
.withPrincipal("8,000.00") //
@@ -312,6 +456,7 @@ public class AccountTransferTest {
.withInterestRateFrequencyTypeAsMonths() //
.withAmortizationTypeAsEqualInstallments() //
.withInterestTypeAsDecliningBalance() //
.withAccountingRuleAsCashBased(accounts)//
.build(null);
return this.loanTransactionHelper.getLoanProductId(loanProductJSON);
}
@@ -0,0 +1,93 @@
package org.mifosplatform.integrationtests;
import static org.junit.Assert.assertEquals;
import java.util.HashMap;
import java.util.List;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mifosplatform.integrationtests.common.CommonConstants;
import org.mifosplatform.integrationtests.common.OfficeHelper;
import org.mifosplatform.integrationtests.common.Utils;
import org.mifosplatform.integrationtests.common.accounting.Account;
import org.mifosplatform.integrationtests.common.accounting.AccountHelper;
import org.mifosplatform.integrationtests.common.accounting.OfficeAccountMappingHelper;
import com.jayway.restassured.builder.RequestSpecBuilder;
import com.jayway.restassured.builder.ResponseSpecBuilder;
import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.specification.RequestSpecification;
import com.jayway.restassured.specification.ResponseSpecification;
@SuppressWarnings("rawtypes")
public class OfficeAccountingMappingsTest {
private ResponseSpecification responseSpec;
private RequestSpecification requestSpec;
@Before
public void setup() {
Utils.initializeRESTAssured();
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
}
@SuppressWarnings("unchecked")
@Test
public void testOfficeAccountingMappings() {
OfficeHelper officeHelper = new OfficeHelper(this.requestSpec, this.responseSpec);
Integer officeId = officeHelper.createOffice("01 January 2014");
Assert.assertNotNull(officeId);
Integer officeId2 = officeHelper.createOffice("01 January 2014");
Assert.assertNotNull(officeId2);
AccountHelper accountHelper = new AccountHelper(this.requestSpec, this.responseSpec);
Account transferAccount = accountHelper.createLiabilityAccount();
Assert.assertNotNull(transferAccount);
OfficeAccountMappingHelper accountMappingHelper = new OfficeAccountMappingHelper(this.requestSpec,
new ResponseSpecBuilder().build());
Integer transferAccountMappingId = (Integer) accountMappingHelper.createOfficeAccountMapping(officeId,
transferAccount.getAccountID(), CommonConstants.RESPONSE_RESOURCE_ID);
Assert.assertNotNull(transferAccountMappingId);
HashMap mappingDetails = accountMappingHelper.getOfficeAccountMapping(transferAccountMappingId);
Assert.assertEquals(officeId, ((HashMap) mappingDetails.get("officeData")).get("id"));
Assert.assertEquals(transferAccount.getAccountID(), ((HashMap) mappingDetails.get("glAccountData")).get("id"));
Account transferAccount2 = accountHelper.createLiabilityAccount();
Assert.assertNotNull(transferAccount2);
HashMap changes = (HashMap) accountMappingHelper.updateOfficeAccountMapping(transferAccountMappingId, officeId,
transferAccount2.getAccountID(), CommonConstants.RESPONSE_CHANGES);
Assert.assertEquals(transferAccount2.getAccountID(), changes.get("liabilityTransferInSuspenseAccountId"));
mappingDetails = accountMappingHelper.getOfficeAccountMapping(transferAccountMappingId);
Assert.assertEquals(officeId, ((HashMap) mappingDetails.get("officeData")).get("id"));
Assert.assertEquals(transferAccount2.getAccountID(), ((HashMap) mappingDetails.get("glAccountData")).get("id"));
List<HashMap> error1 = (List<HashMap>) accountMappingHelper.updateOfficeAccountMapping(transferAccountMappingId, officeId2,
transferAccount2.getAccountID(), CommonConstants.RESPONSE_ERROR);
assertEquals("error.msg.officeToAccountMapping.update.of.officeId.is.not.supported",
error1.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
List<HashMap> error2 = (List<HashMap>) accountMappingHelper.createOfficeAccountMapping(officeId, transferAccount.getAccountID(),
CommonConstants.RESPONSE_ERROR);
assertEquals("error.msg.officeToAccountMapping.exists.for.office", error2.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
Account fundAccount = accountHelper.createAssetAccount();
Assert.assertNotNull(fundAccount);
List<HashMap> error3 = (List<HashMap>) accountMappingHelper.createOfficeAccountMapping(officeId2, fundAccount.getAccountID(),
CommonConstants.RESPONSE_ERROR);
assertEquals("error.msg.liabilityTransferInSuspenseAccountId.invalid.account.type", error3.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
}
}
@@ -18,13 +18,19 @@ public class ClientHelper {
public static Integer createClient(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
final String activationDate) {
System.out.println("---------------------------------CREATING A CLIENT---------------------------------------------");
return Utils.performServerPost(requestSpec, responseSpec, CREATE_CLIENT_URL, getTestClientAsJSON(activationDate), "clientId");
return createClient(requestSpec, responseSpec, activationDate, "1");
}
public static String getTestClientAsJSON(final String dateOfJoining) {
public static Integer createClient(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
final String activationDate, final String officeId) {
System.out.println("---------------------------------CREATING A CLIENT---------------------------------------------");
return Utils.performServerPost(requestSpec, responseSpec, CREATE_CLIENT_URL, getTestClientAsJSON(activationDate, officeId),
"clientId");
}
public static String getTestClientAsJSON(final String dateOfJoining, final String officeId) {
final HashMap<String, String> map = new HashMap<String, String>();
map.put("officeId", "1");
map.put("officeId", officeId);
map.put("firstname", Utils.randomNameGenerator("Client_FirstName_", 5));
map.put("lastname", Utils.randomNameGenerator("Client_LastName_", 4));
map.put("externalId", randomIDGenerator("ID_", 7));
@@ -0,0 +1,38 @@
package org.mifosplatform.integrationtests.common;
import java.util.HashMap;
import com.google.gson.Gson;
import com.jayway.restassured.specification.RequestSpecification;
import com.jayway.restassured.specification.ResponseSpecification;
public class OfficeHelper {
private static final String OFFICE_URL = "/mifosng-provider/api/v1/offices";
private final RequestSpecification requestSpec;
private final ResponseSpecification responseSpec;
public OfficeHelper(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
this.requestSpec = requestSpec;
this.responseSpec = responseSpec;
}
public Integer createOffice(final String openingDate) {
String json = getAsJSON(openingDate);
return Utils.performServerPost(this.requestSpec, this.responseSpec, OFFICE_URL + "?" + Utils.TENANT_IDENTIFIER, json,
CommonConstants.RESPONSE_RESOURCE_ID);
}
public static String getAsJSON(final String openingDate) {
final HashMap<String, String> map = new HashMap<String, String>();
map.put("parentId", "1");
map.put("name", Utils.randomNameGenerator("Office_", 4));
map.put("dateFormat", "dd MMMM yyyy");
map.put("locale", "en");
map.put("openingDate", openingDate);
System.out.println("map : " + map);
return new Gson().toJson(map);
}
}
@@ -0,0 +1,15 @@
package org.mifosplatform.integrationtests.common.accounting;
import java.util.HashMap;
import com.google.gson.Gson;
public class OfficeAccountMappingBuilder {
public static String build(Integer officeId, Integer glAccountId) {
final HashMap<String, Object> map = new HashMap<String, Object>();
map.put("officeId", officeId);
map.put("liabilityTransferInSuspenseAccountId", glAccountId);
return new Gson().toJson(map);
}
}
@@ -0,0 +1,44 @@
package org.mifosplatform.integrationtests.common.accounting;
import java.util.HashMap;
import org.mifosplatform.integrationtests.common.Utils;
import com.jayway.restassured.specification.RequestSpecification;
import com.jayway.restassured.specification.ResponseSpecification;
@SuppressWarnings("rawtypes")
public class OfficeAccountMappingHelper {
private static final String ACCOUNT_MAPPING_URL = "/mifosng-provider/api/v1/officeglaccounts";
private final RequestSpecification requestSpec;
private final ResponseSpecification responseSpec;
public OfficeAccountMappingHelper(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
this.requestSpec = requestSpec;
this.responseSpec = responseSpec;
}
public Object createOfficeAccountMapping(Integer officeId, Integer glAccountId, String jsonBack) {
String json = OfficeAccountMappingBuilder.build(officeId, glAccountId);
return Utils.performServerPost(this.requestSpec, this.responseSpec, ACCOUNT_MAPPING_URL + "?" + Utils.TENANT_IDENTIFIER, json,
jsonBack);
}
public Object updateOfficeAccountMapping(Integer mappingId, Integer officeId, Integer glAccountId, String jsonBack) {
String json = OfficeAccountMappingBuilder.build(officeId, glAccountId);
return Utils.performServerPut(this.requestSpec, this.responseSpec, ACCOUNT_MAPPING_URL + "/" + mappingId + "?"
+ Utils.TENANT_IDENTIFIER, json, jsonBack);
}
public HashMap getOfficeAccountMapping(final Integer mappingId) {
final String URL = ACCOUNT_MAPPING_URL + "/" + mappingId + "?" + Utils.TENANT_IDENTIFIER;
return Utils.performServerGet(requestSpec, responseSpec, URL, "");
}
public HashMap getOfficeAccountMappings() {
final String URL = ACCOUNT_MAPPING_URL + "?" + Utils.TENANT_IDENTIFIER;
return Utils.performServerGet(requestSpec, responseSpec, URL, "");
}
}
@@ -14,7 +14,7 @@ public class AccountTransferHelper {
private static final String LOCALE = "en_GB";
private static final String OFFICE_ID = "1";
private static final String TRANSFER_DESCRIPTION = "Transfer";
private static final String ACCOUNT_TRANSFER_DATE = "01 March 2013";
public static final String ACCOUNT_TRANSFER_DATE = "01 March 2013";
private String transferDate = "";
private String officeId = OFFICE_ID;
@@ -0,0 +1,158 @@
/**
* 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.accounting.accountmapping.api;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.mifosplatform.accounting.accountmapping.data.OfficeToGLAccountMappingData;
import org.mifosplatform.accounting.accountmapping.service.OfficeToGLAccountMappingReadPlatformService;
import org.mifosplatform.commands.domain.CommandWrapper;
import org.mifosplatform.commands.service.CommandWrapperBuilder;
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.mifosplatform.infrastructure.core.service.Page;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.group.service.SearchParameters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/officeglaccounts")
@Component
@Scope("singleton")
public class OfficeGLAccountsApiResource {
private static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "officeData", "glAccountData",
"accountingMappingOptions", "officeOptions"));
private final String resourceNameForPermission = "OFFICEGLACCOUNT";
private final OfficeToGLAccountMappingReadPlatformService officeToGLAccountMappingReadPlatformService;
private final DefaultToApiJsonSerializer<OfficeToGLAccountMappingData> apiJsonSerializerService;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PlatformSecurityContext context;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@Autowired
public OfficeGLAccountsApiResource(final PlatformSecurityContext context,
final OfficeToGLAccountMappingReadPlatformService officeToGLAccountMappingReadPlatformService,
final DefaultToApiJsonSerializer<OfficeToGLAccountMappingData> toApiJsonSerializer,
final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
this.context = context;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
this.apiJsonSerializerService = toApiJsonSerializer;
this.officeToGLAccountMappingReadPlatformService = officeToGLAccountMappingReadPlatformService;
}
@GET
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveTemplate(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
OfficeToGLAccountMappingData officeToGLAccountMappingData = this.officeToGLAccountMappingReadPlatformService.retrieveTemplate();
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.apiJsonSerializerService.serialize(settings, officeToGLAccountMappingData, RESPONSE_DATA_PARAMETERS);
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAll(@Context final UriInfo uriInfo, @QueryParam("sqlSearch") final String sqlSearch,
@QueryParam("externalId") final String externalId, @QueryParam("offset") final Integer offset,
@QueryParam("limit") final Integer limit, @QueryParam("orderBy") final String orderBy,
@QueryParam("sortOrder") final String sortOrder) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
final SearchParameters searchParameters = SearchParameters.forAccountTransfer(sqlSearch, externalId, offset, limit, orderBy,
sortOrder);
final Page<OfficeToGLAccountMappingData> mappings = this.officeToGLAccountMappingReadPlatformService.retrieveAll(searchParameters);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.apiJsonSerializerService.serialize(settings, mappings, RESPONSE_DATA_PARAMETERS);
}
@GET
@Path("{mappingId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retreiveAccountMapping(@PathParam("mappingId") final Long mappingId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
OfficeToGLAccountMappingData officeToGLAccountMappingData = this.officeToGLAccountMappingReadPlatformService.retrieve(mappingId);
if (settings.isTemplate()) {
OfficeToGLAccountMappingData templateData = this.officeToGLAccountMappingReadPlatformService.retrieveTemplate();
officeToGLAccountMappingData = OfficeToGLAccountMappingData.associateTemplateData(templateData, officeToGLAccountMappingData);
}
return this.apiJsonSerializerService.serialize(settings, officeToGLAccountMappingData, RESPONSE_DATA_PARAMETERS);
}
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createGLAccount(final String jsonRequestBody) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createOfficeToGLAccountMapping().withJson(jsonRequestBody)
.build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.apiJsonSerializerService.serialize(result);
}
@PUT
@Path("{mappingId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateGLAccount(@PathParam("mappingId") final Long mappingId, final String jsonRequestBody) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateOfficeToGLAccountMapping(mappingId)
.withJson(jsonRequestBody).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.apiJsonSerializerService.serialize(result);
}
@DELETE
@Path("{mappingId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteGLAccount(@PathParam("mappingId") final Long mappingId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteOfficeToGLAccountMapping(mappingId).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.apiJsonSerializerService.serialize(result);
}
}
@@ -0,0 +1,47 @@
package org.mifosplatform.accounting.accountmapping.data;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.mifosplatform.accounting.glaccount.data.GLAccountData;
import org.mifosplatform.organisation.office.data.OfficeData;
public class OfficeToGLAccountMappingData {
private final Long id;
private final OfficeData officeData;
private final GLAccountData glAccountData;
private final Map<String, List<GLAccountData>> accountingMappingOptions;
private final Collection<OfficeData> officeOptions;
public static OfficeToGLAccountMappingData instance(final Long id, final OfficeData officeData, final GLAccountData glAccountData) {
final Map<String, List<GLAccountData>> accountingMappingOptions = null;
final Collection<OfficeData> officeOptions = null;
return new OfficeToGLAccountMappingData(id, officeData, glAccountData, accountingMappingOptions, officeOptions);
}
public static OfficeToGLAccountMappingData template(final Map<String, List<GLAccountData>> accountingMappingOptions,
final Collection<OfficeData> officeOptions) {
final Long id = null;
final OfficeData officeData = null;
final GLAccountData glAccountData = null;
return new OfficeToGLAccountMappingData(id, officeData, glAccountData, accountingMappingOptions, officeOptions);
}
public static OfficeToGLAccountMappingData associateTemplateData(final OfficeToGLAccountMappingData templateData,
final OfficeToGLAccountMappingData accountMappingData) {
return new OfficeToGLAccountMappingData(accountMappingData.id, accountMappingData.officeData, accountMappingData.glAccountData,
templateData.accountingMappingOptions, templateData.officeOptions);
}
private OfficeToGLAccountMappingData(final Long id, final OfficeData officeData, final GLAccountData glAccountData,
final Map<String, List<GLAccountData>> accountingMappingOptions, final Collection<OfficeData> officeOptions) {
this.id = id;
this.officeData = officeData;
this.glAccountData = glAccountData;
this.accountingMappingOptions = accountingMappingOptions;
this.officeOptions = officeOptions;
}
}
@@ -0,0 +1,69 @@
/**
* 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.accounting.accountmapping.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.mifosplatform.accounting.glaccount.domain.GLAccount;
import org.mifosplatform.organisation.office.domain.Office;
import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity
@Table(name = "acc_gl_office_mapping")
public class OfficeToGLAccountMapping extends AbstractPersistable<Long> {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "gl_account_id")
private GLAccount glAccount;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "office_id")
private Office office;
@Column(name = "financial_account_type", nullable = false)
private int financialAccountType;
public static OfficeToGLAccountMapping createNew(final GLAccount glAccount, final Office office, final int financialAccountType) {
return new OfficeToGLAccountMapping(glAccount, office, financialAccountType);
}
protected OfficeToGLAccountMapping() {
//
}
private OfficeToGLAccountMapping(final GLAccount glAccount, final Office office, final int financialAccountType) {
this.glAccount = glAccount;
this.office = office;
this.financialAccountType = financialAccountType;
}
public GLAccount glAccount() {
return this.glAccount;
}
public void updateGlAccount(final GLAccount glAccount) {
this.glAccount = glAccount;
}
public Office office() {
return this.office;
}
public void updateOffice(Office office) {
this.office = office;
}
public int getFinancialAccountType() {
return this.financialAccountType;
}
}
@@ -0,0 +1,23 @@
/**
* 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.accounting.accountmapping.domain;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface OfficeToGLAccountMappingRepository extends JpaRepository<OfficeToGLAccountMapping, Long>,
JpaSpecificationExecutor<OfficeToGLAccountMapping> {
@Query("from OfficeToGLAccountMapping otga where otga.office.id = :officeId and otga.financialAccountType = :financialAccountType")
OfficeToGLAccountMapping findByOfficeAndFinancialAccountType(@Param("officeId")Long officeId,@Param("financialAccountType") int financialAccountType);
@Query("from OfficeToGLAccountMapping otga where otga.office.id =:officeId")
List<OfficeToGLAccountMapping> findByOffice(@Param("officeId")Long officeId);
}
@@ -0,0 +1,55 @@
/**
* 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.accounting.accountmapping.domain;
import java.util.List;
import org.mifosplatform.accounting.accountmapping.exception.OfficeToGLAccountMappingNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* <p>
* Wrapper for {@link OfficeToGLAccountMappingRepository} that adds NULL
* checking and Error handling capabilities
* </p>
*/
@Service
public class OfficeToGLAccountMappingRepositoryWrapper {
private final OfficeToGLAccountMappingRepository repository;
@Autowired
public OfficeToGLAccountMappingRepositoryWrapper(final OfficeToGLAccountMappingRepository repository) {
this.repository = repository;
}
public OfficeToGLAccountMapping findOneWithNotFoundDetection(final Long id) {
final OfficeToGLAccountMapping officeToGLAccountMapping = this.repository.findOne(id);
if (officeToGLAccountMapping == null) { throw new OfficeToGLAccountMappingNotFoundException(id); }
return officeToGLAccountMapping;
}
public OfficeToGLAccountMapping findByOfficeAndFinancialAccountType(final Long officeId, final int financialAccountType) {
return this.repository.findByOfficeAndFinancialAccountType(officeId, financialAccountType);
}
public List<OfficeToGLAccountMapping> findByOffice(final Long officeId) {
return this.repository.findByOffice(officeId);
}
public void save(final OfficeToGLAccountMapping entity) {
this.repository.save(entity);
}
public void saveAndFlush(final OfficeToGLAccountMapping entity) {
this.repository.saveAndFlush(entity);
}
public void delete(final OfficeToGLAccountMapping entity) {
this.repository.delete(entity);
}
}
@@ -0,0 +1,21 @@
/**
* 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.accounting.accountmapping.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
/**
* A {@link RuntimeException} thrown when product to GL account mapping are not
* found.
*/
public class DuplicateOfficeToGLAccountMappingFoundException extends AbstractPlatformDomainRuleException {
public DuplicateOfficeToGLAccountMappingFoundException(final Long officeId, final Integer accountType) {
super("error.msg.officeToAccountMapping.exists.for.office", "Mapping for office with Id " + officeId
+ " exist for an account of type " + accountType, officeId, accountType);
}
}
@@ -0,0 +1,19 @@
/**
* 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.accounting.accountmapping.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
/**
* A {@link RuntimeException} thrown when Calendar resources are not found.
*/
public class MappingUpdateNotSupportedException extends AbstractPlatformDomainRuleException {
public MappingUpdateNotSupportedException(final String postFix, final String defaultUserMessage,
final Object... defaultUserMessageArgs) {
super("error.msg.officeToAccountMapping.update.of." + postFix + ".is.not.supported", defaultUserMessage, defaultUserMessageArgs);
}
}
@@ -0,0 +1,24 @@
/**
* 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.accounting.accountmapping.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
/**
* A {@link RuntimeException} thrown when product to GL account mapping are not
* found.
*/
public class OfficeToGLAccountMappingNotFoundException extends AbstractPlatformResourceNotFoundException {
public OfficeToGLAccountMappingNotFoundException(final Long officeId, final String accountType) {
super("error.msg.officeToAccountMapping.not.found", "Mapping for office with Id " + officeId
+ " does not exist for an account of type " + accountType, officeId, accountType);
}
public OfficeToGLAccountMappingNotFoundException(final Long id) {
super("error.msg.officeToAccountMapping.not.found", "Mapping for GL Account with Id " + id + " does not exist", id);
}
}
@@ -0,0 +1,32 @@
/**
* 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.accounting.accountmapping.handler;
import org.mifosplatform.accounting.accountmapping.service.OfficeToGLAccountMappingWritePlatformService;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class CreateOfficeToGLAccountMappingHandler implements NewCommandSourceHandler {
private final OfficeToGLAccountMappingWritePlatformService writePlatformService;
@Autowired
public CreateOfficeToGLAccountMappingHandler(final OfficeToGLAccountMappingWritePlatformService writePlatformService) {
this.writePlatformService = writePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.createGLAccountMapping(command);
}
}
@@ -0,0 +1,31 @@
/**
* 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.accounting.accountmapping.handler;
import org.mifosplatform.accounting.accountmapping.service.OfficeToGLAccountMappingWritePlatformService;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class DeleteOfficeToGLAccountMappingCommandHandler implements NewCommandSourceHandler {
private final OfficeToGLAccountMappingWritePlatformService writePlatformService;
@Autowired
public DeleteOfficeToGLAccountMappingCommandHandler(final OfficeToGLAccountMappingWritePlatformService writePlatformService) {
this.writePlatformService = writePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.deleteGLAccountMapping(command.entityId(), command);
}
}
@@ -0,0 +1,31 @@
/**
* 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.accounting.accountmapping.handler;
import org.mifosplatform.accounting.accountmapping.service.OfficeToGLAccountMappingWritePlatformService;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UpdateOfficeToGLAccountMappingCommandHandler implements NewCommandSourceHandler {
private final OfficeToGLAccountMappingWritePlatformService writePlatformService;
@Autowired
public UpdateOfficeToGLAccountMappingCommandHandler(final OfficeToGLAccountMappingWritePlatformService writePlatformService) {
this.writePlatformService = writePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.updateGLAccountMapping(command.entityId(), command);
}
}
@@ -0,0 +1,98 @@
/**
* 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.accounting.accountmapping.serialization;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.mifosplatform.accounting.common.AccountingConstants.ORGANIZATION_ACCOUNTING_PARAMS;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
@Component
public final class OfficeToGLAccountMappingDataValidator {
/**
* The parameters supported for this command.
*/
private final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("locale",
ORGANIZATION_ACCOUNTING_PARAMS.LIABILITY_TRANSFER_SUSPENSE.getValue(), "officeId"));
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public OfficeToGLAccountMappingDataValidator(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
public void validateForCreate(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loanproduct");
final JsonElement element = this.fromApiJsonHelper.parse(json);
final Long liabilityTransferInSuspenseAccountId = this.fromApiJsonHelper.extractLongNamed(
ORGANIZATION_ACCOUNTING_PARAMS.LIABILITY_TRANSFER_SUSPENSE.getValue(), element);
baseDataValidator.reset().parameter(ORGANIZATION_ACCOUNTING_PARAMS.LIABILITY_TRANSFER_SUSPENSE.getValue())
.value(liabilityTransferInSuspenseAccountId).notNull().integerGreaterThanZero();
final Long officeID = this.fromApiJsonHelper.extractLongNamed("officeId", element);
baseDataValidator.reset().parameter("officeId").value(officeID).notNull().integerGreaterThanZero();
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
public void validateForUpdate(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loanproduct");
final JsonElement element = this.fromApiJsonHelper.parse(json);
if (this.fromApiJsonHelper.parameterExists(ORGANIZATION_ACCOUNTING_PARAMS.LIABILITY_TRANSFER_SUSPENSE.getValue(), element)) {
final Long liabilityTransferInSuspenseAccountId = this.fromApiJsonHelper.extractLongNamed(
ORGANIZATION_ACCOUNTING_PARAMS.LIABILITY_TRANSFER_SUSPENSE.getValue(), element);
baseDataValidator.reset().parameter(ORGANIZATION_ACCOUNTING_PARAMS.LIABILITY_TRANSFER_SUSPENSE.getValue())
.value(liabilityTransferInSuspenseAccountId).notNull().integerGreaterThanZero();
}
if (this.fromApiJsonHelper.parameterExists("officeId", element)) {
final Long officeID = this.fromApiJsonHelper.extractLongNamed("officeId", element);
baseDataValidator.reset().parameter("officeId").value(officeID).notNull().integerGreaterThanZero();
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -0,0 +1,21 @@
/**
* 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.accounting.accountmapping.service;
import org.mifosplatform.accounting.accountmapping.data.OfficeToGLAccountMappingData;
import org.mifosplatform.infrastructure.core.service.Page;
import org.mifosplatform.portfolio.group.service.SearchParameters;
public interface OfficeToGLAccountMappingReadPlatformService {
Page<OfficeToGLAccountMappingData> retrieveAll(final SearchParameters searchParameters);
OfficeToGLAccountMappingData retrieve(Long mappingId);
OfficeToGLAccountMappingData retrieveTemplate();
}
@@ -0,0 +1,136 @@
package org.mifosplatform.accounting.accountmapping.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.joda.time.LocalDate;
import org.mifosplatform.accounting.accountmapping.data.OfficeToGLAccountMappingData;
import org.mifosplatform.accounting.accountmapping.exception.OfficeToGLAccountMappingNotFoundException;
import org.mifosplatform.accounting.common.AccountingDropdownReadPlatformService;
import org.mifosplatform.accounting.glaccount.data.GLAccountData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.Page;
import org.mifosplatform.infrastructure.core.service.PaginationHelper;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.organisation.office.service.OfficeReadPlatformService;
import org.mifosplatform.portfolio.group.service.SearchParameters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
public class OfficeToGLAccountMappingReadPlatformServiceImpl implements OfficeToGLAccountMappingReadPlatformService {
private final JdbcTemplate jdbcTemplate;
private final OfficeToGLAccountMappingMapper accountMappingMapper;
private final PaginationHelper<OfficeToGLAccountMappingData> paginationHelper = new PaginationHelper<OfficeToGLAccountMappingData>();
private final OfficeReadPlatformService officeReadPlatformService;
private final AccountingDropdownReadPlatformService accountingDropdownReadPlatformService;
@Autowired
public OfficeToGLAccountMappingReadPlatformServiceImpl(final RoutingDataSource dataSource,
final OfficeReadPlatformService officeReadPlatformService,
final AccountingDropdownReadPlatformService accountingDropdownReadPlatformService) {
accountMappingMapper = new OfficeToGLAccountMappingMapper();
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.officeReadPlatformService = officeReadPlatformService;
this.accountingDropdownReadPlatformService = accountingDropdownReadPlatformService;
}
@Override
public Page<OfficeToGLAccountMappingData> retrieveAll(final SearchParameters searchParameters) {
StringBuilder sqlBuilder = new StringBuilder(300);
sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
sqlBuilder.append(this.accountMappingMapper.schema());
Object[] finalObjectArray = {};
if (searchParameters.isOrderByRequested()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
sqlBuilder.append(" limit ").append(searchParameters.getLimit());
if (searchParameters.isOffset()) {
sqlBuilder.append(" offset ").append(searchParameters.getOffset());
}
}
final String sqlCountRows = "SELECT FOUND_ROWS()";
return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows, sqlBuilder.toString(), finalObjectArray,
this.accountMappingMapper);
}
@Override
public OfficeToGLAccountMappingData retrieve(Long mappingId) {
try {
StringBuilder sqlBuilder = new StringBuilder(200);
sqlBuilder.append("select ");
sqlBuilder.append(this.accountMappingMapper.schema());
sqlBuilder.append(" where om.id=?");
return this.jdbcTemplate.queryForObject(sqlBuilder.toString(), this.accountMappingMapper, new Object[] { mappingId });
} catch (final EmptyResultDataAccessException e) {
throw new OfficeToGLAccountMappingNotFoundException(mappingId);
}
}
@Override
public OfficeToGLAccountMappingData retrieveTemplate() {
Collection<OfficeData> officeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
final Map<String, List<GLAccountData>> accountOptions = this.accountingDropdownReadPlatformService.retrieveAccountMappingOptions();
return OfficeToGLAccountMappingData.template(accountOptions, officeOptions);
}
private static final class OfficeToGLAccountMappingMapper implements RowMapper<OfficeToGLAccountMappingData> {
private final String sql;
public OfficeToGLAccountMappingMapper() {
StringBuilder sb = new StringBuilder(300);
sb.append("om.id , office.id as officeId, office.name as officeName, ");
sb.append(" glaccount.id as glAccountId,glaccount.name as glAccountName,glaccount.gl_code as glCode ");
sb.append(" from acc_gl_office_mapping om ");
sb.append("inner join m_office office on office.id = om.office_id ");
sb.append("inner join acc_gl_account glaccount on glaccount.id = om.gl_account_id");
sql = sb.toString();
}
public String schema() {
return sql;
}
@Override
public OfficeToGLAccountMappingData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = JdbcSupport.getLong(rs, "id");
final Long officeId = JdbcSupport.getLong(rs, "officeId");
final String officeName = rs.getString("officeName");
final String nameDecorated = null;
final String externalId = null;
final LocalDate openingDate = null;
final String hierarchy = null;
final Long parentId = null;
final String parentName = null;
final Collection<OfficeData> allowedParents = null;
final OfficeData officeData = new OfficeData(officeId, officeName, nameDecorated, externalId, openingDate, hierarchy, parentId,
parentName, allowedParents);
final Long glAccountId = JdbcSupport.getLong(rs, "glAccountId");
final String glAccountName = rs.getString("glAccountName");
final String glCode = rs.getString("glCode");
final GLAccountData gLAccountData = new GLAccountData(glAccountId, glAccountName, glCode);
final OfficeToGLAccountMappingData accountMappingData = OfficeToGLAccountMappingData.instance(id, officeData, gLAccountData);
return accountMappingData;
}
}
}
@@ -0,0 +1,19 @@
/**
* 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.accounting.accountmapping.service;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
public interface OfficeToGLAccountMappingWritePlatformService {
CommandProcessingResult createGLAccountMapping(JsonCommand command);
CommandProcessingResult updateGLAccountMapping(Long mappingId, JsonCommand command);
CommandProcessingResult deleteGLAccountMapping(Long mappingId, JsonCommand command);
}
@@ -0,0 +1,157 @@
package org.mifosplatform.accounting.accountmapping.service;
import java.util.HashMap;
import java.util.Map;
import org.mifosplatform.accounting.accountmapping.domain.OfficeToGLAccountMapping;
import org.mifosplatform.accounting.accountmapping.domain.OfficeToGLAccountMappingRepositoryWrapper;
import org.mifosplatform.accounting.accountmapping.exception.DuplicateOfficeToGLAccountMappingFoundException;
import org.mifosplatform.accounting.accountmapping.exception.MappingUpdateNotSupportedException;
import org.mifosplatform.accounting.accountmapping.serialization.OfficeToGLAccountMappingDataValidator;
import org.mifosplatform.accounting.common.AccountingConstants.ORGANIZATION_ACCOUNTING_PARAMS;
import org.mifosplatform.accounting.common.AccountingConstants.ORGANIZATION_ACCOUNTS;
import org.mifosplatform.accounting.glaccount.domain.GLAccount;
import org.mifosplatform.accounting.glaccount.domain.GLAccountRepositoryWrapper;
import org.mifosplatform.accounting.glaccount.domain.GLAccountType;
import org.mifosplatform.accounting.producttoaccountmapping.exception.ProductToGLAccountMappingInvalidException;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.office.domain.OfficeRepositoryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.google.gson.JsonElement;
@Service
public class OfficeToGLAccountMappingWritePlatformServiceImpl implements OfficeToGLAccountMappingWritePlatformService {
private final OfficeToGLAccountMappingRepositoryWrapper accountMappingRepository;
private final OfficeToGLAccountMappingDataValidator fromApiJsonDeserializer;
private final FromJsonHelper fromApiJsonHelper;
private final GLAccountRepositoryWrapper glAccountRepositoryWrapper;
private final OfficeRepositoryWrapper officeRepositoryWrapper;
@Autowired
public OfficeToGLAccountMappingWritePlatformServiceImpl(final OfficeToGLAccountMappingRepositoryWrapper accountMappingRepository,
final OfficeToGLAccountMappingDataValidator fromApiJsonDeserializer, final FromJsonHelper fromApiJsonHelper,
final GLAccountRepositoryWrapper glAccountRepositoryWrapper, final OfficeRepositoryWrapper officeRepositoryWrapper) {
this.accountMappingRepository = accountMappingRepository;
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.fromApiJsonHelper = fromApiJsonHelper;
this.glAccountRepositoryWrapper = glAccountRepositoryWrapper;
this.officeRepositoryWrapper = officeRepositoryWrapper;
}
@Override
public CommandProcessingResult createGLAccountMapping(JsonCommand command) {
this.fromApiJsonDeserializer.validateForCreate(command.json());
final JsonElement element = this.fromApiJsonHelper.parse(command.json());
final Long officeId = this.fromApiJsonHelper.extractLongNamed("officeId", element);
final Office office = this.officeRepositoryWrapper.findOneWithNotFoundDetection(officeId);
OfficeToGLAccountMapping accountMapping = createLiabilityTrasferSuspenceMapping(office, element);
checkForExistingMapping(accountMapping);
this.accountMappingRepository.save(accountMapping);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(accountMapping.getId()) //
.build();
}
private void checkForExistingMapping(final OfficeToGLAccountMapping accountMapping) {
OfficeToGLAccountMapping existingMapping = this.accountMappingRepository.findByOfficeAndFinancialAccountType(accountMapping
.office().getId(), accountMapping.getFinancialAccountType());
if (existingMapping != null && !existingMapping.getId().equals(accountMapping.getId())) { throw new DuplicateOfficeToGLAccountMappingFoundException(
accountMapping.office().getId(), accountMapping.getFinancialAccountType()); }
}
@Override
public CommandProcessingResult updateGLAccountMapping(Long mappingId, JsonCommand command) {
this.fromApiJsonDeserializer.validateForUpdate(command.json());
final OfficeToGLAccountMapping officeToGLAccountMapping = this.accountMappingRepository.findOneWithNotFoundDetection(mappingId);
Map<String, Object> changes = findChanges(command, officeToGLAccountMapping);
final JsonElement element = this.fromApiJsonHelper.parse(command.json());
if (changes.containsKey(ORGANIZATION_ACCOUNTING_PARAMS.LIABILITY_TRANSFER_SUSPENSE.getValue())) {
final GLAccount glAccount = fetchGLAccount(element, ORGANIZATION_ACCOUNTING_PARAMS.LIABILITY_TRANSFER_SUSPENSE.getValue(),
GLAccountType.LIABILITY);
officeToGLAccountMapping.updateGlAccount(glAccount);
}
if (!changes.isEmpty()) {
checkForExistingMapping(officeToGLAccountMapping);
this.accountMappingRepository.save(officeToGLAccountMapping);
}
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(mappingId) //
.with(changes) //
.build();
}
@Override
public CommandProcessingResult deleteGLAccountMapping(Long mappingId, JsonCommand command) {
final OfficeToGLAccountMapping officeToGLAccountMapping = this.accountMappingRepository.findOneWithNotFoundDetection(mappingId);
this.accountMappingRepository.delete(officeToGLAccountMapping);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(mappingId) //
.build();
}
private OfficeToGLAccountMapping createLiabilityTrasferSuspenceMapping(final Office office, final JsonElement element) {
final GLAccount glAccount = fetchGLAccount(element, ORGANIZATION_ACCOUNTING_PARAMS.LIABILITY_TRANSFER_SUSPENSE.getValue(),
GLAccountType.LIABILITY);
final Integer financialAccountType = ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue();
return OfficeToGLAccountMapping.createNew(glAccount, office, financialAccountType);
}
private GLAccount fetchGLAccount(final JsonElement element, final String paramName, final GLAccountType expectedAccountType) {
final Long accountId = this.fromApiJsonHelper.extractLongNamed(paramName, element);
final GLAccount glAccount = getAccountByIdAndType(paramName, expectedAccountType, accountId);
return glAccount;
}
/**
* Fetches account with a particular Id and throws and Exception it is not
* of the expected Account Category ('ASSET','liability' etc)
*
* @param paramName
* @param expectedAccountType
* @param accountId
* @return
*/
public GLAccount getAccountByIdAndType(final String paramName, final GLAccountType expectedAccountType, final Long accountId) {
final GLAccount glAccount = this.glAccountRepositoryWrapper.findOneWithNotFoundDetection(accountId);
// validate account is of the expected Type
if (glAccount.getType().intValue() != expectedAccountType.getValue()) { throw new ProductToGLAccountMappingInvalidException(
paramName, glAccount.getName(), accountId, GLAccountType.fromInt(glAccount.getType()).toString(),
expectedAccountType.toString()); }
return glAccount;
}
public Map<String, Object> findChanges(JsonCommand command, OfficeToGLAccountMapping accountMapping) {
Map<String, Object> changes = new HashMap<String, Object>();
final String officeParamName = "officeId";
Long existingOfficeId = accountMapping.office().getId();
if (command.isChangeInLongParameterNamed(officeParamName, existingOfficeId)) {
final Long newValue = command.longValueOfParameterNamed(officeParamName);
String defaultMsg = "Office updating not allowed ";
throw new MappingUpdateNotSupportedException("officeId", defaultMsg, newValue,existingOfficeId,accountMapping.getId());
}
Long existingGLAccountId = accountMapping.glAccount().getId();
if (command
.isChangeInLongParameterNamed(ORGANIZATION_ACCOUNTING_PARAMS.LIABILITY_TRANSFER_SUSPENSE.getValue(), existingGLAccountId)) {
final Long newValue = command.longValueOfParameterNamed(ORGANIZATION_ACCOUNTING_PARAMS.LIABILITY_TRANSFER_SUSPENSE.getValue());
changes.put(ORGANIZATION_ACCOUNTING_PARAMS.LIABILITY_TRANSFER_SUSPENSE.getValue(), newValue);
}
return changes;
}
}
@@ -13,7 +13,7 @@ public class AccountingConstants {
/*** Accounting placeholders for cash based accounting for loan products ***/
public static enum CASH_ACCOUNTS_FOR_LOAN {
FUND_SOURCE(1), LOAN_PORTFOLIO(2), INTEREST_ON_LOANS(3), INCOME_FROM_FEES(4), INCOME_FROM_PENALTIES(5), LOSSES_WRITTEN_OFF(6), TRANSFERS_SUSPENSE(
10), OVERPAYMENT(11),INCOME_FROM_RECOVERY(12);
10), OVERPAYMENT(11), INCOME_FROM_RECOVERY(12);
private final Integer value;
@@ -46,7 +46,7 @@ public class AccountingConstants {
/*** Accounting placeholders for accrual based accounting for loan products ***/
public static enum ACCRUAL_ACCOUNTS_FOR_LOAN {
FUND_SOURCE(1), LOAN_PORTFOLIO(2), INTEREST_ON_LOANS(3), INCOME_FROM_FEES(4), INCOME_FROM_PENALTIES(5), LOSSES_WRITTEN_OFF(6), INTEREST_RECEIVABLE(
7), FEES_RECEIVABLE(8), PENALTIES_RECEIVABLE(9), TRANSFERS_SUSPENSE(10), OVERPAYMENT(11),INCOME_FROM_RECOVERY(12);
7), FEES_RECEIVABLE(8), PENALTIES_RECEIVABLE(9), TRANSFERS_SUSPENSE(10), OVERPAYMENT(11), INCOME_FROM_RECOVERY(12);
private final Integer value;
@@ -88,8 +88,8 @@ public class AccountingConstants {
"receivableFeeAccountId"), PENALTIES_RECEIVABLE("receivablePenaltyAccountId"), TRANSFERS_SUSPENSE(
"transfersInSuspenseAccountId"), PAYMENT_CHANNEL_FUND_SOURCE_MAPPING("paymentChannelToFundSourceMappings"), PAYMENT_TYPE(
"paymentTypeId"), FEE_INCOME_ACCOUNT_MAPPING("feeToIncomeAccountMappings"), PENALTY_INCOME_ACCOUNT_MAPPING(
"penaltyToIncomeAccountMappings"), CHARGE_ID("chargeId"), INCOME_ACCOUNT_ID("incomeAccountId"),
INCOME_FROM_RECOVERY("incomeFromRecoveryAccountId");
"penaltyToIncomeAccountMappings"), CHARGE_ID("chargeId"), INCOME_ACCOUNT_ID("incomeAccountId"), INCOME_FROM_RECOVERY(
"incomeFromRecoveryAccountId");
private final String value;
@@ -111,8 +111,8 @@ public class AccountingConstants {
FUND_SOURCE("fundSourceAccount"), LOAN_PORTFOLIO("loanPortfolioAccount"), INTEREST_ON_LOANS("interestOnLoanAccount"), INCOME_FROM_FEES(
"incomeFromFeeAccount"), INCOME_FROM_PENALTIES("incomeFromPenaltyAccount"), LOSSES_WRITTEN_OFF("writeOffAccount"), OVERPAYMENT(
"overpaymentLiabilityAccount"), INTEREST_RECEIVABLE("receivableInterestAccount"), FEES_RECEIVABLE("receivableFeeAccount"), PENALTIES_RECEIVABLE(
"receivablePenaltyAccount"), TRANSFERS_SUSPENSE("transfersInSuspenseAccount"), INCOME_ACCOUNT_ID("incomeAccount"),
INCOME_FROM_RECOVERY("incomeFromRecoveryAccount");
"receivablePenaltyAccount"), TRANSFERS_SUSPENSE("transfersInSuspenseAccount"), INCOME_ACCOUNT_ID("incomeAccount"), INCOME_FROM_RECOVERY(
"incomeFromRecoveryAccount"), LIABILITY_TRANSFER_SUSPENSE("liabilityTransferInSuspenseAccount");
private final String value;
@@ -215,6 +215,83 @@ public class AccountingConstants {
}
}
public static enum ORGANIZATION_ACCOUNTS {
LIABILITY_TRANSFER_SUSPENSE(100);
private final Integer value;
private ORGANIZATION_ACCOUNTS(final Integer value) {
this.value = value;
}
@Override
public String toString() {
return name().toString().replaceAll("_", " ");
}
public Integer getValue() {
return this.value;
}
private static final Map<Integer, ORGANIZATION_ACCOUNTS> intToEnumMap = new HashMap<Integer, ORGANIZATION_ACCOUNTS>();
static {
for (final ORGANIZATION_ACCOUNTS type : ORGANIZATION_ACCOUNTS.values()) {
intToEnumMap.put(type.value, type);
}
}
public static ORGANIZATION_ACCOUNTS fromInt(final int i) {
final ORGANIZATION_ACCOUNTS type = intToEnumMap.get(Integer.valueOf(i));
return type;
}
}
/***
* Enum of all accounting related input parameter names used while
* creating/updating a loan product
***/
public static enum ORGANIZATION_ACCOUNTING_PARAMS {
LIABILITY_TRANSFER_SUSPENSE("liabilityTransferInSuspenseAccountId");
private final String value;
private ORGANIZATION_ACCOUNTING_PARAMS(final String value) {
this.value = value;
}
@Override
public String toString() {
return name().toString().replaceAll("_", " ");
}
public String getValue() {
return this.value;
}
}
/***
* Enum of all accounting related input parameter names used while
* creating/updating a loan product
***/
public static enum ORGANIZATION_ACCOUNTING_DATA_PARAMS {
LIABILITY_TRANSFER_SUSPENSE("liabilityTransferInSuspenseAccount");
private final String value;
private ORGANIZATION_ACCOUNTING_DATA_PARAMS(final String value) {
this.value = value;
}
@Override
public String toString() {
return name().toString().replaceAll("_", " ");
}
public String getValue() {
return this.value;
}
}
public static final String ASSESTS_TAG_OPTION_CODE_NAME = "AssetAccountTags";
public static final String LIABILITIES_TAG_OPTION_CODE_NAME = "LiabilityAccountTags";
public static final String EQUITY_TAG_OPTION_CODE_NAME = "EquityAccountTags";
@@ -25,4 +25,6 @@ public interface AccountingDropdownReadPlatformService {
public Map<String, List<GLAccountData>> retrieveAccountMappingOptionsForSavingsProducts();
public Map<String, List<GLAccountData>> retrieveAccountMappingOptions();
}
@@ -50,6 +50,16 @@ public class AccountingDropdownReadPlatformServiceImpl implements AccountingDrop
@Override
public Map<String, List<GLAccountData>> retrieveAccountMappingOptionsForLoanProducts() {
return retrieveAccountMappingOptions();
}
@Override
public Map<String, List<GLAccountData>> retrieveAccountMappingOptionsForSavingsProducts() {
return retrieveAccountMappingOptions();
}
@Override
public Map<String, List<GLAccountData>> retrieveAccountMappingOptions() {
final Map<String, List<GLAccountData>> accountOptions = new HashMap<String, List<GLAccountData>>();
List<GLAccountData> assetAccountOptions = this.accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GLAccountType.ASSET);
if (assetAccountOptions.isEmpty()) {
@@ -79,16 +89,4 @@ public class AccountingDropdownReadPlatformServiceImpl implements AccountingDrop
return accountOptions;
}
@Override
public Map<String, List<GLAccountData>> retrieveAccountMappingOptionsForSavingsProducts() {
final Map<String, List<GLAccountData>> accountOptions = retrieveAccountMappingOptionsForLoanProducts();
List<GLAccountData> liabilityAccountOptions = this.accountReadPlatformService
.retrieveAllEnabledDetailGLAccounts(GLAccountType.LIABILITY);
if (liabilityAccountOptions.isEmpty()) {
liabilityAccountOptions = null;
}
accountOptions.put("liabilityAccountOptions", liabilityAccountOptions);
return accountOptions;
}
}
@@ -36,10 +36,12 @@ public class LoanTransactionDTO {
private final List<ChargePaymentDTO> penaltyPayments;
private final List<ChargePaymentDTO> feePayments;
private final boolean isAccountTransfer;
public LoanTransactionDTO(final Long officeId, final Long paymentTypeId, final String transactionId, final Date transactionDate,
final LoanTransactionEnumData transactionType, final BigDecimal amount, final BigDecimal principal, final BigDecimal interest,
final BigDecimal fees, final BigDecimal penalties, final BigDecimal overPayment, final boolean reversed,
final List<ChargePaymentDTO> feePayments, final List<ChargePaymentDTO> penaltyPayments) {
final List<ChargePaymentDTO> feePayments, final List<ChargePaymentDTO> penaltyPayments, boolean isAccountTransfer) {
this.paymentTypeId = paymentTypeId;
this.transactionId = transactionId;
this.transactionDate = transactionDate;
@@ -54,6 +56,7 @@ public class LoanTransactionDTO {
this.penaltyPayments = penaltyPayments;
this.overPayment = overPayment;
this.officeId = officeId;
this.isAccountTransfer = isAccountTransfer;
}
public Long getOfficeId() {
@@ -112,4 +115,8 @@ public class LoanTransactionDTO {
return this.feePayments;
}
public boolean isAccountTransfer() {
return this.isAccountTransfer;
}
}
@@ -29,9 +29,12 @@ public class SavingsTransactionDTO {
private final List<ChargePaymentDTO> penaltyPayments;
private final List<ChargePaymentDTO> feePayments;
private final boolean isAccountTransfer;
public SavingsTransactionDTO(final Long officeId, final Long paymentTypeId, final String transactionId, final Date transactionDate,
final SavingsAccountTransactionEnumData transactionType, final BigDecimal amount, final boolean reversed,
final List<ChargePaymentDTO> feePayments, final List<ChargePaymentDTO> penaltyPayments, final BigDecimal overdraftAmount) {
final List<ChargePaymentDTO> feePayments, final List<ChargePaymentDTO> penaltyPayments, final BigDecimal overdraftAmount,
boolean isAccountTransfer) {
this.paymentTypeId = paymentTypeId;
this.transactionId = transactionId;
this.transactionDate = transactionDate;
@@ -42,6 +45,7 @@ public class SavingsTransactionDTO {
this.penaltyPayments = penaltyPayments;
this.officeId = officeId;
this.overdraftAmount = overdraftAmount;
this.isAccountTransfer = isAccountTransfer;
}
public Long getOfficeId() {
@@ -88,4 +92,8 @@ public class SavingsTransactionDTO {
return this.overdraftAmount != null && this.overdraftAmount.doubleValue() > 0;
}
public boolean isAccountTransfer() {
return this.isAccountTransfer;
}
}
@@ -14,11 +14,15 @@ import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.accounting.accountmapping.domain.OfficeToGLAccountMapping;
import org.mifosplatform.accounting.accountmapping.domain.OfficeToGLAccountMappingRepository;
import org.mifosplatform.accounting.accountmapping.exception.OfficeToGLAccountMappingNotFoundException;
import org.mifosplatform.accounting.closure.domain.GLClosure;
import org.mifosplatform.accounting.closure.domain.GLClosureRepository;
import org.mifosplatform.accounting.common.AccountingConstants.ACCRUAL_ACCOUNTS_FOR_LOAN;
import org.mifosplatform.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_LOAN;
import org.mifosplatform.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_SAVINGS;
import org.mifosplatform.accounting.common.AccountingConstants.ORGANIZATION_ACCOUNTS;
import org.mifosplatform.accounting.glaccount.domain.GLAccount;
import org.mifosplatform.accounting.journalentry.data.ChargePaymentDTO;
import org.mifosplatform.accounting.journalentry.data.LoanDTO;
@@ -55,6 +59,7 @@ public class AccountingProcessorHelper {
public static final String SAVINGS_TRANSACTION_IDENTIFIER = "S";
private final JournalEntryRepository glJournalEntryRepository;
private final ProductToGLAccountMappingRepository accountMappingRepository;
private final OfficeToGLAccountMappingRepository officeToGLAccountMappingRepository;
private final GLClosureRepository closureRepository;
private final OfficeRepository officeRepository;
private final LoanTransactionRepository loanTransactionRepository;
@@ -64,13 +69,15 @@ public class AccountingProcessorHelper {
public AccountingProcessorHelper(final JournalEntryRepository glJournalEntryRepository,
final ProductToGLAccountMappingRepository accountMappingRepository, final GLClosureRepository closureRepository,
final OfficeRepository officeRepository, final LoanTransactionRepository loanTransactionRepository,
final SavingsAccountTransactionRepository savingsAccountTransactionRepository) {
final SavingsAccountTransactionRepository savingsAccountTransactionRepository,
final OfficeToGLAccountMappingRepository officeToGLAccountMappingRepository) {
this.glJournalEntryRepository = glJournalEntryRepository;
this.accountMappingRepository = accountMappingRepository;
this.closureRepository = closureRepository;
this.officeRepository = officeRepository;
this.loanTransactionRepository = loanTransactionRepository;
this.savingsAccountTransactionRepository = savingsAccountTransactionRepository;
this.officeToGLAccountMappingRepository = officeToGLAccountMappingRepository;
}
public LoanDTO populateLoanDtoFromMap(final Map<String, Object> accountingBridgeData, final boolean cashBasedAccountingEnabled,
@@ -79,6 +86,7 @@ public class AccountingProcessorHelper {
final Long loanProductId = (Long) accountingBridgeData.get("loanProductId");
final Long officeId = (Long) accountingBridgeData.get("officeId");
final CurrencyData currencyData = (CurrencyData) accountingBridgeData.get("currency");
final boolean isAccountTransfer = (Boolean) accountingBridgeData.get("isAccountTransfer");
final List<LoanTransactionDTO> newLoanTransactions = new ArrayList<LoanTransactionDTO>();
@@ -121,7 +129,7 @@ public class AccountingProcessorHelper {
final LoanTransactionDTO transaction = new LoanTransactionDTO(transactionOfficeId, paymentTypeId, transactionId,
transactionDate, transactionType, amount, principal, interest, fees, penalties, overPayments, reversed,
feePaymentDetails, penaltyPaymentDetails);
feePaymentDetails, penaltyPaymentDetails, isAccountTransfer);
newLoanTransactions.add(transaction);
@@ -137,6 +145,7 @@ public class AccountingProcessorHelper {
final Long loanProductId = (Long) accountingBridgeData.get("savingsProductId");
final Long officeId = (Long) accountingBridgeData.get("officeId");
final CurrencyData currencyData = (CurrencyData) accountingBridgeData.get("currency");
final boolean isAccountTransfer = (Boolean) accountingBridgeData.get("isAccountTransfer");
final List<SavingsTransactionDTO> newSavingsTransactions = new ArrayList<SavingsTransactionDTO>();
@SuppressWarnings("unchecked")
@@ -173,7 +182,7 @@ public class AccountingProcessorHelper {
}
final SavingsTransactionDTO transaction = new SavingsTransactionDTO(transactionOfficeId, paymentTypeId, transactionId,
transactionDate, transactionType, amount, reversed, feePayments, penaltyPayments, overdraftAmount);
transactionDate, transactionType, amount, reversed, feePayments, penaltyPayments, overdraftAmount, isAccountTransfer);
newSavingsTransactions.add(transaction);
@@ -204,15 +213,15 @@ public class AccountingProcessorHelper {
* @param isReversal
*/
public void createAccrualBasedJournalEntriesAndReversalsForLoan(final Office office, final String currencyCode,
final ACCRUAL_ACCOUNTS_FOR_LOAN accountTypeToBeDebited, final ACCRUAL_ACCOUNTS_FOR_LOAN accountTypeToBeCredited,
final Integer accountTypeToBeDebited, final Integer 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();
int accountTypeToDebitId = accountTypeToBeDebited;
int accountTypeToCreditId = accountTypeToBeCredited;
// reverse debits and credits for reversals
if (isReversal) {
accountTypeToDebitId = accountTypeToBeCredited.getValue();
accountTypeToCreditId = accountTypeToBeDebited.getValue();
accountTypeToDebitId = accountTypeToBeCredited;
accountTypeToCreditId = accountTypeToBeDebited;
}
createJournalEntriesForLoan(office, currencyCode, accountTypeToDebitId, accountTypeToCreditId, loanProductId, paymentTypeId,
loanId, transactionId, transactionDate, amount);
@@ -239,15 +248,15 @@ public class AccountingProcessorHelper {
* @param isReversal
*/
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) {
int accountTypeToDebitId = accountTypeToBeDebited.getValue();
int accountTypeToCreditId = accountTypeToBeCredited.getValue();
final Integer accountTypeToBeDebited, final Integer accountTypeToBeCredited, final Long savingsProductId,
final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate, final BigDecimal amount,
final Boolean isReversal) {
int accountTypeToDebitId = accountTypeToBeDebited;
int accountTypeToCreditId = accountTypeToBeCredited;
// reverse debits and credits for reversals
if (isReversal) {
accountTypeToDebitId = accountTypeToBeCredited.getValue();
accountTypeToCreditId = accountTypeToBeDebited.getValue();
accountTypeToDebitId = accountTypeToBeCredited;
accountTypeToCreditId = accountTypeToBeDebited;
}
createJournalEntriesForSavings(office, currencyCode, accountTypeToDebitId, accountTypeToCreditId, savingsProductId, paymentTypeId,
loanId, transactionId, transactionDate, amount);
@@ -274,15 +283,15 @@ public class AccountingProcessorHelper {
* @param 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();
final Integer accountTypeToBeDebited, final Integer 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;
int accountTypeToCreditId = accountTypeToBeCredited;
// reverse debits and credits for reversals
if (isReversal) {
accountTypeToDebitId = accountTypeToBeCredited.getValue();
accountTypeToCreditId = accountTypeToBeDebited.getValue();
accountTypeToDebitId = accountTypeToBeCredited;
accountTypeToCreditId = accountTypeToBeDebited;
}
createJournalEntriesForLoan(office, currencyCode, accountTypeToDebitId, accountTypeToCreditId, loanProductId, paymentTypeId,
loanId, transactionId, transactionDate, amount);
@@ -304,22 +313,6 @@ public class AccountingProcessorHelper {
transactionId, transactionDate, amount, 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) {
final int accountMappingTypeId = accountMappingType.getValue();
createDebitJournalEntryOrReversalForLoan(office, currencyCode, accountMappingTypeId, loanProductId, paymentTypeId, loanId,
transactionId, transactionDate, amount, 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) {
final int accountMappingTypeId = accountMappingType.getValue();
createDebitJournalEntryOrReversalForLoan(office, currencyCode, accountMappingTypeId, loanProductId, paymentTypeId, loanId,
transactionId, transactionDate, amount, isReversal);
}
/**
* @param latestGLClosure
* @param transactionDate
@@ -346,8 +339,9 @@ public class AccountingProcessorHelper {
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) {
final GLAccount debitAccount = getLinkedGLAccountForLoanProduct(loanProductId, accountTypeToDebitId, paymentTypeId);
final GLAccount creditAccount = getLinkedGLAccountForLoanProduct(loanProductId, accountTypeToCreditId, paymentTypeId);
final GLAccount debitAccount = getLinkedGLAccountForLoanProduct(loanProductId, accountTypeToDebitId, paymentTypeId, office.getId());
final GLAccount creditAccount = getLinkedGLAccountForLoanProduct(loanProductId, accountTypeToCreditId, paymentTypeId,
office.getId());
createDebitJournalEntryForLoan(office, currencyCode, debitAccount, loanId, transactionId, transactionDate, amount);
createCreditJournalEntryForLoan(office, currencyCode, creditAccount, loanId, transactionId, transactionDate, amount);
}
@@ -355,16 +349,18 @@ public class AccountingProcessorHelper {
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) {
final GLAccount debitAccount = getLinkedGLAccountForSavingsProduct(savingsProductId, accountTypeToDebitId, paymentTypeId);
final GLAccount creditAccount = getLinkedGLAccountForSavingsProduct(savingsProductId, accountTypeToCreditId, paymentTypeId);
final GLAccount debitAccount = getLinkedGLAccountForSavingsProduct(savingsProductId, accountTypeToDebitId, paymentTypeId,
office.getId());
final GLAccount creditAccount = getLinkedGLAccountForSavingsProduct(savingsProductId, accountTypeToCreditId, paymentTypeId,
office.getId());
createDebitJournalEntryForSavings(office, currencyCode, debitAccount, savingsId, transactionId, transactionDate, amount);
createCreditJournalEntryForSavings(office, currencyCode, creditAccount, savingsId, transactionId, transactionDate, amount);
}
private void createDebitJournalEntryOrReversalForLoan(final Office office, final String currencyCode, final int accountMappingTypeId,
public 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) {
final GLAccount account = getLinkedGLAccountForLoanProduct(loanProductId, accountMappingTypeId, paymentTypeId);
final GLAccount account = getLinkedGLAccountForLoanProduct(loanProductId, accountMappingTypeId, paymentTypeId, office.getId());
if (isReversal) {
createCreditJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
} else {
@@ -456,7 +452,7 @@ public class AccountingProcessorHelper {
final GLAccount chargeSpecificAccount = getLinkedGLAccountForSavingsCharges(savingsProductId, accountTypeToBeCredited.getValue(),
chargePaymentDTO.getChargeId());
final GLAccount savingsControlAccount = getLinkedGLAccountForSavingsProduct(savingsProductId, accountTypeToBeDebited.getValue(),
paymentTypeId);
paymentTypeId, office.getId());
if (isReversal) {
createDebitJournalEntryForSavings(office, currencyCode, chargeSpecificAccount, loanId, transactionId, transactionDate,
totalAmount);
@@ -481,7 +477,7 @@ public class AccountingProcessorHelper {
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) {
final GLAccount account = getLinkedGLAccountForLoanProduct(loanProductId, accountMappingTypeId, paymentTypeId);
final GLAccount account = getLinkedGLAccountForLoanProduct(loanProductId, accountMappingTypeId, paymentTypeId, office.getId());
if (isReversal) {
createDebitJournalEntryForLoan(office, currencyCode, account, loanId, transactionId, transactionDate, amount);
} else {
@@ -561,27 +557,38 @@ public class AccountingProcessorHelper {
this.glJournalEntryRepository.saveAndFlush(journalEntry);
}
private GLAccount getLinkedGLAccountForLoanProduct(final Long loanProductId, final int accountMappingTypeId, final Long paymentTypeId) {
ProductToGLAccountMapping accountMapping = this.accountMappingRepository.findCoreProductToFinAccountMapping(loanProductId,
PortfolioProductType.LOAN.getValue(), accountMappingTypeId);
/****
* Get more specific mapping for FUND source accounts (based on payment
* channels). Note that fund source placeholder ID would be same for
* both cash and accrual accounts
***/
if (accountMappingTypeId == CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue()) {
final ProductToGLAccountMapping paymentChannelSpecificAccountMapping = this.accountMappingRepository
.findByProductIdAndProductTypeAndFinancialAccountTypeAndPaymentTypeId(loanProductId,
PortfolioProductType.LOAN.getValue(), accountMappingTypeId, paymentTypeId);
if (paymentChannelSpecificAccountMapping != null) {
accountMapping = paymentChannelSpecificAccountMapping;
private GLAccount getLinkedGLAccountForLoanProduct(final Long loanProductId, final int accountMappingTypeId, final Long paymentTypeId,
Long officeId) {
GLAccount glAccount = null;
if (isOrganizationAccount(accountMappingTypeId)) {
OfficeToGLAccountMapping accountMapping = this.officeToGLAccountMappingRepository.findByOfficeAndFinancialAccountType(officeId,
accountMappingTypeId);
if (accountMapping == null) { throw new OfficeToGLAccountMappingNotFoundException(officeId,
String.valueOf(accountMappingTypeId)); }
glAccount = accountMapping.glAccount();
} else {
ProductToGLAccountMapping accountMapping = this.accountMappingRepository.findCoreProductToFinAccountMapping(loanProductId,
PortfolioProductType.LOAN.getValue(), accountMappingTypeId);
/****
* Get more specific mapping for FUND source accounts (based on
* payment channels). Note that fund source placeholder ID would be
* same for both cash and accrual accounts
***/
if (accountMappingTypeId == CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue()) {
final ProductToGLAccountMapping paymentChannelSpecificAccountMapping = this.accountMappingRepository
.findByProductIdAndProductTypeAndFinancialAccountTypeAndPaymentTypeId(loanProductId,
PortfolioProductType.LOAN.getValue(), accountMappingTypeId, paymentTypeId);
if (paymentChannelSpecificAccountMapping != null) {
accountMapping = paymentChannelSpecificAccountMapping;
}
}
if (accountMapping == null) { throw new ProductToGLAccountMappingNotFoundException(PortfolioProductType.LOAN, loanProductId,
ACCRUAL_ACCOUNTS_FOR_LOAN.OVERPAYMENT.toString()); }
glAccount = accountMapping.getGlAccount();
}
if (accountMapping == null) { throw new ProductToGLAccountMappingNotFoundException(PortfolioProductType.LOAN, loanProductId,
ACCRUAL_ACCOUNTS_FOR_LOAN.OVERPAYMENT.toString()); }
return accountMapping.getGlAccount();
return glAccount;
}
private GLAccount getLinkedGLAccountForLoanCharges(final Long loanProductId, final int accountMappingTypeId, final Long chargeId) {
@@ -631,22 +638,40 @@ public class AccountingProcessorHelper {
}
private GLAccount getLinkedGLAccountForSavingsProduct(final Long savingsProductId, final int accountMappingTypeId,
final Long paymentTypeId) {
ProductToGLAccountMapping accountMapping = this.accountMappingRepository.findCoreProductToFinAccountMapping(savingsProductId,
PortfolioProductType.SAVING.getValue(), accountMappingTypeId);
/****
* Get more specific mapping for FUND source accounts (based on payment
* channels). Note that fund source placeholder ID would be same for
* both cash and accrual accounts
***/
if (accountMappingTypeId == CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.getValue()) {
final ProductToGLAccountMapping paymentChannelSpecificAccountMapping = this.accountMappingRepository
.findByProductIdAndProductTypeAndFinancialAccountTypeAndPaymentTypeId(savingsProductId,
PortfolioProductType.SAVING.getValue(), accountMappingTypeId, paymentTypeId);
if (paymentChannelSpecificAccountMapping != null) {
accountMapping = paymentChannelSpecificAccountMapping;
final Long paymentTypeId, Long officeId) {
GLAccount glAccount = null;
if (isOrganizationAccount(accountMappingTypeId)) {
OfficeToGLAccountMapping accountMapping = this.officeToGLAccountMappingRepository.findByOfficeAndFinancialAccountType(officeId,
accountMappingTypeId);
if (accountMapping == null) { throw new OfficeToGLAccountMappingNotFoundException(officeId,
String.valueOf(accountMappingTypeId)); }
glAccount = accountMapping.glAccount();
} else {
ProductToGLAccountMapping accountMapping = this.accountMappingRepository.findCoreProductToFinAccountMapping(savingsProductId,
PortfolioProductType.SAVING.getValue(), accountMappingTypeId);
/****
* Get more specific mapping for FUND source accounts (based on
* payment channels). Note that fund source placeholder ID would be
* same for both cash and accrual accounts
***/
if (accountMappingTypeId == CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.getValue()) {
final ProductToGLAccountMapping paymentChannelSpecificAccountMapping = this.accountMappingRepository
.findByProductIdAndProductTypeAndFinancialAccountTypeAndPaymentTypeId(savingsProductId,
PortfolioProductType.SAVING.getValue(), accountMappingTypeId, paymentTypeId);
if (paymentChannelSpecificAccountMapping != null) {
accountMapping = paymentChannelSpecificAccountMapping;
}
}
glAccount = accountMapping.getGlAccount();
}
return accountMapping.getGlAccount();
return glAccount;
}
private boolean isOrganizationAccount(final int accountMappingTypeId) {
boolean isOrganizationAccount = false;
if (ORGANIZATION_ACCOUNTS.fromInt(accountMappingTypeId) != null) {
isOrganizationAccount = true;
}
return isOrganizationAccount;
}
}
@@ -10,6 +10,8 @@ import java.util.Date;
import org.mifosplatform.accounting.closure.domain.GLClosure;
import org.mifosplatform.accounting.common.AccountingConstants.ACCRUAL_ACCOUNTS_FOR_LOAN;
import org.mifosplatform.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_LOAN;
import org.mifosplatform.accounting.common.AccountingConstants.ORGANIZATION_ACCOUNTS;
import org.mifosplatform.accounting.journalentry.data.LoanDTO;
import org.mifosplatform.accounting.journalentry.data.LoanTransactionDTO;
import org.mifosplatform.organisation.office.domain.Office;
@@ -60,6 +62,11 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
createJournalEntriesForRecoveryRepayments(loanDTO, loanTransactionDTO, office);
}
/** Logic for Refunds of Overpayments **/
else if (loanTransactionDTO.getTransactionType().isRefund()) {
createJournalEntriesForRefund(loanDTO, loanTransactionDTO, office);
}
/** Handle Write Offs, waivers and their reversals **/
else if ((loanTransactionDTO.getTransactionType().isWriteOff() || loanTransactionDTO.getTransactionType().isWaiveInterest() || loanTransactionDTO
.getTransactionType().isWaiveCharges())) {
@@ -92,9 +99,15 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// create journal entries for the disbursement (or disbursement
// reversal)
this.helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO,
ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE, loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
disbursalAmount, isReversed);
if (loanTransactionDTO.isAccountTransfer()) {
this.helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue(), ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue(),
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, disbursalAmount, isReversed);
} else {
this.helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue(), ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue(), loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, disbursalAmount, isReversed);
}
}
@@ -198,11 +211,19 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
* reversals)
***/
if (writeOff) {
this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF,
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode,
ACCRUAL_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
transactionDate, totalDebitAmount, isReversal);
} else {
this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE,
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
if (loanTransactionDTO.isAccountTransfer()) {
this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode,
ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
transactionDate, totalDebitAmount, isReversal);
} else {
this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode,
ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
transactionDate, totalDebitAmount, isReversal);
}
}
}
@@ -227,9 +248,9 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
this.helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE,
ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_RECOVERY, loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
amount, isReversal);
this.helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue(), ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_RECOVERY.getValue(), loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, amount, isReversal);
}
@@ -268,20 +289,44 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
// create journal entries for recognizing interest (or reversal)
if (interestAmount != null && !(interestAmount.compareTo(BigDecimal.ZERO) == 0)) {
this.helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE, ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS, loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, interestAmount, isReversed);
ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE.getValue(), ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS.getValue(),
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, interestAmount, isReversed);
}
// create journal entries for the fees application (or reversal)
if (feesAmount != null && !(feesAmount.compareTo(BigDecimal.ZERO) == 0)) {
this.helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
ACCRUAL_ACCOUNTS_FOR_LOAN.FEES_RECEIVABLE, ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES, loanProductId, paymentTypeId,
loanId, transactionId, transactionDate, feesAmount, isReversed);
ACCRUAL_ACCOUNTS_FOR_LOAN.FEES_RECEIVABLE.getValue(), ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue(),
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, feesAmount, isReversed);
}
// create journal entries for the penalties application (or reversal)
if (penaltiesAmount != null && !(penaltiesAmount.compareTo(BigDecimal.ZERO) == 0)) {
this.helper.createAccrualBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE, ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES, loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, penaltiesAmount, isReversed);
ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE.getValue(), ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue(),
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, penaltiesAmount, isReversed);
}
}
private void createJournalEntriesForRefund(final LoanDTO loanDTO, final LoanTransactionDTO loanTransactionDTO, final Office office) {
// loan properties
final Long loanProductId = loanDTO.getLoanProductId();
final Long loanId = loanDTO.getLoanId();
final String currencyCode = loanDTO.getCurrencyCode();
// transaction properties
final String transactionId = loanTransactionDTO.getTransactionId();
final Date transactionDate = loanTransactionDTO.getTransactionDate();
final BigDecimal refundAmount = loanTransactionDTO.getAmount();
final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
if (loanTransactionDTO.isAccountTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
CASH_ACCOUNTS_FOR_LOAN.OVERPAYMENT.getValue(), ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue(),
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, refundAmount, isReversal);
} else {
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
CASH_ACCOUNTS_FOR_LOAN.OVERPAYMENT.getValue(), CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue(), loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, refundAmount, isReversal);
}
}
}
@@ -10,6 +10,7 @@ import java.util.Date;
import org.mifosplatform.accounting.closure.domain.GLClosure;
import org.mifosplatform.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_LOAN;
import org.mifosplatform.accounting.common.AccountingConstants.ORGANIZATION_ACCOUNTS;
import org.mifosplatform.accounting.journalentry.data.LoanDTO;
import org.mifosplatform.accounting.journalentry.data.LoanTransactionDTO;
import org.mifosplatform.organisation.office.domain.Office;
@@ -73,8 +74,9 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
else if (loanTransactionDTO.getTransactionType().isWriteOff()) {
final BigDecimal principalAmount = loanTransactionDTO.getPrincipal();
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
CASH_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF, CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO, loanProductId, paymentTypeId,
loanId, transactionId, transactionDate, principalAmount, loanTransactionDTO.isReversed());
CASH_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF.getValue(), CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue(),
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, principalAmount,
loanTransactionDTO.isReversed());
} else if (loanTransactionDTO.getTransactionType().isInitiateTransfer()
|| loanTransactionDTO.getTransactionType().isApproveTransfer()
|| loanTransactionDTO.getTransactionType().isWithdrawTransfer()) {
@@ -107,10 +109,16 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
final BigDecimal disbursalAmount = loanTransactionDTO.getAmount();
final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
if (loanTransactionDTO.isAccountTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue(), ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue(),
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, disbursalAmount, isReversal);
} else {
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue(), CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue(), loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, disbursalAmount, isReversal);
}
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO,
CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE, loanProductId, paymentTypeId, loanId, transactionId, transactionDate, disbursalAmount,
isReversal);
}
/**
@@ -137,9 +145,15 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.OVERPAYMENT,
CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE, loanProductId, paymentTypeId, loanId, transactionId, transactionDate, refundAmount,
isReversal);
if (loanTransactionDTO.isAccountTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
CASH_ACCOUNTS_FOR_LOAN.OVERPAYMENT.getValue(), ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue(),
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, refundAmount, isReversal);
} else {
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
CASH_ACCOUNTS_FOR_LOAN.OVERPAYMENT.getValue(), CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue(), loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, refundAmount, isReversal);
}
}
/**
@@ -203,8 +217,14 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
}
/*** create a single debit entry (or reversal) for the entire amount **/
this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE, loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
if (loanTransactionDTO.isAccountTransfer()) {
this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode,
ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
transactionDate, totalDebitAmount, isReversal);
} else {
this.helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue(),
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount, isReversal);
}
}
/**
@@ -228,9 +248,9 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
final boolean isReversal = loanTransactionDTO.isReversed();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE,
CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_RECOVERY, loanProductId, paymentTypeId, loanId, transactionId, transactionDate, amount,
isReversal);
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue(),
CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_RECOVERY.getValue(), loanProductId, paymentTypeId, loanId, transactionId,
transactionDate, amount, isReversal);
}
@@ -261,14 +281,14 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
// final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
if (loanTransactionDTO.getTransactionType().isInitiateTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.TRANSFERS_SUSPENSE,
CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO, loanProductId, null, loanId, transactionId, transactionDate, principalAmount,
isReversal);
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
CASH_ACCOUNTS_FOR_LOAN.TRANSFERS_SUSPENSE.getValue(), CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue(), loanProductId,
null, loanId, transactionId, transactionDate, principalAmount, isReversal);
} else if (loanTransactionDTO.getTransactionType().isApproveTransfer()
|| loanTransactionDTO.getTransactionType().isWithdrawTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode, CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO,
CASH_ACCOUNTS_FOR_LOAN.TRANSFERS_SUSPENSE, loanProductId, null, loanId, transactionId, transactionDate,
principalAmount, isReversal);
this.helper.createCashBasedJournalEntriesAndReversalsForLoan(office, currencyCode,
CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue(), CASH_ACCOUNTS_FOR_LOAN.TRANSFERS_SUSPENSE.getValue(), loanProductId,
null, loanId, transactionId, transactionDate, principalAmount, isReversal);
}
}
}
@@ -11,6 +11,7 @@ import java.util.List;
import org.mifosplatform.accounting.closure.domain.GLClosure;
import org.mifosplatform.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_SAVINGS;
import org.mifosplatform.accounting.common.AccountingConstants.ORGANIZATION_ACCOUNTS;
import org.mifosplatform.accounting.journalentry.data.ChargePaymentDTO;
import org.mifosplatform.accounting.journalentry.data.SavingsDTO;
import org.mifosplatform.accounting.journalentry.data.SavingsTransactionDTO;
@@ -48,37 +49,81 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
this.helper.checkForBranchClosures(latestGLClosure, transactionDate);
if (savingsTransactionDTO.getTransactionType().isWithdrawal() && savingsTransactionDTO.isOverdraftTransaction()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE,
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, overdraftAmount, isReversal);
if (amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1) {
if (savingsTransactionDTO.isAccountTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount.subtract(overdraftAmount), isReversal);
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(),
ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, overdraftAmount, isReversal);
if (amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.getValue(),
ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, amount.subtract(overdraftAmount), isReversal);
}
} else {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(),
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, overdraftAmount, isReversal);
if (amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.getValue(),
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, amount.subtract(overdraftAmount), isReversal);
}
}
} else if (savingsTransactionDTO.getTransactionType().isDeposit() && savingsTransactionDTO.isOverdraftTransaction()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL,
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
if (amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1) {
if (savingsTransactionDTO.isAccountTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount.subtract(overdraftAmount), isReversal);
ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue(),
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, amount, isReversal);
if (amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue(),
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, amount.subtract(overdraftAmount), isReversal);
}
} else {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.getValue(),
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, amount, isReversal);
if (amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.getValue(),
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, amount.subtract(overdraftAmount), isReversal);
}
}
}
/** Handle Deposits and reversals of deposits **/
else if (savingsTransactionDTO.getTransactionType().isDeposit()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
if (savingsTransactionDTO.isAccountTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue(),
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, amount, isReversal);
} else {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.getValue(), CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
}
}
/** Handle withdrawals and reversals of withdrawals **/
else if (savingsTransactionDTO.getTransactionType().isWithdrawal()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
if (savingsTransactionDTO.isAccountTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.getValue(),
ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, amount, isReversal);
} else {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.getValue(), CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
}
}
/**
@@ -86,11 +131,12 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
* Applications
**/
else if (savingsTransactionDTO.getTransactionType().isInterestPosting()) {
//Post journal entry if earned interest amount is greater than zero
// Post journal entry if earned interest amount is greater than
// zero
if (savingsTransactionDTO.getAmount().compareTo(BigDecimal.ZERO) == 1) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS.getValue(), CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
}
}
@@ -111,27 +157,28 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
/** Handle Transfers proposal **/
else if (savingsTransactionDTO.getTransactionType().isInitiateTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.getValue(), CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
}
/** Handle Transfer Withdrawal or Acceptance **/
else if (savingsTransactionDTO.getTransactionType().isWithdrawTransfer()
|| savingsTransactionDTO.getTransactionType().isApproveTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE.getValue(), CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
}
/** overdraft **/
else if (savingsTransactionDTO.getTransactionType().isOverdraftInterest()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_INTEREST, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.getValue(), CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_INTEREST.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
} else if (savingsTransactionDTO.getTransactionType().isWrittenoff()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.LOSSES_WRITTEN_OFF, CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL,
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
CASH_ACCOUNTS_FOR_SAVINGS.LOSSES_WRITTEN_OFF.getValue(),
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, amount, isReversal);
} else if (savingsTransactionDTO.getTransactionType().isOverdraftFee()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_FEES, savingsProductId,
@@ -125,9 +125,9 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_DATA_PARAMS.LOSSES_WRITTEN_OFF.getValue(), gLAccountData);
} else if (glAccountForLoan.equals(CASH_ACCOUNTS_FOR_LOAN.OVERPAYMENT)) {
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_DATA_PARAMS.OVERPAYMENT.getValue(), gLAccountData);
} else if(glAccountForLoan.equals(CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_RECOVERY)) {
} else if (glAccountForLoan.equals(CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_RECOVERY)) {
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_DATA_PARAMS.INCOME_FROM_RECOVERY.getValue(), gLAccountData);
}
}
}
} else if (AccountingRuleType.ACCRUAL_UPFRONT.getValue().equals(accountingType)
|| AccountingRuleType.ACCRUAL_PERIODIC.getValue().equals(accountingType)) {
@@ -163,7 +163,7 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_DATA_PARAMS.FEES_RECEIVABLE.getValue(), gLAccountData);
} else if (glAccountForLoan.equals(ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE)) {
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_DATA_PARAMS.PENALTIES_RECEIVABLE.getValue(), gLAccountData);
} else if((glAccountForLoan.equals(ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_RECOVERY))){
} else if ((glAccountForLoan.equals(ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_RECOVERY))) {
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_DATA_PARAMS.INCOME_FROM_RECOVERY.getValue(), gLAccountData);
}
}
@@ -24,7 +24,7 @@ public class CommandWrapper {
private final String json;
private final String transactionId;
private final Long productId;
@SuppressWarnings("unused")
private Long templateId;
@@ -347,7 +347,7 @@ public class CommandWrapper {
public boolean isTemplateRessource() {
return this.entityName.equalsIgnoreCase("Template");
}
public boolean isApproveLoanApplication() {
return this.actionName.equalsIgnoreCase("APPROVE") && this.entityName.equalsIgnoreCase("LOAN");
}
@@ -367,7 +367,7 @@ public class CommandWrapper {
public boolean isDisbursementOfLoan() {
return this.actionName.equalsIgnoreCase("DISBURSE") && this.entityName.equalsIgnoreCase("LOAN");
}
public boolean isDisbursementOfLoanToSavings() {
return this.actionName.equalsIgnoreCase("DISBURSETOSAVINGS") && this.entityName.equalsIgnoreCase("LOAN");
}
@@ -379,6 +379,7 @@ public class CommandWrapper {
public boolean isLoanRepayment() {
return this.actionName.equalsIgnoreCase("REPAYMENT") && this.entityName.equalsIgnoreCase("LOAN");
}
public boolean isLoanRecoveryPayment() {
return this.actionName.equalsIgnoreCase("RECOVERYPAYMENT") && this.entityName.equalsIgnoreCase("LOAN");
}
@@ -729,93 +730,93 @@ public class CommandWrapper {
public boolean isDepositAccountResource() {
return isFixedDepositAccountResource() || isRecurringDepositAccountResource();
}
public boolean isFixedDepositAccountResource() {
return this.entityName.equalsIgnoreCase("FIXEDDEPOSITACCOUNT");
}
public boolean isRecurringDepositAccountResource() {
return this.entityName.equalsIgnoreCase("RECURRINGDEPOSITACCOUNT");
}
public boolean isFixedDepositAccountCreate() {
return isCreate() && isFixedDepositAccountResource();
}
public boolean isRecurringDepositAccountCreate() {
return isCreate() && isRecurringDepositAccountResource();
}
public boolean isFixedDepositAccountUpdate() {
return isUpdate() && isFixedDepositAccountResource();
}
public boolean isRecurringDepositAccountUpdate() {
return isUpdate() && isRecurringDepositAccountResource();
}
public boolean isFixedDepositAccountDelete() {
return isDelete() && isFixedDepositAccountResource();
}
public boolean isRecurringDepositAccountDelete() {
return isDelete() && isRecurringDepositAccountResource();
}
public boolean isRejectionOfFixedDepositAccountApplication() {
return this.actionName.equalsIgnoreCase("REJECT") && isFixedDepositAccountResource();
}
public boolean isRejectionOfRecurringDepositAccountApplication() {
return this.actionName.equalsIgnoreCase("REJECT") && isRecurringDepositAccountResource();
}
public boolean isWithdrawFixedDepositAccountApplicationByApplicant() {
return this.actionName.equalsIgnoreCase("WITHDRAW") && isFixedDepositAccountResource();
}
public boolean isWithdrawRecurringDepositAccountApplicationByApplicant() {
return this.actionName.equalsIgnoreCase("WITHDRAW") && isRecurringDepositAccountResource();
}
public boolean isApprovalOfFixedDepositAccountApplication() {
return this.actionName.equalsIgnoreCase("APPROVE") && isFixedDepositAccountResource();
}
public boolean isApprovalOfRecurringDepositAccountApplication() {
return this.actionName.equalsIgnoreCase("APPROVE") && isRecurringDepositAccountResource();
}
public boolean isUndoApprovalOfFixedDepositAccountApplication() {
return this.actionName.equalsIgnoreCase("APPROVALUNDO") && isFixedDepositAccountResource();
}
public boolean isUndoApprovalOfRecurringDepositAccountApplication() {
return this.actionName.equalsIgnoreCase("APPROVALUNDO") && isRecurringDepositAccountResource();
}
//Account transaction actions
// Account transaction actions
public boolean isDeposit() {
return this.actionName.equalsIgnoreCase("DEPOSIT");
}
public boolean isWithdrawal() {
return this.actionName.equalsIgnoreCase("WITHDRAWAL");
}
public boolean isActivation() {
return this.actionName.equalsIgnoreCase("ACTIVATE");
}
public boolean isInterestCalculation() {
return this.actionName.equalsIgnoreCase("CALCULATEINTEREST");
}
public boolean isInterestPosting() {
return this.actionName.equalsIgnoreCase("POSTINTEREST");
}
public boolean isUndoTransaction() {
return this.actionName.equalsIgnoreCase("UNDOTRANSACTION");
}
@@ -823,14 +824,18 @@ public class CommandWrapper {
public boolean isAdjustTransaction() {
return this.actionName.equalsIgnoreCase("ADJUSTTRANSACTION");
}
public boolean isDepositAccountClose() {
return this.actionName.equalsIgnoreCase("CLOSE") && isDepositAccountResource();
}
public boolean isDepositAccountPrematureClose() {
return this.actionName.equalsIgnoreCase("PREMATURECLOSE") && isDepositAccountResource();
}
// End - Deposit accounts
public boolean isOfficeToGLAccountMapping() {
return this.entityName.equalsIgnoreCase("OFFICEGLACCOUNT");
}
}
@@ -573,7 +573,7 @@ public class CommandWrapperBuilder {
return this;
}
public CommandWrapperBuilder loanRecoveryPaymentTransaction(final Long loanId){
public CommandWrapperBuilder loanRecoveryPaymentTransaction(final Long loanId) {
this.actionName = "RECOVERYPAYMENT";
this.entityName = "LOAN";
this.entityId = null;
@@ -707,7 +707,7 @@ public class CommandWrapperBuilder {
this.href = "/loans/" + loanId;
return this;
}
public CommandWrapperBuilder disburseLoanToSavingsApplication(final Long loanId) {
this.actionName = "DISBURSETOSAVINGS";
this.entityName = "LOAN";
@@ -1795,7 +1795,7 @@ public class CommandWrapperBuilder {
this.href = "/fixeddepositaccounts/" + accountId + "?command=postInterest";
return this;
}
public CommandWrapperBuilder fixedDepositAccountDeposit(final Long accountId) {
this.actionName = "DEPOSIT";
this.entityName = "FIXEDDEPOSITACCOUNT";
@@ -1804,7 +1804,7 @@ public class CommandWrapperBuilder {
this.href = "/fixeddepositaccounts/" + accountId + "/transactions?command=deposit";
return this;
}
public CommandWrapperBuilder fixedDepositAccountWithdrawal(final Long accountId) {
this.actionName = "WITHDRAWAL";
this.entityName = "FIXEDDEPOSITACCOUNT";
@@ -1838,7 +1838,7 @@ public class CommandWrapperBuilder {
this.href = "/recurringdepositaccounts/" + accountId + "/transactions?command=deposit";
return this;
}
public CommandWrapperBuilder recurringAccountWithdrawal(final Long accountId) {
this.actionName = "WITHDRAWAL";
this.entityName = "RECURRINGDEPOSITACCOUNT";
@@ -1858,7 +1858,7 @@ public class CommandWrapperBuilder {
this.href = "/recurringdepositaccounts/" + accountId + "/transactions/" + transactionId + "?command=modify";
return this;
}
public CommandWrapperBuilder undoRecurringAccountTransaction(final Long accountId, final Long transactionId) {
this.actionName = "UNDOTRANSACTION";
this.entityName = "RECURRINGDEPOSITACCOUNT";
@@ -1869,7 +1869,7 @@ public class CommandWrapperBuilder {
this.href = "/recurringdepositaccounts/" + accountId + "/transactions/" + transactionId + "?command=undo";
return this;
}
public CommandWrapperBuilder deleteRecurringDepositAccount(final Long accountId) {
this.actionName = "DELETE";
this.entityName = "RECURRINGDEPOSITACCOUNT";
@@ -1958,4 +1958,29 @@ public class CommandWrapperBuilder {
this.href = "/recurringdepositaccounts/" + accountId + "?command=postInterest";
return this;
}
public CommandWrapperBuilder createOfficeToGLAccountMapping() {
this.actionName = "CREATE";
this.entityName = "OFFICEGLACCOUNT";
this.entityId = null;
this.href = "/organizationglaccounts/template";
return this;
}
public CommandWrapperBuilder updateOfficeToGLAccountMapping(final Long mappingId) {
this.actionName = "UPDATE";
this.entityName = "OFFICEGLACCOUNT";
this.entityId = mappingId;
this.href = "/organizationglaccounts/" + mappingId;
return this;
}
public CommandWrapperBuilder deleteOfficeToGLAccountMapping(final Long mappingId) {
this.actionName = "DELETE";
this.entityName = "OFFICEGLACCOUNT";
this.entityId = mappingId;
this.href = "/organizationglaccounts/" + mappingId;
return this;
}
}
@@ -63,7 +63,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
CommandSource commandSourceResult = null;
if (command.commandId() != null) {
commandSourceResult = this.commandSourceRepository.findOne(command.commandId());
commandSourceResult.markAsChecked(maker, DateTime.now());
commandSourceResult.markAsChecked(maker, DateTime.now());
} else {
commandSourceResult = CommandSource.fullEntryFrom(wrapper, command, maker);
}
@@ -341,9 +341,9 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
handler = this.applicationContext.getBean("undoDisbursalLoanCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isLoanRepayment()) {
handler = this.applicationContext.getBean("loanRepaymentCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isLoanRecoveryPayment()){
} else if (wrapper.isLoanRecoveryPayment()) {
handler = this.applicationContext.getBean("loanRecoveryPaymentCommandHandler", NewCommandSourceHandler.class);
}else if (wrapper.isLoanRepaymentAdjustment()) {
} else if (wrapper.isLoanRepaymentAdjustment()) {
handler = this.applicationContext.getBean("loanRepaymentAdjustmentCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isWaiveInterestPortionOnLoan()) {
handler = this.applicationContext.getBean("waiveInterestPortionOnLoanCommandHandler", NewCommandSourceHandler.class);
@@ -777,6 +777,16 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if (wrapper.isOfficeToGLAccountMapping()) {
if (wrapper.isCreate()) {
handler = this.applicationContext.getBean("createOfficeToGLAccountMappingHandler", NewCommandSourceHandler.class);
} else if (wrapper.isUpdate()) {
handler = this.applicationContext.getBean("updateOfficeToGLAccountMappingCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isDelete()) {
handler = this.applicationContext.getBean("deleteOfficeToGLAccountMappingCommandHandler", NewCommandSourceHandler.class);
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
} else {
throw new UnsupportedCommandException(wrapper.commandName());
@@ -99,6 +99,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
Long fromSavingsAccountId = null;
Long transferDetailId = null;
boolean isInterestTransfer = false;
boolean isAccountTransfer = true;
if (isSavingsToSavingsAccountTransfer(fromAccountType, toAccountType)) {
fromSavingsAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
@@ -106,13 +107,13 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
final SavingsAccountTransaction withdrawal = this.savingsAccountDomainService.handleWithdrawal(fromSavingsAccount, fmt,
transactionDate, transactionAmount, paymentDetail, fromSavingsAccount.isWithdrawalFeeApplicableForTransfer(),
isInterestTransfer);
isInterestTransfer, isAccountTransfer);
final Long toSavingsId = command.longValueOfParameterNamed(toAccountIdParamName);
final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsId);
final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(toSavingsAccount, fmt,
transactionDate, transactionAmount, paymentDetail);
transactionDate, transactionAmount, paymentDetail, isAccountTransfer);
final AccountTransferDetails accountTransferDetails = this.accountTransferAssembler.assembleSavingsToSavingsTransfer(command,
fromSavingsAccount, toSavingsAccount, withdrawal, deposit);
@@ -126,7 +127,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
final SavingsAccountTransaction withdrawal = this.savingsAccountDomainService.handleWithdrawal(fromSavingsAccount, fmt,
transactionDate, transactionAmount, paymentDetail, fromSavingsAccount.isWithdrawalFeeApplicableForTransfer(),
isInterestTransfer);
isInterestTransfer, isAccountTransfer);
final Long toLoanAccountId = command.longValueOfParameterNamed(toAccountIdParamName);
final Loan toLoanAccount = this.loanAccountAssembler.assembleFrom(toLoanAccountId);
@@ -134,7 +135,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
final boolean isRecoveryRepayment = false;
final LoanTransaction loanRepaymentTransaction = this.loanAccountDomainService.makeRepayment(toLoanAccount,
new CommandProcessingResultBuilder(), transactionDate, transactionAmount, paymentDetail, null, null,
isRecoveryRepayment);
isRecoveryRepayment, isAccountTransfer);
final AccountTransferDetails accountTransferDetails = this.accountTransferAssembler.assembleSavingsToLoanTransfer(command,
fromSavingsAccount, toLoanAccount, withdrawal, loanRepaymentTransaction);
@@ -156,7 +157,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsAccountId);
final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(toSavingsAccount, fmt,
transactionDate, transactionAmount, paymentDetail);
transactionDate, transactionAmount, paymentDetail, isAccountTransfer);
final AccountTransferDetails accountTransferDetails = this.accountTransferAssembler.assembleLoanToSavingsTransfer(command,
fromLoanAccount, toSavingsAccount, deposit, loanRefundTransaction);
@@ -230,6 +231,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
@Transactional
public Long transferFunds(final AccountTransferDTO accountTransferDTO) {
Long transferTransactionId = null;
boolean isAccountTransfer = true;
AccountTransferDetails accountTransferDetails = accountTransferDTO.getAccountTransferDetails();
if (isSavingsToLoanAccountTransfer(accountTransferDTO.getFromAccountType(), accountTransferDTO.getToAccountType())) {
//
@@ -248,7 +250,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
final SavingsAccountTransaction withdrawal = this.savingsAccountDomainService.handleWithdrawal(fromSavingsAccount,
accountTransferDTO.getFmt(), accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
accountTransferDTO.getPaymentDetail(), fromSavingsAccount.isWithdrawalFeeApplicableForTransfer(), AccountTransferType
.fromInt(accountTransferDTO.getTransferType()).isInterestTransfer());
.fromInt(accountTransferDTO.getTransferType()).isInterestTransfer(), isAccountTransfer);
LoanTransaction loanTransaction = null;
@@ -262,7 +264,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
final boolean isRecoveryRepayment = false;
loanTransaction = this.loanAccountDomainService.makeRepayment(toLoanAccount, new CommandProcessingResultBuilder(),
accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
accountTransferDTO.getPaymentDetail(), null, null, isRecoveryRepayment);
accountTransferDTO.getPaymentDetail(), null, null, isRecoveryRepayment, isAccountTransfer);
}
accountTransferDetails = this.accountTransferAssembler.assembleSavingsToLoanTransfer(accountTransferDTO, fromSavingsAccount,
@@ -293,11 +295,11 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
final SavingsAccountTransaction withdrawal = this.savingsAccountDomainService.handleWithdrawal(fromSavingsAccount,
accountTransferDTO.getFmt(), accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
accountTransferDTO.getPaymentDetail(), fromSavingsAccount.isWithdrawalFeeApplicableForTransfer(), AccountTransferType
.fromInt(accountTransferDTO.getTransferType()).isInterestTransfer());
.fromInt(accountTransferDTO.getTransferType()).isInterestTransfer(), isAccountTransfer);
final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(toSavingsAccount,
accountTransferDTO.getFmt(), accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
accountTransferDTO.getPaymentDetail());
accountTransferDTO.getPaymentDetail(), isAccountTransfer);
accountTransferDetails = this.accountTransferAssembler.assembleSavingsToSavingsTransfer(accountTransferDTO, fromSavingsAccount,
toSavingsAccount, withdrawal, deposit);
@@ -335,7 +337,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(toSavingsAccount,
accountTransferDTO.getFmt(), accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
accountTransferDTO.getPaymentDetail());
accountTransferDTO.getPaymentDetail(), isAccountTransfer);
accountTransferDetails = this.accountTransferAssembler.assembleLoanToSavingsTransfer(accountTransferDTO, fromLoanAccount,
toSavingsAccount, deposit, loanTransaction);
this.accountTransferDetailRepository.saveAndFlush(accountTransferDetails);
@@ -767,7 +767,7 @@ public class Loan extends AbstractPersistable<Long> {
}
return amount.getAmount();
}
public BigDecimal getTotalWrittenOff() {
return this.summary.getTotalWrittenOff();
}
@@ -3304,7 +3304,7 @@ public class Loan extends AbstractPersistable<Long> {
}
public Map<String, Object> deriveAccountingBridgeData(final CurrencyData currencyData, final List<Long> existingTransactionIds,
final List<Long> existingReversedTransactionIds) {
final List<Long> existingReversedTransactionIds, boolean isAccountTransfer) {
final Map<String, Object> accountingBridgeData = new LinkedHashMap<String, Object>();
accountingBridgeData.put("loanId", getId());
@@ -3315,6 +3315,7 @@ public class Loan extends AbstractPersistable<Long> {
accountingBridgeData.put("cashBasedAccountingEnabled", isCashBasedAccountingEnabledOnLoanProduct());
accountingBridgeData.put("upfrontAccrualBasedAccountingEnabled", isUpfrontAccrualAccountingEnabledOnLoanProduct());
accountingBridgeData.put("periodicAccrualBasedAccountingEnabled", isPeriodicAccrualAccountingEnabledOnLoanProduct());
accountingBridgeData.put("isAccountTransfer", isAccountTransfer);
final List<Map<String, Object>> newLoanTransactions = new ArrayList<Map<String, Object>>();
for (final LoanTransaction transaction : this.loanTransactions) {
@@ -15,7 +15,7 @@ public interface LoanAccountDomainService {
LoanTransaction makeRepayment(Loan loan, CommandProcessingResultBuilder builderResult, LocalDate transactionDate,
BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, String txnExternalId,
final boolean isRecoveryRepayment);
final boolean isRecoveryRepayment, boolean isAccountTransfer);
LoanTransaction makeRefund(Long accountId, CommandProcessingResultBuilder builderResult, LocalDate transactionDate,
BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, String txnExternalId);
@@ -82,7 +82,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
@Override
public LoanTransaction makeRepayment(final Loan loan, final CommandProcessingResultBuilder builderResult,
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final String noteText,
final String txnExternalId, final boolean isRecoveryRepayment) {
final String txnExternalId, final boolean isRecoveryRepayment, boolean isAccountTransfer) {
checkClientOrGroupActive(loan);
@@ -160,7 +160,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
this.noteRepository.save(note);
}
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
builderResult.withEntityId(newRepaymentTransaction.getId()) //
.withOfficeId(loan.getOfficeId()) //
@@ -176,6 +176,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final String noteText, final String txnExternalId,
final Integer transactionType, Integer installmentNumber) {
boolean isAccountTransfer = true;
checkClientOrGroupActive(loan);
final List<Long> existingTransactionIds = new ArrayList<Long>();
@@ -206,18 +207,18 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
this.noteRepository.save(note);
}
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
return newPaymentTransaction;
}
private void postJournalEntries(final Loan loanAccount, final List<Long> existingTransactionIds,
final List<Long> existingReversedTransactionIds) {
final List<Long> existingReversedTransactionIds, boolean isAccountTransfer) {
final MonetaryCurrency currency = loanAccount.getCurrency();
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepositoryWrapper.findOneWithNotFoundDetection(currency);
final Map<String, Object> accountingBridgeData = loanAccount.deriveAccountingBridgeData(applicationCurrency.toData(),
existingTransactionIds, existingReversedTransactionIds);
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
}
@@ -241,6 +242,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
public LoanTransaction makeRefund(final Long accountId, final CommandProcessingResultBuilder builderResult,
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final String noteText,
final String txnExternalId) {
boolean isAccountTransfer = true;
final Loan loan = this.loanAccountAssembler.assembleFrom(accountId);
checkClientOrGroupActive(loan);
@@ -267,7 +269,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
this.noteRepository.save(note);
}
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
builderResult.withEntityId(newRefundTransaction.getId()) //
.withOfficeId(loan.getOfficeId()) //
@@ -283,7 +285,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
final PaymentDetail paymentDetail, final String noteText, final String txnExternalId) {
final Loan loan = this.loanAccountAssembler.assembleFrom(loanId);
checkClientOrGroupActive(loan);
boolean isAccountTransfer = true;
final List<Long> existingTransactionIds = new ArrayList<Long>();
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
final Money amount = Money.of(loan.getCurrency(), transactionAmount);
@@ -311,7 +313,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
this.noteRepository.save(note);
}
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
return disbursementTransaction;
}
@@ -147,6 +147,7 @@ public class LoanAccrualWritePlatformServiceImpl implements LoanAccrualWritePlat
accountingBridgeData.put("cashBasedAccountingEnabled", false);
accountingBridgeData.put("upfrontAccrualBasedAccountingEnabled", false);
accountingBridgeData.put("periodicAccrualBasedAccountingEnabled", true);
accountingBridgeData.put("isAccountTransfer", false);
final List<Map<String, Object>> newLoanTransactions = new ArrayList<Map<String, Object>>();
newLoanTransactions.add(transactionMap);
@@ -545,9 +545,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
this.noteRepository.save(note);
}
}
boolean isAccountTransfer = false;
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(applicationCurrency.toData(),
existingTransactionIds, existingReversedTransactionIds);
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
}
@@ -587,9 +587,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final Loan loan = this.loanAssembler.assembleFrom(loanId);
final PaymentDetail paymentDetail = this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);
boolean isAccountTransfer = false;
final CommandProcessingResultBuilder commandProcessingResultBuilder = new CommandProcessingResultBuilder();
this.loanAccountDomainService.makeRepayment(loan, commandProcessingResultBuilder, transactionDate, transactionAmount,
paymentDetail, noteText, txnExternalId, isRecoveryRepayment);
paymentDetail, noteText, txnExternalId, isRecoveryRepayment, isAccountTransfer);
return commandProcessingResultBuilder.withCommandId(command.commandId()) //
.withLoanId(loanId) //
@@ -607,7 +608,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final boolean isRecoveryRepayment = false;
if (repaymentCommand == null) { return changes; }
boolean isAccountTransfer = false;
for (final SingleRepaymentCommand singleLoanRepaymentCommand : repaymentCommand) {
/****
* TODO Vishwas, have a re-look at this implementation, defaulting
@@ -618,7 +619,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final CommandProcessingResultBuilder commandProcessingResultBuilder = new CommandProcessingResultBuilder();
this.loanAccountDomainService.makeRepayment(loan, commandProcessingResultBuilder, bulkRepaymentCommand.getTransactionDate(),
singleLoanRepaymentCommand.getTransactionAmount(), paymentDetail, bulkRepaymentCommand.getNote(), null,
isRecoveryRepayment);
isRecoveryRepayment, isAccountTransfer);
changes.put("bulkTransations", singleLoanRepaymentCommand);
}
@@ -1541,9 +1542,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final MonetaryCurrency currency = loan.getCurrency();
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
boolean isAccountTransfer = false;
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(applicationCurrency.toData(),
existingTransactionIds, existingReversedTransactionIds);
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
}
@@ -76,7 +76,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
public SavingsAccountTransaction handleWithdrawal(final SavingsAccount account, final DateTimeFormatter fmt,
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail,
final boolean applyWithdrawFee) {
boolean isAccountTransfer = false;
final Set<Long> existingTransactionIds = new HashSet<Long>();
final Set<Long> existingReversedTransactionIds = new HashSet<Long>();
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
@@ -96,7 +96,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
saveTransactionToGenerateTransactionId(withdrawal);
this.savingsAccountRepository.save(account);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
return withdrawal;
}
@@ -105,18 +105,19 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
@Override
public SavingsAccountTransaction handleFDDeposit(final FixedDepositAccount account, final DateTimeFormatter fmt,
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail) {
return this.savingsAccountDomainService.handleDeposit(account, fmt, transactionDate, transactionAmount, paymentDetail);
boolean isAccountTransfer = false;
return this.savingsAccountDomainService.handleDeposit(account, fmt, transactionDate, transactionAmount, paymentDetail,
isAccountTransfer);
}
@Transactional
@Override
public SavingsAccountTransaction handleRDDeposit(final RecurringDepositAccount account, final DateTimeFormatter fmt,
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail) {
boolean isAccountTransfer = false;
final MathContext mc = MathContext.DECIMAL64;
final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(account, fmt, transactionDate,
transactionAmount, paymentDetail);
transactionAmount, paymentDetail, isAccountTransfer);
account.handleScheduleInstallments(deposit);
account.updateMaturityDateAndAmount(mc);
@@ -128,24 +129,23 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
@Override
public Long handleFDAccountClosure(final FixedDepositAccount account, final PaymentDetail paymentDetail, final AppUser user,
final JsonCommand command, final LocalDate tenantsTodayDate, final Map<String, Object> changes) {
boolean isAccountTransfer = false;
final Set<Long> existingTransactionIds = new HashSet<Long>();
final Set<Long> existingReversedTransactionIds = new HashSet<Long>();
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
/*<<<<<<< HEAD
final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
paymentDetail, new Date());
final SavingsAccountTransaction deposit = account.deposit(transactionDTO);
boolean isInterestTransfer = false;
final MathContext mc = MathContext.DECIMAL64;
if (account.isBeforeLastPostingPeriod(transactionDate)) {
final LocalDate today = DateUtils.getLocalDateOfTenant();
account.postInterest(mc, today, isInterestTransfer);
} else {
final LocalDate today = DateUtils.getLocalDateOfTenant();
account.calculateInterestUsing(mc, today, isInterestTransfer);
=======
*/
/*
* <<<<<<< HEAD final SavingsAccountTransactionDTO transactionDTO = new
* SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
* paymentDetail, new Date()); final SavingsAccountTransaction deposit =
* account.deposit(transactionDTO); boolean isInterestTransfer = false;
* final MathContext mc = MathContext.DECIMAL64; if
* (account.isBeforeLastPostingPeriod(transactionDate)) { final
* LocalDate today = DateUtils.getLocalDateOfTenant();
* account.postInterest(mc, today, isInterestTransfer); } else { final
* LocalDate today = DateUtils.getLocalDateOfTenant();
* account.calculateInterestUsing(mc, today, isInterestTransfer);
* =======
*/
final MathContext mc = MathContext.DECIMAL64;
final Locale locale = command.extractLocale();
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
@@ -176,11 +176,11 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
paymentDetail, false);
savingsTransactionId = withdrawal.getId();
}
account.close(user, command, tenantsTodayDate, changes);
this.savingsAccountRepository.save(account);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
return savingsTransactionId;
}
@@ -189,7 +189,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
@Override
public Long handleRDAccountClosure(final RecurringDepositAccount account, final PaymentDetail paymentDetail, final AppUser user,
final JsonCommand command, final LocalDate tenantsTodayDate, final Map<String, Object> changes) {
boolean isAccountTransfer = false;
final Set<Long> existingTransactionIds = new HashSet<Long>();
final Set<Long> existingReversedTransactionIds = new HashSet<Long>();
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
@@ -242,7 +242,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
this.savingsAccountRepository.save(account);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
return savingsTransactionId;
}
@@ -260,7 +260,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
@Override
public Long handleFDAccountPreMatureClosure(final FixedDepositAccount account, final PaymentDetail paymentDetail, final AppUser user,
final JsonCommand command, final LocalDate tenantsTodayDate, final Map<String, Object> changes) {
boolean isAccountTransfer = false;
final Set<Long> existingTransactionIds = new HashSet<Long>();
final Set<Long> existingReversedTransactionIds = new HashSet<Long>();
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
@@ -292,7 +292,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
this.savingsAccountRepository.save(account);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
return savingsTransactionId;
}
@@ -300,7 +300,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
@Override
public Long handleRDAccountPreMatureClosure(final RecurringDepositAccount account, final PaymentDetail paymentDetail,
final AppUser user, final JsonCommand command, final LocalDate tenantsTodayDate, final Map<String, Object> changes) {
boolean isAccountTransfer = false;
final Set<Long> existingTransactionIds = new HashSet<Long>();
final Set<Long> existingReversedTransactionIds = new HashSet<Long>();
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
@@ -329,7 +329,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
account.prematureClosure(user, command, tenantsTodayDate, changes);
this.savingsAccountRepository.save(account);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
return savingsTransactionId;
}
@@ -345,13 +345,13 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
}
private void postJournalEntries(final SavingsAccount savingsAccount, final Set<Long> existingTransactionIds,
final Set<Long> existingReversedTransactionIds) {
final Set<Long> existingReversedTransactionIds, boolean isAccountTransfer) {
final MonetaryCurrency currency = savingsAccount.getCurrency();
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepositoryWrapper.findOneWithNotFoundDetection(currency);
final Map<String, Object> accountingBridgeData = savingsAccount.deriveAccountingBridgeData(applicationCurrency.toData(),
existingTransactionIds, existingReversedTransactionIds);
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
this.journalEntryWritePlatformService.createJournalEntriesForSavings(accountingBridgeData);
}
}
@@ -1021,7 +1021,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
}
public Map<String, Object> deriveAccountingBridgeData(final CurrencyData currencyData, final Set<Long> existingTransactionIds,
final Set<Long> existingReversedTransactionIds) {
final Set<Long> existingReversedTransactionIds, boolean isAccountTransfer) {
final Map<String, Object> accountingBridgeData = new LinkedHashMap<String, Object>();
accountingBridgeData.put("savingsId", getId());
@@ -1030,6 +1030,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
accountingBridgeData.put("officeId", officeId());
accountingBridgeData.put("cashBasedAccountingEnabled", isCashBasedAccountingEnabledOnSavingsProduct());
accountingBridgeData.put("accrualBasedAccountingEnabled", isAccrualBasedAccountingEnabledOnSavingsProduct());
accountingBridgeData.put("isAccountTransfer", isAccountTransfer);
final List<Map<String, Object>> newLoanTransactions = new ArrayList<Map<String, Object>>();
for (final SavingsAccountTransaction transaction : this.transactions) {
@@ -14,8 +14,8 @@ import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
public interface SavingsAccountDomainService {
SavingsAccountTransaction handleWithdrawal(SavingsAccount account, DateTimeFormatter fmt, LocalDate transactionDate,
BigDecimal transactionAmount, PaymentDetail paymentDetail, boolean applyWithdrawFee, boolean isInterestTransfer);
BigDecimal transactionAmount, PaymentDetail paymentDetail, boolean applyWithdrawFee, boolean isInterestTransfer, boolean isAccountTransfer);
SavingsAccountTransaction handleDeposit(SavingsAccount account, DateTimeFormatter fmt, LocalDate transactionDate,
BigDecimal transactionAmount, PaymentDetail paymentDetail);
BigDecimal transactionAmount, PaymentDetail paymentDetail, boolean isAccountTransfer);
}
@@ -48,7 +48,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
@Override
public SavingsAccountTransaction handleWithdrawal(final SavingsAccount account, final DateTimeFormatter fmt,
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail,
final boolean applyWithdrawFee, boolean isInterestTransfer) {
final boolean applyWithdrawFee, boolean isInterestTransfer, final boolean isAccountTransfer) {
final Set<Long> existingTransactionIds = new HashSet<Long>();
final Set<Long> existingReversedTransactionIds = new HashSet<Long>();
@@ -69,7 +69,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
saveTransactionToGenerateTransactionId(withdrawal);
this.savingsAccountRepository.save(account);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
return withdrawal;
}
@@ -77,7 +77,8 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
@Transactional
@Override
public SavingsAccountTransaction handleDeposit(final SavingsAccount account, final DateTimeFormatter fmt,
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail) {
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail,
final boolean isAccountTransfer) {
boolean isInterestTransfer = false;
final Set<Long> existingTransactionIds = new HashSet<Long>();
@@ -100,7 +101,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
this.savingsAccountRepository.save(account);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
return deposit;
}
@@ -117,13 +118,13 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
}
private void postJournalEntries(final SavingsAccount savingsAccount, final Set<Long> existingTransactionIds,
final Set<Long> existingReversedTransactionIds) {
final Set<Long> existingReversedTransactionIds, boolean isAccountTransfer) {
final MonetaryCurrency currency = savingsAccount.getCurrency();
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepositoryWrapper.findOneWithNotFoundDetection(currency);
final Map<String, Object> accountingBridgeData = savingsAccount.deriveAccountingBridgeData(applicationCurrency.toData(),
existingTransactionIds, existingReversedTransactionIds);
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
this.journalEntryWritePlatformService.createJournalEntriesForSavings(accountingBridgeData);
}
}
@@ -1157,9 +1157,9 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
final MonetaryCurrency currency = savingsAccount.getCurrency();
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepositoryWrapper.findOneWithNotFoundDetection(currency);
boolean isAccountTransfer = false;
final Map<String, Object> accountingBridgeData = savingsAccount.deriveAccountingBridgeData(applicationCurrency.toData(),
existingTransactionIds, existingReversedTransactionIds);
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
this.journalEntryWritePlatformService.createJournalEntriesForSavings(accountingBridgeData);
}
@@ -150,7 +150,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
final Set<Long> existingTransactionIds = new HashSet<Long>();
final Set<Long> existingReversedTransactionIds = new HashSet<Long>();
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
boolean isAccountTransfer = false;
final Map<String, Object> changes = account.activate(user, command, DateUtils.getLocalDateOfTenant());
if (!changes.isEmpty()) {
final Locale locale = command.extractLocale();
@@ -158,7 +158,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
Money amountForDeposit = account.activateWithBalance();
if (amountForDeposit.isGreaterThanZero()) {
this.savingsAccountDomainService.handleDeposit(account, fmt, account.getActivationLocalDate(),
amountForDeposit.getAmount(), null);
amountForDeposit.getAmount(), null, isAccountTransfer);
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
}
account.processAccountUponActivation();
@@ -198,9 +198,9 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
final Map<String, Object> changes = new LinkedHashMap<String, Object>();
final PaymentDetail paymentDetail = this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);
boolean isAccountTransfer = false;
final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(account, fmt, transactionDate,
transactionAmount, paymentDetail);
transactionAmount, paymentDetail, isAccountTransfer);
return new CommandProcessingResultBuilder() //
.withEntityId(deposit.getId()) //
@@ -235,9 +235,9 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
boolean isInterestTransfer = false;
boolean isAccountTransfer = false;
final SavingsAccountTransaction withdrawal = this.savingsAccountDomainService.handleWithdrawal(account, fmt, transactionDate,
transactionAmount, paymentDetail, true, isInterestTransfer);
transactionAmount, paymentDetail, true, isInterestTransfer, isAccountTransfer);
return new CommandProcessingResultBuilder() //
.withEntityId(withdrawal.getId()) //
@@ -884,9 +884,9 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
final MonetaryCurrency currency = savingsAccount.getCurrency();
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepositoryWrapper.findOneWithNotFoundDetection(currency);
boolean isAccountTransfer = false;
final Map<String, Object> accountingBridgeData = savingsAccount.deriveAccountingBridgeData(applicationCurrency.toData(),
existingTransactionIds, existingReversedTransactionIds);
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
this.journalEntryWritePlatformService.createJournalEntriesForSavings(accountingBridgeData);
}
}
@@ -451,9 +451,10 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
savingsAccountDataDTO.getAppliedBy());
account.approveAndActivateApplication(savingsAccountDataDTO.getApplicationDate().toDate(), savingsAccountDataDTO.getAppliedBy());
Money amountForDeposit = account.activateWithBalance();
boolean isAccountTransfer = false;
if (amountForDeposit.isGreaterThanZero()) {
this.savingsAccountDomainService.handleDeposit(account, savingsAccountDataDTO.getFmt(), account.getActivationLocalDate(),
amountForDeposit.getAmount(), null);
amountForDeposit.getAmount(), null, isAccountTransfer);
}
account.processAccountUponActivation();
this.savingAccountRepository.save(account);