diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm index 3d527db70..6ed3600c2 100644 --- a/api-docs/apiLive.htm +++ b/api-docs/apiLive.htm @@ -8998,7 +8998,7 @@ GET https://DomainName/api/v1/permissions glCode - The Ledger code associated with the + The ledger code associated with the Account
These codes are mandatory and should be unique within an organization @@ -9014,17 +9014,17 @@ GET https://DomainName/api/v1/permissions Classifies the account into one of the following Types -
Asset accounts: represent the different types of economic resources +
Asset: 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 + Liability: 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 + Income: 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 + Expense: 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 + Equity: 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 @@ -9036,8 +9036,8 @@ GET https://DomainName/api/v1/permissions 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 + "Header" accounts specify the title of a group of accounts. They are used + only for grouping together 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

@@ -9049,7 +9049,7 @@ GET https://DomainName/api/v1/permissions manualEntriesAllowed - Specifies if manual adjustments can be made + Specifies if manual entries can be made against this account using the
Create Journal Entries API @@ -9074,7 +9074,7 @@ GET https://DomainName/api/v1/permissions
Integer optional
-
manualAdjustmentsAllowed
+
manualEntriesAllowed
boolean optional
@@ -9091,7 +9091,7 @@ GET https://DomainName/api/v1/permissions
glaccounts


-
glaccounts?type=1&manualAdjustmentsAllowed=true&usage=1&disabled=false
+
glaccounts?type=1&manualEntriesAllowed=true&usage=1&disabled=false
@@ -9266,8 +9266,8 @@ GET https://DomainName/api/v1/glaccounts/{glaccountsId}

Create a General Ledger Account

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

@@ -9275,7 +9275,7 @@ GET https://DomainName/api/v1/glaccounts/{glaccountsId} -
Mandatory Fields
name, glCode, classification, usage and manualEntriesAllowed + name, glCode, type, usage and manualEntriesAllowed
@@ -9292,7 +9292,7 @@ Request Body: "name": "Cash at Bangalore", "glCode": "100017", "manualEntriesAllowed": true, - "classification": 1, + "type": 1, "usage": 1, "description": "Cash at Bangalore Branch" } @@ -9315,16 +9315,19 @@ Request Body: PUT https://DomainName/api/v1/glaccounts/{glaccountId}
-PUT glaccounts/1 +PUT glaccounts/22 Content-Type: application/json Request Body: { - "name": "Cash at Tumkur" + "name": "Cash at Bangalore rural" } { - "resourceId": 1 + "resourceId": 22, + "changes": { + "name": "Cash at Bangalore rural" + } }
@@ -9339,7 +9342,10 @@ Request Body: { - "resourceId": 1 + "resourceId": 1, + "changes": { + "disabled": true + } }
@@ -9365,7 +9371,8 @@ No Request Body: { - "resourceId": 1 + "resourceId": 1, + "changes": {} } @@ -9376,8 +9383,9 @@ No Request Body:

Accounting Closure

An accounting closure indicates that no more journal - entries may be logged or reversed in the system - (either manually or via the portfolio) prior to the closure date + entries may be logged (or reversed) in the system, + either manually or via the portfolio with an entry date + prior to the defined closure date

@@ -9448,7 +9456,6 @@ GET https://DomainName/api/v1/glclosures "lastUpdatedByUserId": 1, "lastUpdatedByUsername": "mifos", "comments": "closed", - "allowedOffices": [] }, { "id": 6, @@ -9475,7 +9482,6 @@ GET https://DomainName/api/v1/glclosures "lastUpdatedByUserId": 1, "lastUpdatedByUsername": "mifos", "comments": "hello", - "allowedOffices": [] } ] @@ -9523,7 +9529,6 @@ GET https://DomainName/api/v1/glclosures/{glclosureId} "lastUpdatedByUserId": 1, "lastUpdatedByUsername": "mifos", "comments": "closed", - "allowedOffices": [] } @@ -9554,14 +9559,15 @@ Request Body: { "officeId": 1, "closingDate": "06 December 2012", - "comments": "The accountants are heading for a carribean vacation" + "comments": "The accountants are heading for a carribean vacation", "locale": "en" , "dateFormat": "dd MMMM yyyy" } { - "resourceId": 1 + "officeId": 1, + "resourceId": 9 } @@ -9571,7 +9577,7 @@ Request Body:

Update an Accounting closure

-

Once an accounting closure is created, only the comment associated with it can be edited +

Once an accounting closure is created, only the comments associated with it may be edited

@@ -9588,22 +9594,11 @@ Request Body: { - "resourceId": 1 -} - -
-
- -PUT glclosures/1 -Content-Type: application/json -Request Body: -{ - "disabled": true -} - - -{ - "resourceId": 1 + "officeId": 1, + "resourceId": 1, + "changes": { + "comments": "All transactions verified by Johnny Cash" + } }
@@ -9612,10 +9607,10 @@ Request Body:  
-

Delete An accounting closure

+

Delete an accounting closure

Note: Only the latest accounting closure - associated with a branch may be closed. + associated with a branch may be deleted.

@@ -9629,6 +9624,7 @@ No Request Body: { + "officeId": 1, "resourceId": 1 } @@ -9641,7 +9637,7 @@ No Request Body:

Journal Entries

A journal entry refers to the logging of transactions against general ledger accounts. A journal - entry can consist of several line items, each of which is either a "debit" or a "credit". The total amount of the + entry may consist of several line items, each of which is either a "debit" or a "credit". The total amount of the debits must equal the total amount of the credits or the journal entry is said to be "unbalanced"

A journal entry directly changes the account balances on @@ -9707,19 +9703,13 @@ No Request Body: of transactionId and entityId is unique

- - - - - -
entryType
Either a Credit(1) or a Debit(2)
portfolioGenerated
Flag determines if an entry is generated by the portfolio (posted automatically by - the system during lifecycle of loan and saving + the system during the lifecycle of loan or saving products) or manually created by using the Create (Balanced) Journal Entries API @@ -9761,7 +9751,7 @@ No Request Body:
Flag determines if portfolio generated Journal Entries (posted automatically by the system - during lifecycle of loan and saving products) + during lifecycle of loan or saving products) shall also be returned
Set to "True" by default if not passed in explicity
@@ -9803,7 +9793,7 @@ GET https://DomainName/api/v1/journalentries?transactionId=PB37X8Y21EQUY4S "glAccountName": "Something totally else", "glAccountId": 17, "glAccountCode": "340098", - "glAccountClassification": { + "glAccountType": { "id": 3, "code": "accountType.equity", "value": "EQUITY" @@ -9837,7 +9827,7 @@ GET https://DomainName/api/v1/journalentries?transactionId=PB37X8Y21EQUY4S "glAccountName": "Something else", "glAccountId": 19, "glAccountCode": "560050", - "glAccountClassification": { + "glAccountType": { "id": 3, "code": "accountType.equity", "value": "EQUITY" @@ -9879,7 +9869,7 @@ GET https://DomainName/api/v1/journalentries?transactionId=PB37X8Y21EQUY4S amounts are equal
Compound Journal entries may have "n" debits and "m" credits where both "m" and "n" are greater than 0 - and the sum or all debits and all credits are equal + and the net sum or all debits and credits are equal

@@ -9901,9 +9891,9 @@ GET https://DomainName/api/v1/journalentries?transactionId=PB37X8Y21EQUY4S in the journal entry. Each credit entry contains the following items
glAccountId: Identifier of the general ledger - account against which credit entry shall be + account against which the credit entry shall be made
- amount: Amount of money involved in the credit + amount: Amount of money credited
comments: Optional description associated with a credit entry @@ -9918,7 +9908,7 @@ GET https://DomainName/api/v1/journalentries?transactionId=PB37X8Y21EQUY4S in the journal entry. Each debit entry contains the following items
glAccountId: Identifier of the general ledger account against which the debit entry shall be made
- amount: Amount of money involved in the debit + amount: Amount of money debited
comments: Optional description associated with a debit entry @@ -9955,7 +9945,8 @@ Request Body: { - "resourceId": C1MAE935K0IAEYA + "officeId": 1, + "transactionId": "DNEEMS2LPD0NJ9O" } @@ -9979,13 +9970,13 @@ GET https://DomainName/api/v1/journalentries/{entryId} { - "id": 22, + "id": 1, "officeId": 2, "officeName": "sub branch 1", "glAccountName": "Income from interest", "glAccountId": 14, "glAccountCode": "400001", - "glAccountClassification": { + "glAccountType": { "id": 4, "code": "accountType.income", "value": "INCOME" @@ -10024,7 +10015,8 @@ GET https://DomainName/api/v1/journalentries/{entryId}

Note: A journal entry is reversed by logging debits for all credits that constitute the Journal entry and - vice-versa + vice-versa. The transactionId of the "reversal Entry" is returned + as the methods response

Arguments
@@ -10045,7 +10037,7 @@ Content-Type: application/json { - "resourceId": C1MAE935K0IAEYA + "transactionId": "YFDYMPBVVI9TRJP" } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/closure/data/GLClosureData.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/closure/data/GLClosureData.java index f5967dbbd..7e4339c15 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/closure/data/GLClosureData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/closure/data/GLClosureData.java @@ -61,6 +61,7 @@ public class GLClosureData { this.lastUpdatedByUserId = lastUpdatedByUserId; this.lastUpdatedByUsername = lastUpdatedByUsername; this.comments = comments; + this.allowedOffices = null; } public List getAllowedOffices() { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/closure/domain/GLClosure.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/closure/domain/GLClosure.java index 2479a477e..e97bcfb5e 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/closure/domain/GLClosure.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/closure/domain/GLClosure.java @@ -23,7 +23,6 @@ import org.mifosplatform.accounting.closure.api.GLClosureJsonInputParams; import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom; import org.mifosplatform.organisation.office.domain.Office; -import org.mifosplatform.portfolio.loanaccount.guarantor.GuarantorConstants.GUARANTOR_JSON_INPUT_PARAMS; import org.mifosplatform.useradministration.domain.AppUser; @Entity @@ -65,7 +64,7 @@ public class GLClosure extends AbstractAuditableCustom { public static GLClosure fromJson(Office office, final JsonCommand command) { Date closingDate = command.DateValueOfParameterNamed(GLClosureJsonInputParams.CLOSING_DATE.getValue()); - String comments = command.stringValueOfParameterNamed(GUARANTOR_JSON_INPUT_PARAMS.COMMENT.getValue()); + String comments = command.stringValueOfParameterNamed(GLClosureJsonInputParams.COMMENTS.getValue()); return new GLClosure(office, closingDate, comments); } @@ -80,9 +79,8 @@ public class GLClosure extends AbstractAuditableCustom { if (command.isChangeInStringParameterNamed(paramName, propertyToBeUpdated)) { final String newValue = command.stringValueOfParameterNamed(paramName); actualChanges.put(paramName, newValue); - propertyToBeUpdated = newValue; // now update actual property - if (paramName.equals(GUARANTOR_JSON_INPUT_PARAMS.COMMENT.getValue())) { + if (paramName.equals(GLClosureJsonInputParams.COMMENTS.getValue())) { this.comments = newValue; } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/closure/service/GLClosureWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/closure/service/GLClosureWritePlatformServiceJpaRepositoryImpl.java index e9e123516..5cf49fc78 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/closure/service/GLClosureWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/closure/service/GLClosureWritePlatformServiceJpaRepositoryImpl.java @@ -102,7 +102,7 @@ public class GLClosureWritePlatformServiceJpaRepositoryImpl implements GLClosure } return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(glClosure.getOffice().getId()) - .withEntityId(glClosure.getId()).build(); + .withEntityId(glClosure.getId()).with(changesOnly).build(); } @Transactional diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/glaccount/domain/GLAccount.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/glaccount/domain/GLAccount.java index 0640f3800..15e37f218 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/glaccount/domain/GLAccount.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/glaccount/domain/GLAccount.java @@ -121,8 +121,6 @@ public class GLAccount extends AbstractPersistable { newValue = command.integerValueOfParameterNamed(paramName); } actualChanges.put(paramName, newValue); - propertyToBeUpdated = newValue; - // now update actual property if (paramName.equals(GLAccountJsonInputParams.TYPE.getValue())) { this.type = newValue; @@ -137,8 +135,6 @@ public class GLAccount extends AbstractPersistable { if (command.isChangeInStringParameterNamed(paramName, propertyToBeUpdated)) { final String newValue = command.stringValueOfParameterNamed(paramName); actualChanges.put(paramName, newValue); - propertyToBeUpdated = newValue; - // now update actual property if (paramName.equals(GLAccountJsonInputParams.DESCRIPTION.getValue())) { this.description = newValue; @@ -155,8 +151,6 @@ public class GLAccount extends AbstractPersistable { if (command.isChangeInLongParameterNamed(paramName, propertyToBeUpdated)) { final Long newValue = command.longValueOfParameterNamed(paramName); actualChanges.put(paramName, newValue); - propertyToBeUpdated = newValue; - // now update actual property if (paramName.equals(GLAccountJsonInputParams.PARENT_ID.getValue())) { // do nothing as this is a nested property @@ -169,8 +163,6 @@ public class GLAccount extends AbstractPersistable { if (command.isChangeInBooleanParameterNamed(paramName, propertyToBeUpdated)) { final Boolean newValue = command.booleanObjectValueOfParameterNamed(paramName); actualChanges.put(paramName, newValue); - propertyToBeUpdated = newValue; - // now update actual property if (paramName.equals(GLAccountJsonInputParams.MANUAL_ENTRIES_ALLOWED.getValue())) { this.manualEntriesAllowed = newValue; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java index 288431bc8..f50e84f00 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java @@ -1106,7 +1106,7 @@ public class Loan extends AbstractAuditableCustom { handleDisbursementTransaction(expectedDisbursedOnLocalDate); } - public Map deriveDisbursementData(final CurrencyData currencyData) { + public Map deriveDisbursementData(final CurrencyData currencyData, final List existingTransactionIds) { final Map accountingBridgeData = new LinkedHashMap(20); @@ -1119,7 +1119,9 @@ public class Loan extends AbstractAuditableCustom { final List> newLoanTransactions = new ArrayList>(); final List disbursementTransactions = findDisbursementTransactions(); for (LoanTransaction loanTransaction : disbursementTransactions) { - newLoanTransactions.add(loanTransaction.toMapData(currencyData)); + if (!existingTransactionIds.contains(loanTransaction.getId())) { + newLoanTransactions.add(loanTransaction.toMapData(currencyData)); + } } accountingBridgeData.put("newLoanTransactions", newLoanTransactions); @@ -1150,7 +1152,8 @@ public class Loan extends AbstractAuditableCustom { } public Map disburse(final AppUser currentUser, final JsonCommand command, - final LoanLifecycleStateMachine loanLifecycleStateMachine, final ApplicationCurrency currency) { + final LoanLifecycleStateMachine loanLifecycleStateMachine, final ApplicationCurrency currency, + final List existingTransactionIds) { final Map actualChanges = new LinkedHashMap(); @@ -1183,6 +1186,8 @@ public class Loan extends AbstractAuditableCustom { if (isRepaymentScheduleRegenerationRequiredForDisbursement(disbursedOn)) { regenerateRepaymentSchedule(currency); } + + existingTransactionIds.addAll(findExistingTransactionIds()); } return actualChanges; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 1f08f2e51..ff9d9f7e6 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -130,7 +130,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final ApplicationCurrency currency = this.applicationCurrencyRepository.findOneByCode(loan.getPrincpal().getCurrencyCode()); - final Map changes = loan.disburse(currentUser, command, defaultLoanLifecycleStateMachine(), currency); + /*** + * In cases where an "Undo disbursement is done and the loan is + * disbursed again, we need to ensure the old transactions are entered + * again in accounting + ***/ + final List existingTransactionIds = new ArrayList(); + final Map changes = loan.disburse(currentUser, command, defaultLoanLifecycleStateMachine(), currency, existingTransactionIds); if (!changes.isEmpty()) { this.loanRepository.save(loan); @@ -139,7 +145,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.noteRepository.save(note); } - final Map accountingBridgeData = loan.deriveDisbursementData(currency.toData()); + final Map accountingBridgeData = loan.deriveDisbursementData(currency.toData(), existingTransactionIds); journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData); } @@ -271,10 +277,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final LoanTransaction newTransactionDetail = loan.adjustExistingTransaction(transactionDate, transactionAmount, defaultLoanLifecycleStateMachine(), transactionToAdjust); if (newTransactionDetail.isGreaterThanZero(loan.getPrincpal().getCurrency())) { - this.loanTransactionRepository.save(newTransactionDetail); + this.loanTransactionRepository.saveAndFlush(newTransactionDetail); } - this.loanRepository.save(loan); + this.loanRepository.saveAndFlush(loan); final String noteText = command.stringValueOfParameterNamed("note"); if (StringUtils.isNotBlank(noteText)) {