diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm index e799a8aa5..1dc3f13f1 100644 --- a/api-docs/apiLive.htm +++ b/api-docs/apiLive.htm @@ -293,6 +293,27 @@ + + + loans/{loanId}/guarantors + Create a Guarantor + + List Guarantors + + + + + + + loans/{loanId}/guarantors/{guarantorId} + + Retrieve a Guarantor + + Update a Guarantor + + Delete a Guarantor + + @@ -1076,6 +1097,113 @@ +
+

Accounting

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
RESOURCES
+
+ + + + + + +
POST
create/complex + update
+ + + + + + +
GET
read
+ + + + + + +
PUT
update
+ + + + + + +
DELETE
delete
General Ledger AccountglaccountsCreate a New Ledger AccountList Ledger Accounts
glaccounts/{glaccountId}Retrieve a Ledger AccountUpdate a Ledger AccountDelete a Ledger Account
Accounting ClosureglclosuresCreate an Accounting ClosureList Accounting Closures
glclosures/{glclosureId}Retrieve an Accounting ClosureUpdate an Accounting ClosureDelete an Accounting Closure
Journal EntriesjournalentriesCreate Journal EntriesList Journal Entries
journalentries/{entryId}Retrieve a Journal Entry
journalentries/{transactionId}/reversalReverse Journal Entries
+
+
+
@@ -3976,7 +4104,7 @@ Request Body: - accountingType + accountingRule Example Values:NONE(1), @@ -4055,7 +4183,11 @@ GET https://DomainName/api/v1/loanproducts "code": "interestCalculationPeriodType.same.as.repayment.period", "value": "Same as repayment period" }, - "accountingType": 1 + "accountingRule": { + "id": 1, + "code": "accountingRuleType.none", + "value": "NONE" + } } ] @@ -4123,7 +4255,7 @@ GET https://DomainName/api/v1/loanproducts/template "code": "interestCalculationPeriodType.same.as.repayment.period", "value": "Same as repayment period" }, - "accountingType": 1, + "accountingRule": 1, "currencyOptions": [ { "code": "USD", @@ -4281,6 +4413,158 @@ GET https://DomainName/api/v1/loanproducts/template } } ], + "accountingOptions": { + "assetAccountOptions": [ + { + "id": 1, + "name": "Fund Source For Loans", + "glCode": "100001", + "disabled": false, + "manualEntriesAllowed": true, + "type": { + "id": 1, + "code": "accountType.asset", + "value": "ASSET" + }, + "usage": { + "id": 1, + "code": "accountUsage.detail", + "value": "DETAIL" + }, + "description": "Desc" + }, + { + "id": 2, + "name": "Interest Receivable", + "glCode": "100002", + "disabled": false, + "manualEntriesAllowed": true, + "type": { + "id": 1, + "code": "accountType.asset", + "value": "ASSET" + }, + "usage": { + "id": 1, + "code": "accountUsage.detail", + "value": "DETAIL" + }, + "description": "Desc" + }, + { + "id": 3, + "name": "Fees Receivable", + "glCode": "100003", + "disabled": false, + "manualEntriesAllowed": true, + "type": { + "id": 1, + "code": "accountType.asset", + "value": "ASSET" + }, + "usage": { + "id": 1, + "code": "accountUsage.detail", + "value": "DETAIL" + }, + "description": "Desc" + }, + { + "id": 4, + "name": "Penalties Receivable", + "glCode": "100004", + "disabled": false, + "manualEntriesAllowed": true, + "type": { + "id": 1, + "code": "accountType.asset", + "value": "ASSET" + }, + "usage": { + "id": 1, + "code": "accountUsage.detail", + "value": "DETAIL" + }, + "description": "better duddette" + } + ], + "expenseAccountOptions": [ + { + "id": 5, + "name": "Written Off Losses", + "glCode": "500005", + "disabled": false, + "manualEntriesAllowed": true, + "type": { + "id": 5, + "code": "accountType.expense", + "value": "EXPENSE" + }, + "usage": { + "id": 1, + "code": "accountUsage.detail", + "value": "DETAIL" + }, + "description": "Desc" + } + ], + "incomeAccountOptions": [ + { + "id": 6, + "name": "Income from Interest", + "glCode": "400001", + "disabled": false, + "manualEntriesAllowed": true, + "type": { + "id": 4, + "code": "accountType.income", + "value": "INCOME" + }, + "usage": { + "id": 1, + "code": "accountUsage.detail", + "value": "DETAIL" + }, + "description": "Desc" + }, + { + "id": 7, + "name": "Income from Fees", + "glCode": "400002", + "disabled": false, + "manualEntriesAllowed": true, + "type": { + "id": 4, + "code": "accountType.income", + "value": "INCOME" + }, + "usage": { + "id": 1, + "code": "accountUsage.detail", + "value": "DETAIL" + }, + "description": "Desc" + }, + { + "id": 8, + "name": "Income from Penalties", + "glCode": "400003", + "disabled": false, + "manualEntriesAllowed": true, + "type": { + "id": 4, + "code": "accountType.income", + "value": "INCOME" + }, + "usage": { + "id": 1, + "code": "accountUsage.detail", + "value": "DETAIL" + }, + "description": "Desc" + } + ] + }, "accountingMappings": {} } @@ -4355,7 +4639,7 @@ GET https://DomainName/api/v1/loanproducts/{productId} "code": "interestCalculationPeriodType.same.as.repayment.period", "value": "Same as repayment period" }, - "accountingType": 1, + "accountingRule": 1, "charges": [] } @@ -4367,7 +4651,17 @@ GET https://DomainName/api/v1/loanproducts/{productId}

Create a Loan Product

- +

Depending of the Accounting Rule (accountingRule) selected, + additional fields with details with the appropriate Ledger Account + identifiers would need to be passed in. +

+ +

Refer + MifosX Accounting Specs Draft for more details regarding the + significance of the selected accounting Rule +

+ +
@@ -4376,7 +4670,24 @@ GET https://DomainName/api/v1/loanproducts/{productId} inArrearsTolerance, repaymentFrequencyType, repaymentEvery, numberOfRepayments, interestRatePerPeriod, interestRateFrequencyType, amortizationType, interestType, - interestCalculationPeriodType, accountingType + interestCalculationPeriodType, accountingRule + + + + + + + + + + + +
Mandatory Fields
Additional Mandatory Fields for Cash(2) based accounting
fundSourceAccountId, loanPortfolioAccountId, interestOnLoanAccountId, + incomeFromFeeAccountId, incomeFromPenaltyAccountId, + writeOffAccountId
Additional Mandatory Fields for Accrual(3) based accounting
fundSourceAccountId, loanPortfolioAccountId, interestOnLoanAccountId, + incomeFromFeeAccountId, incomeFromPenaltyAccountId, + writeOffAccountId, receivableInterestAccountId, receivableFeeAccountId, + receivablePenaltyAccountId
@@ -4403,7 +4714,7 @@ Request Body: "amortizationType": 1, "interestType": 0, "interestCalculationPeriodType": 1, - "accountingType": 1 + "accountingRule": 1 } @@ -4411,6 +4722,76 @@ Request Body: "resourceId": 1 } + +POST loanproducts +Content-Type: application/json +Request Body: +{ + "name": "A new loan product for me", + "currencyCode": "USD", + "locale": "en_GB", + "digitsAfterDecimal": "2", + "principal": "100,000.00", + "numberOfRepayments": "12", + "repaymentEvery": "1", + "repaymentFrequencyType": 2, + "transactionProcessingStrategyId": 1, + "interestRatePerPeriod": "1.75", + "interestRateFrequencyType": 2, + "amortizationType": 1, + "interestType": 0, + "interestCalculationPeriodType": 1, + "accountingRule":"3", + "fundSourceAccountId":"15", + "loanPortfolioAccountId":"16", + "interestOnLoanAccountId":"14", + "incomeFromFeeAccountId":"13", + "incomeFromPenaltyAccountId":"12", + "writeOffAccountId":"11" +} + + +{ + "resourceId": 2 +} + + +POST loanproducts +Content-Type: application/json +Request Body: +{ + "name": "A new loan product for me", + "currencyCode": "USD", + "locale": "en_GB", + "digitsAfterDecimal": "2", + "principal": "100,000.00", + "numberOfRepayments": "12", + "repaymentEvery": "1", + "repaymentFrequencyType": 2, + "transactionProcessingStrategyId": 1, + "interestRatePerPeriod": "1.75", + "interestRateFrequencyType": 2, + "amortizationType": 1, + "interestType": 0, + "interestCalculationPeriodType": 1, + "accountingRule":"3", + "fundSourceAccountId":"15", + "loanPortfolioAccountId":"16", + "receivableInterestAccountId":"10", + "receivableFeeAccountId":"9", + "receivablePenaltyAccountId":"8", + "interestOnLoanAccountId":"14", + "incomeFromFeeAccountId":"13", + "incomeFromPenaltyAccountId":"12", + "writeOffAccountId":"11" +} + + +{ + "resourceId": 3 +} + +
@@ -6985,6 +7366,390 @@ GET https://DomainName/api/v1/permissions + +   +
+
+

General Ledger Account

+

Ledger accounts represent an Individual account within an Organizations Chart + Of Accounts(COA) and are assigned a name and unique number by which they can + be identified.
+ All transactions relating to a company's assets, liabilities, owners' equity, + revenue and expenses are recorded against these accounts +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field Descriptions
name
The name of the account
glCode
The Ledger code associated with the + Account
These codes are mandatory and should be unique within + an organization
disabled
A boolean flag that indicates whether an account + is currently in use
type
Classifies the account into one of the following Types +
Asset accounts: represent the different types of economic resources + owned or controlled by business, common examples of Asset accounts are cash, + cash in bank, building, inventory, prepaid rent, goodwill, accounts receivable
+ Liability accounts: represent the different types of economic obligations + by a business, such as accounts payable, bank loan, bonds payable
+ Income accounts: represent the company's gross earnings and common examples + include Interest Income, Sales and Service revenue
+ Expense accounts: represent the company's expenditures to enable itself to + operate. Common examples are electricity and water, rentals, depreciation, + doubtful accounts, insurance.
+ Equity accounts: represent the residual equity of a business (after + deducting from Assets all the liabilities) including Retained Earnings + and Appropriations

+ The options are fully listed in Retrieve + General Ledger Accounts Template. +
usage
Determines how the account shall be used
+ "Header" accounts specify the title of a group of accounts. Header accounts are used + only to group detail accounts that have a similar purpose; that is, detail accounts + are assigned to specific header accounts +
+ "Detail" accounts may have transactions logged against them

+ The options are fully listed in Retrieve + General Ledger Accounts Template. +
manualEntriesAllowed
Specifies if manual adjustments can be made + against this account using the + Create Journal Entries API
description
Human understandable description for the Ledger Account +
+
+
+ +   +
+
+

List General Ledger Accounts

+
Arguments
+
+
type
+
+ Integer optional +
+
manualAdjustmentsAllowed
+
+ boolean optional +
+
usage
+
+ Integer optional +
+
disabled
+
+ boolean optional +
+
+

Example Requests:

+
glaccounts
+
+
+
glaccounts?type=1&manualAdjustmentsAllowed=true&usage=1&disabled=false
+
+
+ +GET https://DomainName/api/v1/glaccounts + + +[ + { + "id": 16, + "name": "Cash", + "glCode": "100001", + "disabled": false, + "manualEntriesAllowed": true, + "type": { + "id": 1, + "code": "accountType.asset", + "value": "ASSET" + }, + "usage": { + "id": 1, + "code": "accountUsage.detail", + "value": "DETAIL" + }, + "description": "Desc" + }, + { + "id": 15, + "name": "Fund Source For Loan", + "glCode": "100002", + "disabled": false, + "manualEntriesAllowed": true, + "type": { + "id": 1, + "code": "accountType.asset", + "value": "ASSET" + }, + "usage": { + "id": 1, + "code": "accountUsage.detail", + "value": "DETAIL" + }, + "description": "Desc" + } +] + +
+
+ +   +
+
+

Retrieve GL Accounts Template

+

This is a convenience resource. It can be useful when + building maintenance user interface screens for client + applications. The template data returned consists of any or all + of: +

+

+

Example Request:

+
glaccounts/template
+
+
+ +GET https://DomainName/api/v1/glaccounts/template + + +{ + "disabled": false, + "manualEntriesAllowed": true, + "type": { + "id": 1, + "code": "accountType.asset", + "value": "ASSET" + }, + "usage": { + "id": 1, + "code": "accountUsage.detail", + "value": "DETAIL" + }, + "accountTypeOptions": [ + { + "id": 1, + "code": "accountType.asset", + "value": "ASSET" + }, + { + "id": 2, + "code": "accountType.liability", + "value": "LIABILITY" + }, + { + "id": 3, + "code": "accountType.equity", + "value": "EQUITY" + }, + { + "id": 4, + "code": "accountType.income", + "value": "INCOME" + }, + { + "id": 5, + "code": "accountType.expense", + "value": "EXPENSE" + } + ], + "usageOptions": [ + { + "id": 1, + "code": "accountUsage.detail", + "value": "DETAIL" + }, + { + "id": 2, + "code": "accountUsage.header", + "value": "HEADER" + } + ] +} + +
+
+ + +   +
+
+

Retrieve a General Ledger Account

+

Example Requests:

+
glaccounts/1
+
+
+
glaccounts/1?template=true
+
+
+
glaccounts/1?fields=name,glCode
+
+
+ +GET https://DomainName/api/v1/glaccounts/{glaccountsId} + + +{ + "id": 1, + "name": "Cash", + "glCode": "100001", + "disabled": false, + "manualEntriesAllowed": true, + "type": { + "id": 1, + "code": "accountType.asset1", + "value": "ASSET" + }, + "usage": { + "id": 1, + "code": "accountUsage.detail", + "value": "DETAIL" + }, + "description": "Desc" +} + +
+
+ +   +
+
+

Create a General Ledger Account

+

+ Note: You can optionally
+ create a Hierarchical Chart of Account by using the "parentId" + property of an Account
+

+ + + + + + + +
Mandatory Fields
name, glCode, classification, usage and manualEntriesAllowed +
+
+
+ +POST https://DomainName/api/v1/glaccounts_update + + +POST glaccounts +Content-Type: application/json +Request Body: +{ + "name": "Cash at Bangalore", + "glCode": "100017", + "manualEntriesAllowed": true, + "classification": 1, + "usage": 1, + "description": "Cash at Bangalore Branch" +} + + +{ + "resourceId": 22 +} + +
+
+ +   +
+
+

Update a General Ledger Account

+
+
+ +PUT https://DomainName/api/v1/glaccounts/{glaccountId} + + +PUT glaccounts/1 +Content-Type: application/json +Request Body: +{ + "name": "Cash at Tumkur" +} + + +{ + "resourceId": 1, +} + +
+
+ +   +
+
+

Delete a General Ledger Account

+

+ Note: Only Ledger Accounts against which no transactions have been logged + (either manually or by the loan or Savings portfolio) can be deleted. +

+
+
+ +DELETE https://DomainName/api/v1/glaccounts/{glaccountId} + + +DELETE glaccounts/1 +Content-Type: application/json +No Request Body: + + +{ + "resourceId": 1 +} + +
+
+ + diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/api/GLAccountsApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/api/GLAccountsApiResource.java index a26122e0c..bdc622e9c 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/api/GLAccountsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/api/GLAccountsApiResource.java @@ -70,7 +70,7 @@ public class GLAccountsApiResource { @GET @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String retrieveAllAccounts(@Context final UriInfo uriInfo, @QueryParam("classification") final Integer classification, + public String retrieveAllAccounts(@Context final UriInfo uriInfo, @QueryParam("type") final Integer classification, @QueryParam("searchParam") final String searchParam, @QueryParam("usage") final Integer usage, @QueryParam("manualAdjustmentsAllowed") final Boolean manualTransactionsAllowed, @QueryParam("disabled") final Boolean disabled) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/api/GLJournalEntriesApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/api/GLJournalEntriesApiResource.java index 7a16871bc..b106a1a6f 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/api/GLJournalEntriesApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/api/GLJournalEntriesApiResource.java @@ -15,6 +15,7 @@ import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.UriInfo; +import org.apache.commons.lang.StringUtils; import org.mifosplatform.accounting.api.commands.GLJournalEntryCommand; import org.mifosplatform.accounting.api.data.GLJournalEntryData; import org.mifosplatform.accounting.api.data.JournalEntryIdentifier; @@ -24,6 +25,7 @@ import org.mifosplatform.accounting.api.infrastructure.DateParam; import org.mifosplatform.accounting.service.GLJournalEntryReadPlatformService; import org.mifosplatform.accounting.service.GLJournalEntryWritePlatformService; import org.mifosplatform.infrastructure.core.api.ApiParameterHelper; +import org.mifosplatform.infrastructure.core.exception.UnrecognizedQueryParamException; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; @@ -58,9 +60,9 @@ public class GLJournalEntriesApiResource { @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) public String retrieveAllJournalEntries(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId, - @QueryParam("glAccountId") final Long glAccountId, - @QueryParam("portfolioGenerated") final Boolean portfolioGenerated, @QueryParam("fromDate") final DateParam fromDateParam, - @QueryParam("toDate") final DateParam toDateParam) { + @QueryParam("glAccountId") final Long glAccountId, @QueryParam("portfolioGenerated") final Boolean portfolioGenerated, + @QueryParam("fromDate") final DateParam fromDateParam, @QueryParam("toDate") final DateParam toDateParam, + @QueryParam("transactionId") String transactionId) { // TODO: Vishwas Add pagination, approach at // http://www.javaworld.com/community/node/8295 looks good @@ -79,8 +81,13 @@ public class GLJournalEntriesApiResource { if (toDateParam != null) { toDate = toDateParam.getDate(); } - glJournalEntryDatas = this.glJournalEntryReadPlatformService.retrieveAllGLJournalEntries(officeId, glAccountId, - portfolioGenerated, fromDate, toDate); + if (StringUtils.isBlank(transactionId)) { + glJournalEntryDatas = this.glJournalEntryReadPlatformService.retrieveAllGLJournalEntries(officeId, glAccountId, + portfolioGenerated, fromDate, toDate); + } else { + glJournalEntryDatas = this.glJournalEntryReadPlatformService.retrieveRelatedJournalEntries(transactionId); + } + return this.apiJsonSerializerService.serializeGLJournalEntryDataToJson(prettyPrint, responseParameters, glJournalEntryDatas); } @@ -88,7 +95,7 @@ public class GLJournalEntriesApiResource { @Path("{glJournalEntryId}") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String retreiveAccount(@PathParam("glJournalEntryId") final Long glJournalEntryId, @Context final UriInfo uriInfo) { + public String retreiveJournalEntryById(@PathParam("glJournalEntryId") final Long glJournalEntryId, @Context final UriInfo uriInfo) { context.authenticatedUser().validateHasReadPermission(entityType); @@ -111,13 +118,21 @@ public class GLJournalEntriesApiResource { } @POST - @Path("{transactionId}/reversal") + @Path("{transactionId}") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String createReversalJournalEntry(@PathParam("transactionId") final String transactionId) { - - this.glJournalEntryWritePlatformService.revertJournalEntry(transactionId); + public String createReversalJournalEntry(@PathParam("transactionId") final String transactionId, + @QueryParam("command") final String commandParam) { + if (is(commandParam, "reverse")) { + this.glJournalEntryWritePlatformService.revertJournalEntry(transactionId); + } else { + throw new UnrecognizedQueryParamException("command", commandParam); + } return this.apiJsonSerializerService.serializeJournalEntryIdentifier(new JournalEntryIdentifier(transactionId)); } + + private boolean is(final String commandParam, final String commandValue) { + return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/exceptions/GLJournalEntryNotFoundException.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/exceptions/GLJournalEntryNotFoundException.java new file mode 100755 index 000000000..fbb9e0219 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/exceptions/GLJournalEntryNotFoundException.java @@ -0,0 +1,18 @@ +package org.mifosplatform.accounting.exceptions; + +import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException; + +/** + * A {@link RuntimeException} thrown when journal entry resources are not found. + */ +public class GLJournalEntryNotFoundException extends AbstractPlatformResourceNotFoundException { + + public GLJournalEntryNotFoundException(final String transactionId) { + super("error.msg.journalEntries.transactionId.invalid", "Journal Entries with transaction Identifier " + transactionId + + " does not exist or are not system generated/reversible ", transactionId); + } + + public GLJournalEntryNotFoundException(final Long entryId) { + super("error.msg.journalEntries.id.invalid", "Journal Entry with entry Id " + entryId + " does not exist ", entryId); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/GLAccountCommandValidator.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/GLAccountCommandValidator.java index 15ace6697..8f2b2684f 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/GLAccountCommandValidator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/GLAccountCommandValidator.java @@ -30,7 +30,7 @@ public class GLAccountCommandValidator { baseDataValidator.reset().parameter("parentId").value(command.getParentId()).ignoreIfNull().integerGreaterThanZero(); - baseDataValidator.reset().parameter("classification").value(command.getClassification()) + baseDataValidator.reset().parameter("classification").value(command.getClassification()).notNull() .inMinMaxRange(GLAccountType.getMinValue(), GLAccountType.getMaxValue()); baseDataValidator.reset().parameter("usage").value(command.getUsage()) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/GLJournalEntryReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/GLJournalEntryReadPlatformService.java index 891b0eb47..7cbe1e93a 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/GLJournalEntryReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/GLJournalEntryReadPlatformService.java @@ -10,6 +10,8 @@ public interface GLJournalEntryReadPlatformService { List retrieveAllGLJournalEntries(Long officeId, Long glAccountId, Boolean portfolioGenerated, Date fromDate, Date toDate); + List retrieveRelatedJournalEntries(String transactionId); + GLJournalEntryData retrieveGLJournalEntryById(long glJournalEntryId); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLAccountReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLAccountReadPlatformServiceImpl.java index f70277787..1d9d7ffc8 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLAccountReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLAccountReadPlatformServiceImpl.java @@ -45,7 +45,7 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe Long id = rs.getLong("id"); String name = rs.getString("name"); - Long parentId = rs.getLong("parentId"); + Long parentId = JdbcSupport.getLong(rs,"parentId"); String glCode = rs.getString("glCode"); boolean disabled = rs.getBoolean("disabled"); boolean manualEntriesAllowed = rs.getBoolean("manualEntriesAllowed"); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLClosureReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLClosureReadPlatformServiceImpl.java index 9f01998b4..c11066d4f 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLClosureReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLClosureReadPlatformServiceImpl.java @@ -73,7 +73,7 @@ public class GLClosureReadPlatformServiceImpl implements GLClosureReadPlatformSe arrayPos = arrayPos + 1; } - sql = sql + " order by glClosure.closing_date"; + sql = sql + " order by glClosure.closing_date desc"; Object[] finalObjectArray = Arrays.copyOf(objectArray, arrayPos); return this.jdbcTemplate.query(sql, rm, finalObjectArray); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLJournalEntryReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLJournalEntryReadPlatformServiceImpl.java index 4f3273984..507f1d026 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLJournalEntryReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLJournalEntryReadPlatformServiceImpl.java @@ -134,7 +134,7 @@ public class GLJournalEntryReadPlatformServiceImpl implements GLJournalEntryRead } } - sql += " order by journalEntry.entry_date,journalEntry.transaction_id"; + sql += " order by journalEntry.entry_date desc,journalEntry.transaction_id"; Object[] finalObjectArray = Arrays.copyOf(objectArray, arrayPos); return this.jdbcTemplate.query(sql, rm, finalObjectArray); @@ -147,12 +147,27 @@ public class GLJournalEntryReadPlatformServiceImpl implements GLJournalEntryRead GLJournalEntryMapper rm = new GLJournalEntryMapper(); String sql = "select " + rm.schema() + " and journalEntry.id = ?"; - GLJournalEntryData glAccountData = this.jdbcTemplate.queryForObject(sql, rm, new Object[] { glJournalEntryId }); + GLJournalEntryData glJournalEntryData = this.jdbcTemplate.queryForObject(sql, rm, new Object[] { glJournalEntryId }); - return glAccountData; + return glJournalEntryData; } catch (EmptyResultDataAccessException e) { throw new GLJournalEntriesNotFoundException(glJournalEntryId); } } + @Override + public List retrieveRelatedJournalEntries(String transactionId) { + try { + + GLJournalEntryMapper rm = new GLJournalEntryMapper(); + String sql = "select " + rm.schema() + " and journalEntry.transaction_id = ?"; + + List journalEntryDatas = this.jdbcTemplate.query(sql, rm, new Object[] { transactionId }); + + return journalEntryDatas; + } catch (EmptyResultDataAccessException e) { + throw new GLJournalEntriesNotFoundException(transactionId); + } + } + } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/ProductToGLAccountMappingWritePlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/ProductToGLAccountMappingWritePlatformServiceImpl.java index 8ec074334..3cbb1461d 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/ProductToGLAccountMappingWritePlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/ProductToGLAccountMappingWritePlatformServiceImpl.java @@ -50,7 +50,7 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc @Transactional public void createLoanProductToGLAccountMapping(final Long loanProductId, final JsonCommand command) { final JsonElement element = this.fromApiJsonHelper.parse(command.json()); - final Integer accountingRuleTypeId = this.fromApiJsonHelper.extractIntegerNamed("accountingType", element, Locale.getDefault()); + final Integer accountingRuleTypeId = this.fromApiJsonHelper.extractIntegerNamed("accountingRule", element, Locale.getDefault()); final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(accountingRuleTypeId); switch (accountingRuleType) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java index 273183000..6be325542 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java @@ -41,7 +41,7 @@ public class CommandWrapperBuilder { this.json = withJson; return this; } - + public CommandWrapperBuilder updateGlobalConfiguration() { this.actionName = "UPDATE"; this.entityName = "CONFIGURATION"; @@ -127,7 +127,7 @@ public class CommandWrapperBuilder { this.href = "/officetransactions/template"; return this; } - + public CommandWrapperBuilder deleteOfficeTransaction(final Long transactionId) { this.actionName = "DELETE"; this.entityName = "OFFICETRANSACTION"; @@ -151,28 +151,31 @@ public class CommandWrapperBuilder { this.href = "/staff/" + staffId; return this; } - - public CommandWrapperBuilder createGuarantor() { + + public CommandWrapperBuilder createGuarantor(final Long loanId) { this.actionName = "CREATE"; this.entityName = "GUARANTOR"; this.entityId = null; - this.href = "/guarantors/template"; + this.loanId = loanId; + this.href = "/loans/" + loanId + "/guarantors/template"; return this; } - public CommandWrapperBuilder updateGuarantor(final Long guarantorId) { + public CommandWrapperBuilder updateGuarantor(final Long loanId, final Long guarantorId) { this.actionName = "UPDATE"; this.entityName = "GUARANTOR"; this.entityId = guarantorId; - this.href = "/guarantors/" + guarantorId; + this.loanId = loanId; + this.href = "/loans/" + loanId + "/guarantors/" + guarantorId; return this; } - - public CommandWrapperBuilder deleteGuarantor(final Long guarantorId) { + + public CommandWrapperBuilder deleteGuarantor(final Long loanId, final Long guarantorId) { this.actionName = "DELETE"; this.entityName = "GUARANTOR"; this.entityId = guarantorId; - this.href = "/guarantors/" + guarantorId; + this.loanId = loanId; + this.href = "/loans/" + loanId + "/guarantors/" + guarantorId; return this; } @@ -549,7 +552,7 @@ public class CommandWrapperBuilder { this.href = "/loans/" + loanId; return this; } - + public CommandWrapperBuilder unassignLoanOfficer(final Long loanId) { this.actionName = "REMOVELOANOFFICER"; this.entityName = "LOAN"; @@ -565,7 +568,7 @@ public class CommandWrapperBuilder { this.href = "/loans/loanreassignment"; return this; } - + public CommandWrapperBuilder createCodeValue(final Long codeId) { this.actionName = "CREATE"; this.entityName = "CODEVALUE"; @@ -573,7 +576,7 @@ public class CommandWrapperBuilder { this.href = "/codes/" + codeId + "/codevalues/template"; return this; } - + public CommandWrapperBuilder updateCodeValue(Long codeId, final Long codeValueId) { this.actionName = "UPDATE"; this.entityName = "CODEVALUE"; @@ -582,7 +585,7 @@ public class CommandWrapperBuilder { this.href = "/codes/" + codeId + "/codevalues/" + codeValueId; return this; } - + public CommandWrapperBuilder deleteCodeValue(Long codeId, final Long codeValueId) { this.actionName = "DELETE"; this.entityName = "CODEVALUE"; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/guarantor/api/GuarantorsApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/guarantor/api/GuarantorsApiResource.java index df2a97426..ff095372d 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/guarantor/api/GuarantorsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/guarantor/api/GuarantorsApiResource.java @@ -34,12 +34,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; -@Path("/guarantors") +@Path("/loans/{loanId}/guarantors") @Component @Scope("singleton") public class GuarantorsApiResource { - private static final Set RESPONSE_DATA_PARAMETERS = new HashSet(Arrays.asList("externalGuarantor", "existingClientId", + private static final Set RESPONSE_DATA_PARAMETERS = new HashSet(Arrays.asList("guarantorTypeId", "entityId", "firstname", "lastname", "addressLine1", "addressLine2", "city", "state", "zip", "country", "mobileNumber", "housePhoneNumber", "comment", "dob")); @@ -75,14 +75,28 @@ public class GuarantorsApiResource { return this.apiJsonSerializerService.serialize(settings, guarantorData, RESPONSE_DATA_PARAMETERS); } + @GET + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveGuarantorDetails(@Context final UriInfo uriInfo, @PathParam("loanId") final Long loanId) { + context.authenticatedUser().validateHasReadPermission(resourceNameForPermission); + + List guarantorDatas = guarantorReadPlatformService.retrieveGuarantorsForValidLoan(loanId); + + final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + + return this.apiJsonSerializerService.serialize(settings, guarantorDatas, RESPONSE_DATA_PARAMETERS); + } + @GET @Path("{guarantorId}") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String retrieveGuarantorDetails(@Context final UriInfo uriInfo, @PathParam("guarantorId") final Long guarantorId) { + public String retrieveGuarantorDetails(@Context final UriInfo uriInfo, @PathParam("loanId") final Long loanId, + @PathParam("guarantorId") final Long guarantorId) { context.authenticatedUser().validateHasReadPermission(resourceNameForPermission); - GuarantorData guarantorData = guarantorReadPlatformService.retrieveGuarantor(guarantorId); + GuarantorData guarantorData = guarantorReadPlatformService.retrieveGuarantor(loanId, guarantorId); final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); if (settings.isTemplate()) { @@ -96,9 +110,9 @@ public class GuarantorsApiResource { @POST @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String createGuarantor(final String apiRequestBodyAsJson) { + public String createGuarantor(@PathParam("loanId") final Long loanId, final String apiRequestBodyAsJson) { - final CommandWrapper commandRequest = new CommandWrapperBuilder().createGuarantor().withJson(apiRequestBodyAsJson).build(); + final CommandWrapper commandRequest = new CommandWrapperBuilder().createGuarantor(loanId).withJson(apiRequestBodyAsJson).build(); final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); @@ -109,8 +123,10 @@ public class GuarantorsApiResource { @Path("{guarantorId}") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String updateGuarantor(@PathParam("guarantorId") final Long guarantorId, final String jsonRequestBody) { - final CommandWrapper commandRequest = new CommandWrapperBuilder().updateGuarantor(guarantorId).withJson(jsonRequestBody).build(); + public String updateGuarantor(@PathParam("loanId") final Long loanId, @PathParam("guarantorId") final Long guarantorId, + final String jsonRequestBody) { + final CommandWrapper commandRequest = new CommandWrapperBuilder().updateGuarantor(loanId, guarantorId).withJson(jsonRequestBody) + .build(); final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); @@ -121,8 +137,8 @@ public class GuarantorsApiResource { @Path("{guarantorId}") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String deleteGuarantor(@PathParam("guarantorId") final Long guarantorId) { - final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteGuarantor(guarantorId).build(); + public String deleteGuarantor(@PathParam("loanId") final Long loanId, @PathParam("guarantorId") final Long guarantorId) { + final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteGuarantor(loanId, guarantorId).build(); final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/guarantor/service/GuarantorReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/guarantor/service/GuarantorReadPlatformService.java index b2936b298..f40657cf8 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/guarantor/service/GuarantorReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/guarantor/service/GuarantorReadPlatformService.java @@ -6,9 +6,24 @@ import org.mifosplatform.portfolio.loanaccount.guarantor.data.GuarantorData; public interface GuarantorReadPlatformService { + /** + * Validates the passed in loanId before retrieving Loans for the same + * + * @param loanId + * @return + */ + List retrieveGuarantorsForValidLoan(Long loanId); + + /** + * Methods Returns all Guarantors for a Given loan Id (if the loan Id is + * valid and Exists) + * + * @param loanId + * @return + */ List retrieveGuarantorsForLoan(Long loanId); - GuarantorData retrieveGuarantor(Long guarantorId); + GuarantorData retrieveGuarantor(Long loanId, Long guarantorId); GuarantorData retrieveNewGuarantorDetails(); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/guarantor/service/GuarantorReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/guarantor/service/GuarantorReadPlatformServiceImpl.java index ea4697ddc..cf3712ad1 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/guarantor/service/GuarantorReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/guarantor/service/GuarantorReadPlatformServiceImpl.java @@ -13,6 +13,9 @@ import org.mifosplatform.organisation.staff.data.StaffData; import org.mifosplatform.organisation.staff.service.StaffReadPlatformService; import org.mifosplatform.portfolio.client.data.ClientData; import org.mifosplatform.portfolio.client.service.ClientReadPlatformService; +import org.mifosplatform.portfolio.loanaccount.domain.Loan; +import org.mifosplatform.portfolio.loanaccount.domain.LoanRepository; +import org.mifosplatform.portfolio.loanaccount.exception.LoanNotFoundException; import org.mifosplatform.portfolio.loanaccount.guarantor.data.GuarantorData; import org.mifosplatform.portfolio.loanaccount.guarantor.domain.GuarantorType; import org.springframework.beans.factory.annotation.Autowired; @@ -26,13 +29,16 @@ public class GuarantorReadPlatformServiceImpl implements GuarantorReadPlatformSe private final JdbcTemplate jdbcTemplate; private final ClientReadPlatformService clientReadPlatformService; private final StaffReadPlatformService staffReadPlatformService; + private final LoanRepository loanRepository; @Autowired public GuarantorReadPlatformServiceImpl(final TenantAwareRoutingDataSource dataSource, - final ClientReadPlatformService clientReadPlatformService, final StaffReadPlatformService staffReadPlatformService) { + final ClientReadPlatformService clientReadPlatformService, final StaffReadPlatformService staffReadPlatformService, + final LoanRepository loanRepository) { this.jdbcTemplate = new JdbcTemplate(dataSource); this.clientReadPlatformService = clientReadPlatformService; this.staffReadPlatformService = staffReadPlatformService; + this.loanRepository = loanRepository; } private static final class GuarantorMapper implements RowMapper { @@ -68,6 +74,13 @@ public class GuarantorReadPlatformServiceImpl implements GuarantorReadPlatformSe } } + @Override + public List retrieveGuarantorsForValidLoan(Long loanId) { + Loan loan = this.loanRepository.findOne(loanId); + if (loan == null) { throw new LoanNotFoundException(loanId); } + return retrieveGuarantorsForLoan(loanId); + } + @Override public List retrieveGuarantorsForLoan(Long loanId) { final GuarantorMapper rm = new GuarantorMapper(); @@ -84,11 +97,11 @@ public class GuarantorReadPlatformServiceImpl implements GuarantorReadPlatformSe } @Override - public GuarantorData retrieveGuarantor(Long guarantorId) { + public GuarantorData retrieveGuarantor(Long loanId, Long guarantorId) { final GuarantorMapper rm = new GuarantorMapper(); String sql = "select " + rm.schema(); - sql += " where loan_id = ?"; - GuarantorData guarantorData = this.jdbcTemplate.queryForObject(sql, rm, new Object[] { guarantorId }); + sql += " where g.loan_id = ? and g.id = ?"; + GuarantorData guarantorData = this.jdbcTemplate.queryForObject(sql, rm, new Object[] { loanId, guarantorId }); return mergeDetailsForClientOrStaffGuarantor(guarantorData); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/guarantor/service/GuarantorWritePlatformServiceJpaRepositoryIImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/guarantor/service/GuarantorWritePlatformServiceJpaRepositoryIImpl.java index 339b30cd5..92193b1d0 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/guarantor/service/GuarantorWritePlatformServiceJpaRepositoryIImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/guarantor/service/GuarantorWritePlatformServiceJpaRepositoryIImpl.java @@ -58,7 +58,7 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto final GuarantorCommand guarantorCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json()); guarantorCommand.validateForCreate(); - final Long loanId = command.longValueOfParameterNamed(GUARANTOR_JSON_INPUT_PARAMS.LOAN_ID.getValue()); + final Long loanId = command.getLoanId(); Loan loan = retrieveLoanById(loanId); Guarantor guarantor = null; guarantor = Guarantor.fromJson(loan, command); @@ -83,6 +83,7 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto final GuarantorCommand guarantorCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json()); guarantorCommand.validateForUpdate(); + // TODO: Vishwas need to fetch by both loan and Guarantor Id final Guarantor guarantorForUpdate = this.guarantorRepository.findOne(guarantorId); if (guarantorForUpdate == null) { throw new GuarantorNotFoundException(guarantorId); } @@ -108,6 +109,7 @@ public class GuarantorWritePlatformServiceJpaRepositoryIImpl implements Guaranto @Override @Transactional public CommandProcessingResult removeGuarantor(final Long guarantorId) { + // TODO: Vishwas need to fetch by both loan and Guarantor Id final Guarantor guarantorForDelete = this.guarantorRepository.findOne(guarantorId); if (guarantorForDelete == null) { throw new GuarantorNotFoundException(guarantorId); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/api/LoanProductsApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/api/LoanProductsApiResource.java index 798eb51b3..de8bf13bd 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/api/LoanProductsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/api/LoanProductsApiResource.java @@ -19,7 +19,6 @@ import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.UriInfo; -import org.mifosplatform.accounting.AccountingConstants.LOAN_PRODUCT_ACCOUNTING_PARAMS; import org.mifosplatform.accounting.api.data.GLAccountData; import org.mifosplatform.accounting.domain.GLAccountType; import org.mifosplatform.accounting.service.GLAccountReadPlatformService; @@ -58,12 +57,7 @@ public class LoanProductsApiResource { "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType", "charges", "createdOn", "lastModifedOn", "currencyOptions", "amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions", "repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions", "transactionProcessingStrategyOptions", - "chargeOptions", "assetAccountOptions", "incomeAccountOptions", "expenseAccountOptions", "accountingType", - LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), - LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), - LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(), - LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), - LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue())); + "chargeOptions", "accountingOptions", "accountingRule","accountingRuleOptions","accountingMappings","accountingMappingOptions")); private final String resourceNameForPermissions = "LOANPRODUCT"; @@ -205,22 +199,29 @@ public class LoanProductsApiResource { final Collection transactionProcessingStrategyOptions = this.dropdownReadPlatformService .retreiveTransactionProcessingStrategies(); + Map> accountOptions= new HashMap>(); List assetAccountOptions = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GLAccountType.ASSET); if (assetAccountOptions.isEmpty()) { assetAccountOptions = null; } + accountOptions.put("assetAccountOptions", assetAccountOptions); + List incomeAccountOptions = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GLAccountType.INCOME); if (incomeAccountOptions.isEmpty()) { incomeAccountOptions = null; } + accountOptions.put("incomeAccountOptions", incomeAccountOptions); + List expenseAccountOptions = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GLAccountType.EXPENSE); if (expenseAccountOptions.isEmpty()) { expenseAccountOptions = null; } + accountOptions.put("expenseAccountOptions", expenseAccountOptions); + + List accountingRuleTypeOptions = dropdownReadPlatformService.retrieveAccountingRuleTypeOptions(); return new LoanProductData(productData, chargeOptions, currencyOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions, - interestRateFrequencyTypeOptions, fundOptions, transactionProcessingStrategyOptions, assetAccountOptions, - incomeAccountOptions, expenseAccountOptions, accountingMappings); + interestRateFrequencyTypeOptions, fundOptions, transactionProcessingStrategyOptions, accountOptions, accountingRuleTypeOptions,accountingMappings); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanProductData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanProductData.java index d586d2f95..06474106f 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanProductData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanProductData.java @@ -44,8 +44,8 @@ public class LoanProductData { private final EnumOptionData interestType; private final EnumOptionData interestCalculationPeriodType; private final BigDecimal inArrearsTolerance; - - private final EnumOptionData accountingType; + + private final EnumOptionData accountingRule; private final Collection charges; @@ -62,9 +62,8 @@ public class LoanProductData { private final Collection chargeOptions; // accounting related template fields - private final List assetAccountOptions; - private final List incomeAccountOptions; - private final List expenseAccountOptions; + private final List accountingRuleOptions; + private final Map> accountingMappingOptions; // accounting related mapping fields @SuppressWarnings("unused") @@ -140,7 +139,7 @@ public class LoanProductData { productData.amortizationTypeOptions, productData.interestTypeOptions, productData.interestCalculationPeriodTypeOptions, productData.loanTermFrequencyTypeOptions, productData.repaymentFrequencyTypeOptions, productData.interestRateFrequencyTypeOptions, productData.fundOptions, productData.transactionProcessingStrategyOptions, - productData.assetAccountOptions, productData.incomeAccountOptions, productData.expenseAccountOptions, accountingMappings); + productData.accountingMappingOptions, productData.accountingRuleOptions, accountingMappings); } public LoanProductData(final Long id, final String name, final String description, final CurrencyData currency, @@ -173,7 +172,7 @@ public class LoanProductData { this.transactionProcessingStrategyId = transactionProcessingStrategyId; this.transactionProcessingStrategyName = transactionProcessingStrategyName; this.charges = charges; - this.accountingType = accountingType; + this.accountingRule = accountingType; this.chargeOptions = null; this.currencyOptions = null; @@ -186,9 +185,8 @@ public class LoanProductData { this.repaymentFrequencyTypeOptions = null; this.interestRateFrequencyTypeOptions = null; - this.assetAccountOptions = null; - this.incomeAccountOptions = null; - this.expenseAccountOptions = null; + this.accountingMappingOptions = null; + this.accountingRuleOptions = null; this.accountingMappings = null; } @@ -198,8 +196,8 @@ public class LoanProductData { final List loanTermFrequencyTypeOptions, final List repaymentFrequencyTypeOptions, final List interestRateFrequencyTypeOptions, final Collection fundOptions, final Collection transactionProcessingStrategyOptions, - final List assetAccountOptions, final List incomeAccountOptions, - final List expenseAccountOptions, final Map accountingMappings) { + final Map> accountingMappingOptions, final List accountingRuleOptions, + final Map accountingMappings) { this.id = productData.id; this.name = productData.name; this.description = productData.description; @@ -221,7 +219,7 @@ public class LoanProductData { this.transactionProcessingStrategyId = productData.transactionProcessingStrategyId; this.transactionProcessingStrategyName = productData.transactionProcessingStrategyName; this.charges = nullIfEmpty(productData.charges()); - this.accountingType = productData.accountingType; + this.accountingRule = productData.accountingRule; this.chargeOptions = chargeOptions; this.currencyOptions = currencyOptions; @@ -239,9 +237,8 @@ public class LoanProductData { this.repaymentFrequencyTypeOptions = repaymentFrequencyTypeOptions; this.interestRateFrequencyTypeOptions = interestRateFrequencyTypeOptions; - this.assetAccountOptions = assetAccountOptions; - this.incomeAccountOptions = incomeAccountOptions; - this.expenseAccountOptions = expenseAccountOptions; + this.accountingMappingOptions = accountingMappingOptions; + this.accountingRuleOptions = accountingRuleOptions; this.accountingMappings = accountingMappings; } @@ -262,11 +259,11 @@ public class LoanProductData { } public EnumOptionData accountingRuleType() { - return this.accountingType; + return this.accountingRule; } public boolean hasAccountingEnabled() { - return this.accountingType.getId() > 1; + return this.accountingRule.getId() > 1; } public Long getId() { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/serialization/LoanProductCommandFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/serialization/LoanProductCommandFromApiJsonDeserializer.java index 1857a09ef..9728aae3c 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/serialization/LoanProductCommandFromApiJsonDeserializer.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/serialization/LoanProductCommandFromApiJsonDeserializer.java @@ -33,7 +33,7 @@ public final class LoanProductCommandFromApiJsonDeserializer { private final Set supportedParameters = new HashSet(Arrays.asList("name", "description", "fundId", "transactionProcessingStrategyId", "currencyCode", "digitsAfterDecimal", "principal", "inArrearsTolerance", "interestRatePerPeriod", "repaymentEvery", "numberOfRepayments", "repaymentFrequencyType", "interestRateFrequencyType", - "amortizationType", "interestType", "interestCalculationPeriodType", "charges", "locale", "accountingType", + "amortizationType", "interestType", "interestCalculationPeriodType", "charges", "locale", "accountingRule", LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(), @@ -114,8 +114,8 @@ public final class LoanProductCommandFromApiJsonDeserializer { .inMinMaxRange(0, 1); // accounting related data validation - final Integer accountingRuleType = fromApiJsonHelper.extractIntegerNamed("accountingType", element, Locale.getDefault()); - baseDataValidator.reset().parameter("accountingType").value(accountingRuleType).notNull().inMinMaxRange(1, 3); + final Integer accountingRuleType = fromApiJsonHelper.extractIntegerNamed("accountingRule", element, Locale.getDefault()); + baseDataValidator.reset().parameter("accountingRule").value(accountingRuleType).notNull().inMinMaxRange(1, 3); if (isCashBasedAccounting(accountingRuleType) || isAccrualBasedAccounting(accountingRuleType)) { @@ -266,8 +266,8 @@ public final class LoanProductCommandFromApiJsonDeserializer { .inMinMaxRange(0, 1); } - final Integer accountingRuleType = fromApiJsonHelper.extractIntegerNamed("accountingType", element, Locale.getDefault()); - baseDataValidator.reset().parameter("accountingType").value(accountingRuleType).ignoreIfNull().inMinMaxRange(1, 3); + final Integer accountingRuleType = fromApiJsonHelper.extractIntegerNamed("accountingRule", element, Locale.getDefault()); + baseDataValidator.reset().parameter("accountingRule").value(accountingRuleType).ignoreIfNull().inMinMaxRange(1, 3); final Long fundAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), element); baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue()).value(fundAccountId).ignoreIfNull() diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanDropdownReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanDropdownReadPlatformService.java index 312dce8b9..019c71848 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanDropdownReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanDropdownReadPlatformService.java @@ -21,4 +21,6 @@ public interface LoanDropdownReadPlatformService { List retrieveInterestRateFrequencyTypeOptions(); Collection retreiveTransactionProcessingStrategies(); + + List retrieveAccountingRuleTypeOptions(); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanDropdownReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanDropdownReadPlatformServiceImpl.java index 4e4483819..5c38432b1 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanDropdownReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanDropdownReadPlatformServiceImpl.java @@ -6,6 +6,7 @@ import static org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations.i import static org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations.interestType; import static org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations.loanTermFrequencyType; import static org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations.repaymentFrequencyType; +import static org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations.accountingRuleType; import java.util.ArrayList; import java.util.Arrays; @@ -15,6 +16,7 @@ import java.util.List; import org.mifosplatform.infrastructure.core.data.EnumOptionData; import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionProcessingStrategyRepository; import org.mifosplatform.portfolio.loanproduct.data.TransactionProcessingStrategyData; +import org.mifosplatform.portfolio.loanproduct.domain.AccountingRuleType; import org.mifosplatform.portfolio.loanproduct.domain.AmortizationMethod; import org.mifosplatform.portfolio.loanproduct.domain.InterestCalculationPeriodMethod; import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod; @@ -103,4 +105,11 @@ public class LoanDropdownReadPlatformServiceImpl implements LoanDropdownReadPlat return strategyOptions; } + + @Override + public List retrieveAccountingRuleTypeOptions() { + List accountingRuleTypeOptions = Arrays.asList(accountingRuleType(AccountingRuleType.NONE), + accountingRuleType(AccountingRuleType.CASH_BASED),accountingRuleType(AccountingRuleType.ACCRUAL_BASED)); + return accountingRuleTypeOptions; + } } \ No newline at end of file