From b2639fea2c0457772b0569c730f8193a8bff9216 Mon Sep 17 00:00:00 2001 From: Vishwas Babu AJ Date: Sat, 15 Dec 2012 00:14:41 +0530 Subject: [PATCH] minor bug fixes for accounting infrastructure adding sql files --- ...=> patch-12_accounting_tables_updates.sql} | 0 .../patches/patch-13_accounting_reports.sql | 19 ++++ .../accounting/AccountingConstants.java | 10 +++ .../accounting/api/GLAccountsApiResource.java | 6 +- .../accounting/domain/GLAccount.java | 24 +++++- .../GLAccountInvalidDeleteException.java | 2 +- .../GLAccountInvalidUpdateException.java | 29 +++++++ .../GLJournalEntryInvalidException.java | 19 ++-- .../service/GLAccountCommandValidator.java | 6 +- .../service/GLAccountReadPlatformService.java | 3 +- .../GLAccountReadPlatformServiceImpl.java | 86 +++++++++++++++---- ...WritePlatformServiceJpaRepositoryImpl.java | 16 +++- ...GLJournalEntryReadPlatformServiceImpl.java | 2 + ...WritePlatformServiceJpaRepositoryImpl.java | 28 ++++-- 14 files changed, 209 insertions(+), 41 deletions(-) rename mifosng-db/patches/{patch-05_accounting_tables_updates.sql => patch-12_accounting_tables_updates.sql} (100%) create mode 100755 mifosng-db/patches/patch-13_accounting_reports.sql create mode 100755 mifosng-provider/src/main/java/org/mifosplatform/accounting/exceptions/GLAccountInvalidUpdateException.java diff --git a/mifosng-db/patches/patch-05_accounting_tables_updates.sql b/mifosng-db/patches/patch-12_accounting_tables_updates.sql similarity index 100% rename from mifosng-db/patches/patch-05_accounting_tables_updates.sql rename to mifosng-db/patches/patch-12_accounting_tables_updates.sql diff --git a/mifosng-db/patches/patch-13_accounting_reports.sql b/mifosng-db/patches/patch-13_accounting_reports.sql new file mode 100755 index 000000000..ce238de5f --- /dev/null +++ b/mifosng-db/patches/patch-13_accounting_reports.sql @@ -0,0 +1,19 @@ +/**Balance sheet report**/ +INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_subtype`, `report_category`, `report_sql`, `description`, `core_report`, `use_report`) VALUES ('Balance Sheet', 'Pentaho', NULL, 'Accounting', NULL, 'Balance Sheet', 1, 1); +INSERT INTO `stretchy_report_parameter` (`report_id`, `parameter_id`, `report_parameter_name`) VALUES ((select max(report_id) from stretchy_report), 5, 'branch'); +INSERT INTO `stretchy_report_parameter` (`report_id`, `parameter_id`, `report_parameter_name`) VALUES ((select max(report_id) from stretchy_report), 81, 'date'); + +/**Income statement report**/ +INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_subtype`, `report_category`, `report_sql`, `description`, `core_report`, `use_report`) VALUES ('Income Statement', 'Pentaho', NULL, 'Accounting', NULL, 'Profilt and Loss Statement', 1, 1); +INSERT INTO `stretchy_report_parameter` (`report_id`, `parameter_id`, `report_parameter_name`) VALUES ((select max(report_id) from stretchy_report), 5, 'branch'); +INSERT INTO `stretchy_report_parameter` (`report_id`, `parameter_id`, `report_parameter_name`) VALUES ((select max(report_id) from stretchy_report), 80, 'fromDate'); +INSERT INTO `stretchy_report_parameter` (`report_id`, `parameter_id`, `report_parameter_name`) VALUES ((select max(report_id) from stretchy_report), 81, 'toDate'); + +/**Trial Balance report**/ +INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_subtype`, `report_category`, `report_sql`, `description`, `core_report`, `use_report`) VALUES ('Trial Balance', 'Pentaho', NULL, 'Accounting', NULL, 'Trial Balance Report', 1, 1); +INSERT INTO `stretchy_report_parameter` (`report_id`, `parameter_id`, `report_parameter_name`) VALUES ((select max(report_id) from stretchy_report), 5, 'branch'); +INSERT INTO `stretchy_report_parameter` (`report_id`, `parameter_id`, `report_parameter_name`) VALUES ((select max(report_id) from stretchy_report), 80, 'fromDate'); +INSERT INTO `stretchy_report_parameter` (`report_id`, `parameter_id`, `report_parameter_name`) VALUES ((select max(report_id) from stretchy_report), 81, 'toDate'); + + + diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/AccountingConstants.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/AccountingConstants.java index 7b69011ab..6b4522b5b 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/AccountingConstants.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/AccountingConstants.java @@ -22,4 +22,14 @@ public class AccountingConstants { } } + /** USAGES of Accounts **/ + public static enum GL_ACCOUNT_USAGE { + HEADER, DETAIL; + + @Override + public String toString() { + return name().toString(); + } + } + } 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 50073d4fc..816d2f1d9 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 @@ -66,14 +66,16 @@ public class GLAccountsApiResource { @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) public String retrieveAllAccounts(@Context final UriInfo uriInfo, @QueryParam("classification") final String classification, - @QueryParam("searchParam") final String searchParam) { + @QueryParam("searchParam") final String searchParam, @QueryParam("usage") final String usage, + @QueryParam("manualAdjustmentsAllowed") final Boolean manualTransactionsAllowed, @QueryParam("disabled") final Boolean disabled) { context.authenticatedUser().validateHasReadPermission(entityType); final Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); - final List glAccountDatas = this.glAccountReadPlatformService.retrieveAllGLAccounts(classification, searchParam); + final List glAccountDatas = this.glAccountReadPlatformService.retrieveAllGLAccounts(classification, searchParam, + usage, manualTransactionsAllowed, disabled); return this.apiJsonSerializerService.serializeGLAccountDataToJson(prettyPrint, responseParameters, glAccountDatas); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/domain/GLAccount.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/domain/GLAccount.java index 3a2029840..369d1f94a 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/domain/GLAccount.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/domain/GLAccount.java @@ -30,19 +30,15 @@ public class GLAccount extends AbstractPersistable { @JoinColumn(name = "parent_id") private List children = new LinkedList(); - @SuppressWarnings("unused") @Column(name = "name", nullable = false, length = 45) private String name; - @SuppressWarnings("unused") @Column(name = "gl_code", nullable = false, length = 100) private String glCode; - @SuppressWarnings("unused") @Column(name = "disabled", nullable = false) private boolean disabled = false; - @SuppressWarnings("unused") @Column(name = "manual_journal_entries_allowed", nullable = false) private boolean manualEntriesAllowed = true; @@ -113,4 +109,24 @@ public class GLAccount extends AbstractPersistable { return this.children; } + public boolean isDisabled() { + return this.disabled; + } + + public boolean isManualEntriesAllowed() { + return this.manualEntriesAllowed; + } + + public String getGlCode() { + return this.glCode; + } + + public void setGlCode(String glCode) { + this.glCode = glCode; + } + + public String getName() { + return this.name; + } + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/exceptions/GLAccountInvalidDeleteException.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/exceptions/GLAccountInvalidDeleteException.java index c2965e2bb..35d2f646f 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/exceptions/GLAccountInvalidDeleteException.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/exceptions/GLAccountInvalidDeleteException.java @@ -28,6 +28,6 @@ public class GLAccountInvalidDeleteException extends AbstractPlatformDomainRuleE } public GLAccountInvalidDeleteException(final GL_ACCOUNT_INVALID_DELETE_REASON reason, final Long glAccountId) { - super("error.msg.glaccount.glcode.invalid.delete", reason.errorMessage(), glAccountId); + super(reason.errorCode(), reason.errorMessage(), glAccountId); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/exceptions/GLAccountInvalidUpdateException.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/exceptions/GLAccountInvalidUpdateException.java new file mode 100755 index 000000000..d732b4f47 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/exceptions/GLAccountInvalidUpdateException.java @@ -0,0 +1,29 @@ +package org.mifosplatform.accounting.exceptions; + +import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException; + +/** + * A {@link RuntimeException} thrown when an error is encountered during + * updating a GL Account + */ +public class GLAccountInvalidUpdateException extends AbstractPlatformDomainRuleException { + + /*** Enum of reasons for invalid delete **/ + public static enum GL_ACCOUNT_INVALID_UPDATE_REASON { + TRANSANCTIONS_LOGGED; + + public String errorMessage() { + if (name().toString().equalsIgnoreCase("TRANSANCTIONS_LOGGED")) { return "This Usage of this (detail) GL Account as it already has transactions logged against it"; } + return name().toString(); + } + + public String errorCode() { + if (name().toString().equalsIgnoreCase("TRANSANCTIONS_LOGGED")) { return "error.msg.glaccount.glcode.invalid.update.transactions.logged"; } + return name().toString(); + } + } + + public GLAccountInvalidUpdateException(final GL_ACCOUNT_INVALID_UPDATE_REASON reason, final Long glAccountId) { + super(reason.errorCode(), reason.errorMessage(), glAccountId); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/exceptions/GLJournalEntryInvalidException.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/exceptions/GLJournalEntryInvalidException.java index 0743e6c30..83ca2ca8b 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/exceptions/GLJournalEntryInvalidException.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/exceptions/GLJournalEntryInvalidException.java @@ -11,7 +11,7 @@ public class GLJournalEntryInvalidException extends AbstractPlatformDomainRuleEx /*** enum of reasons for invalid Journal Entry **/ public static enum GL_JOURNAL_ENTRY_INVALID_REASON { - FUTURE_DATE, ACCOUNTING_CLOSED, NO_DEBITS_OR_CREDITS, DEBIT_CREDIT_SUM_MISMATCH, DEBIT_CREDIT_ACCOUNT_OR_AMOUNT_EMPTY; + FUTURE_DATE, ACCOUNTING_CLOSED, NO_DEBITS_OR_CREDITS, DEBIT_CREDIT_SUM_MISMATCH, DEBIT_CREDIT_ACCOUNT_OR_AMOUNT_EMPTY, GL_ACCOUNT_DISABLED, GL_ACCOUNT_MANUAL_ENTRIES_NOT_PERMITTED; public String errorMessage() { if (name().toString().equalsIgnoreCase("FUTURE_DATE")) { @@ -22,7 +22,11 @@ public class GLJournalEntryInvalidException extends AbstractPlatformDomainRuleEx return "Journal Entry must have atleast one Debit and one Credit"; } else if (name().toString().equalsIgnoreCase("DEBIT_CREDIT_SUM_MISMATCH")) { return "Sum of All Debits must equal the sum of all Credits for a Journal Entry"; - } else if (name().toString().equalsIgnoreCase("DEBIT_CREDIT_ACCOUNT_OR_AMOUNT_EMPTY")) { return "Both account and amount must be specified for all Debits and Credits"; } + } else if (name().toString().equalsIgnoreCase("DEBIT_CREDIT_ACCOUNT_OR_AMOUNT_EMPTY")) { + return "Both account and amount must be specified for all Debits and Credits"; + } else if (name().toString().equalsIgnoreCase("GL_ACCOUNT_DISABLED")) { + return "Target account has been disabled"; + } else if (name().toString().equalsIgnoreCase("GL_ACCOUNT_MANUAL_ENTRIES_NOT_PERMITTED")) { return "Target account does not allow maual adjustments"; } return name().toString(); } @@ -35,12 +39,17 @@ public class GLJournalEntryInvalidException extends AbstractPlatformDomainRuleEx return "error.msg.glJournalEntry.invalid.no.debits.or.credits"; } else if (name().toString().equalsIgnoreCase("DEBIT_CREDIT_SUM_MISMATCH")) { return "error.msg.glJournalEntry.invalid.mismatch.debits.credits"; - } else if (name().toString().equalsIgnoreCase("DEBIT_CREDIT_ACCOUNT_OR_AMOUNT_EMPTY")) { return "error.msg.glJournalEntry.invalid.empty.account.or.amount"; } + } else if (name().toString().equalsIgnoreCase("DEBIT_CREDIT_ACCOUNT_OR_AMOUNT_EMPTY")) { + return "error.msg.glJournalEntry.invalid.empty.account.or.amount"; + } else if (name().toString().equalsIgnoreCase("GL_ACCOUNT_DISABLED")) { + return "error.msg.glJournalEntry.invalid.account.disabled"; + } else if (name().toString().equalsIgnoreCase("GL_ACCOUNT_MANUAL_ENTRIES_NOT_PERMITTED")) { return "error.msg.glJournalEntry.invalid.account.manual.adjustments.not.permitted"; } return name().toString(); } } - public GLJournalEntryInvalidException(final GL_JOURNAL_ENTRY_INVALID_REASON reason, final Date date) { - super(reason.errorCode(), reason.errorMessage(), date); + public GLJournalEntryInvalidException(final GL_JOURNAL_ENTRY_INVALID_REASON reason, final Date date, final String accountName, + final String accountGLCode) { + super(reason.errorCode(), reason.errorMessage(), date, accountName, accountGLCode); } } \ 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 0324d2248..a4301db9e 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 @@ -31,7 +31,7 @@ public class GLAccountCommandValidator { baseDataValidator.reset().parameter("classification").value(command.getClassification()).notBlank().notExceedingLengthOf(45); baseDataValidator.reset().parameter("description").value(command.getDescription()).ignoreIfNull().notExceedingLengthOf(500); - + baseDataValidator.reset().parameter("manualEntriesAllowed").value(command.getManualEntriesAllowed()).notBlank(); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", @@ -55,8 +55,10 @@ public class GLAccountCommandValidator { baseDataValidator.reset().parameter("description").value(command.getDescription()).ignoreIfNull().notBlank() .notExceedingLengthOf(500); + baseDataValidator.reset().parameter("disabled").value(command.getDisabled()).ignoreIfNull(); + baseDataValidator.reset().anyOfNotNull(command.getName(), command.getGlCode(), command.getParentId(), command.getClassification(), - command.getDescription()); + command.getDescription(), command.getDisabled()); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/GLAccountReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/GLAccountReadPlatformService.java index 828b26c2a..eb450020a 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/GLAccountReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/GLAccountReadPlatformService.java @@ -6,7 +6,8 @@ import org.mifosplatform.accounting.api.data.GLAccountData; public interface GLAccountReadPlatformService { - List retrieveAllGLAccounts(String accountClassification, String searchParam); + List retrieveAllGLAccounts(String accountClassification, String searchParam, String usage, + Boolean manualTransactionsAllowed, Boolean disabled); GLAccountData retrieveGLAccountById(long glAccountId); 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 7504a1082..7b2b797f5 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 @@ -7,6 +7,7 @@ import java.util.List; import org.apache.commons.lang.StringUtils; import org.mifosplatform.accounting.AccountingConstants.GL_ACCOUNT_CLASSIFICATION; +import org.mifosplatform.accounting.AccountingConstants.GL_ACCOUNT_USAGE; import org.mifosplatform.accounting.api.data.GLAccountData; import org.mifosplatform.accounting.exceptions.GLAccountInvalidClassificationException; import org.mifosplatform.accounting.exceptions.GLAccountNotFoundException; @@ -54,7 +55,8 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe } @Override - public List retrieveAllGLAccounts(String accountClassification, String searchParam) { + public List retrieveAllGLAccounts(String accountClassification, String searchParam, String usage, + Boolean manualTransactionsAllowed, Boolean disabled) { if (StringUtils.isNotBlank(accountClassification)) { if (!checkValidGLAccountClassification(accountClassification)) { throw new GLAccountInvalidClassificationException( accountClassification); } @@ -64,25 +66,71 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe String sql = "select " + rm.schema(); Object[] paramaterArray = new Object[3]; int arrayPos = 0; - if (StringUtils.isNotBlank(accountClassification) && searchParam != null) { - sql += " where classification like ? and ( name like %?% or glCode like %?% )"; - paramaterArray[arrayPos] = accountClassification; - arrayPos = arrayPos++; - paramaterArray[arrayPos] = searchParam; - arrayPos = arrayPos++; - paramaterArray[arrayPos] = searchParam; - arrayPos = arrayPos++; - } else if (StringUtils.isNotBlank(accountClassification)) { - sql += " where classification like ?"; - paramaterArray[arrayPos] = accountClassification; - arrayPos++; - } else if (searchParam != null) { - sql += " where ( name like %?% or glCode like %?% )"; - paramaterArray[arrayPos] = searchParam; - arrayPos++; - paramaterArray[arrayPos] = searchParam; - arrayPos++; + boolean filtersPresent = false; + if (StringUtils.isNotBlank(accountClassification) || StringUtils.isNotBlank(searchParam) || StringUtils.isNotBlank(usage) + || (manualTransactionsAllowed != null) || (disabled != null)) { + filtersPresent = true; + sql += " where"; } + + if (filtersPresent) { + boolean firstWhereConditionAdded = false; + if (StringUtils.isNotBlank(accountClassification)) { + sql += " classification like ?"; + paramaterArray[arrayPos] = accountClassification; + arrayPos = arrayPos + 1; + firstWhereConditionAdded = true; + } + if (StringUtils.isNotBlank(searchParam)) { + if (firstWhereConditionAdded) { + sql += " and "; + } + sql += " ( name like %?% or gl_code like %?% )"; + paramaterArray[arrayPos] = searchParam; + arrayPos = arrayPos + 1; + paramaterArray[arrayPos] = searchParam; + arrayPos = arrayPos + 1; + firstWhereConditionAdded = true; + } + if (StringUtils.isNotBlank(usage)) { + if (firstWhereConditionAdded) { + sql += " and "; + } + if (usage.equalsIgnoreCase(GL_ACCOUNT_USAGE.HEADER.toString())) { + sql += " header_account = 1 "; + } else if (usage.equalsIgnoreCase(GL_ACCOUNT_USAGE.DETAIL.toString())) { + sql += " header_account = 0 "; + } else { + + } + firstWhereConditionAdded = true; + } + if (manualTransactionsAllowed != null) { + if (firstWhereConditionAdded) { + sql += " and "; + } + + if (manualTransactionsAllowed) { + sql += " manual_journal_entries_allowed = 1"; + } else { + sql += " manual_journal_entries_allowed = 0"; + } + firstWhereConditionAdded = true; + } + if (disabled != null) { + if (firstWhereConditionAdded) { + sql += " and "; + } + + if (disabled) { + sql += " disabled = 1"; + } else { + sql += " disabled = 0"; + } + firstWhereConditionAdded = true; + } + } + sql = sql + " order by glCode"; Object[] finalObjectArray = Arrays.copyOf(paramaterArray, arrayPos); return this.jdbcTemplate.query(sql, rm, finalObjectArray); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLAccountWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLAccountWritePlatformServiceJpaRepositoryImpl.java index 8fc31c8d3..77d3f6d6f 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLAccountWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLAccountWritePlatformServiceJpaRepositoryImpl.java @@ -13,7 +13,9 @@ import org.mifosplatform.accounting.exceptions.GLAccountDuplicateException; import org.mifosplatform.accounting.exceptions.GLAccountInvalidClassificationException; import org.mifosplatform.accounting.exceptions.GLAccountInvalidDeleteException; import org.mifosplatform.accounting.exceptions.GLAccountInvalidDeleteException.GL_ACCOUNT_INVALID_DELETE_REASON; +import org.mifosplatform.accounting.exceptions.GLAccountInvalidUpdateException.GL_ACCOUNT_INVALID_UPDATE_REASON; import org.mifosplatform.accounting.exceptions.GLAccountInvalidParentException; +import org.mifosplatform.accounting.exceptions.GLAccountInvalidUpdateException; import org.mifosplatform.accounting.exceptions.GLAccountNotFoundException; import org.mifosplatform.accounting.service.GLAccountCommandValidator; import org.mifosplatform.accounting.service.GLAccountWritePlatformService; @@ -91,6 +93,18 @@ public class GLAccountWritePlatformServiceJpaRepositoryImpl implements GLAccount command.getClassification()); } } + /** + * a detail account cannot be changed to a header account if + * transactions are already logged against it + **/ + if (command.isHeaderAccountFlagChanged()) { + if (command.getHeaderAccount() == true) { + List journalEntriesForAccount = glJournalEntryRepository.findFirstJournalEntryForAccount(glAccountId); + if (journalEntriesForAccount.size() > 0) { throw new GLAccountInvalidUpdateException( + GL_ACCOUNT_INVALID_UPDATE_REASON.TRANSANCTIONS_LOGGED, glAccountId); } + } + } + glAccount.update(command, parentGLAccount); this.glAccountRepository.saveAndFlush(glAccount); @@ -109,7 +123,7 @@ public class GLAccountWritePlatformServiceJpaRepositoryImpl implements GLAccount if (glAccount.isHeaderAccount() && glAccount.getChildren().size() > 0) { throw new GLAccountInvalidDeleteException( GL_ACCOUNT_INVALID_DELETE_REASON.HAS_CHILDREN, glAccountId); } - // TODO: does this account have transactions logged against it + // does this account have transactions logged against it List journalEntriesForAccount = glJournalEntryRepository.findFirstJournalEntryForAccount(glAccountId); if (journalEntriesForAccount.size() > 0) { throw new GLAccountInvalidDeleteException( GL_ACCOUNT_INVALID_DELETE_REASON.TRANSANCTIONS_LOGGED, glAccountId); } 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 836fa1435..80c4736d9 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 @@ -129,6 +129,8 @@ public class GLJournalEntryReadPlatformServiceImpl implements GLJournalEntryRead } } + sql += " order by journalEntry.entry_date"; + 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/GLJournalEntryWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLJournalEntryWritePlatformServiceJpaRepositoryImpl.java index 6f0591769..27d1cedc0 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLJournalEntryWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/service/impl/GLJournalEntryWritePlatformServiceJpaRepositoryImpl.java @@ -115,6 +115,9 @@ public class GLJournalEntryWritePlatformServiceJpaRepositoryImpl implements GLJo return reversalTransactionId; } + /** + * @param command + */ private void validateBusinessRulesForJournalEntries(GLJournalEntryCommand command) { /** check if date of Journal entry is valid ***/ @@ -122,12 +125,13 @@ public class GLJournalEntryWritePlatformServiceJpaRepositoryImpl implements GLJo Date entryDate = entryLocalDate.toDateMidnight().toDate(); // shouldn't be in the future Date todaysDate = new Date(); - if (entryDate.after(todaysDate)) { throw new GLJournalEntryInvalidException(GL_JOURNAL_ENTRY_INVALID_REASON.FUTURE_DATE, entryDate); } + if (entryDate.after(todaysDate)) { throw new GLJournalEntryInvalidException(GL_JOURNAL_ENTRY_INVALID_REASON.FUTURE_DATE, entryDate, + null, null); } // shouldn't be before an accounting closure GLClosure latestGLClosure = glClosureRepository.getLatestGLClosureByBranch(command.getOfficeId()); if (latestGLClosure != null) { if (latestGLClosure.getClosingDate().after(entryDate)) { throw new GLJournalEntryInvalidException( - GL_JOURNAL_ENTRY_INVALID_REASON.ACCOUNTING_CLOSED, latestGLClosure.getClosingDate()); } + GL_JOURNAL_ENTRY_INVALID_REASON.ACCOUNTING_CLOSED, latestGLClosure.getClosingDate(), null, null); } } /*** check if credits and debits are valid **/ SingleDebitOrCreditEntryCommand[] credits = command.getCredits(); @@ -135,23 +139,23 @@ public class GLJournalEntryWritePlatformServiceJpaRepositoryImpl implements GLJo // atleast one debit or credit must be present if ((credits == null || credits.length <= 0) || (debits == null || debits.length <= 0)) { throw new GLJournalEntryInvalidException( - GL_JOURNAL_ENTRY_INVALID_REASON.NO_DEBITS_OR_CREDITS, null); } + GL_JOURNAL_ENTRY_INVALID_REASON.NO_DEBITS_OR_CREDITS, null, null, null); } // sum of all debits must be = sum of all credits BigDecimal creditsSum = BigDecimal.ZERO; BigDecimal debitsSum = BigDecimal.ZERO; for (SingleDebitOrCreditEntryCommand creditEntryCommand : credits) { if (creditEntryCommand.getAmount() == null || creditEntryCommand.getGlAccountId() == null) { throw new GLJournalEntryInvalidException( - GL_JOURNAL_ENTRY_INVALID_REASON.DEBIT_CREDIT_ACCOUNT_OR_AMOUNT_EMPTY, null); } + GL_JOURNAL_ENTRY_INVALID_REASON.DEBIT_CREDIT_ACCOUNT_OR_AMOUNT_EMPTY, null, null, null); } creditsSum = creditsSum.add(creditEntryCommand.getAmount()); } for (SingleDebitOrCreditEntryCommand debitEntryCommand : debits) { if (debitEntryCommand.getAmount() == null || debitEntryCommand.getGlAccountId() == null) { throw new GLJournalEntryInvalidException( - GL_JOURNAL_ENTRY_INVALID_REASON.DEBIT_CREDIT_ACCOUNT_OR_AMOUNT_EMPTY, null); } + GL_JOURNAL_ENTRY_INVALID_REASON.DEBIT_CREDIT_ACCOUNT_OR_AMOUNT_EMPTY, null, null, null); } debitsSum = debitsSum.add(debitEntryCommand.getAmount()); } if (creditsSum.compareTo(debitsSum) != 0) { throw new GLJournalEntryInvalidException( - GL_JOURNAL_ENTRY_INVALID_REASON.DEBIT_CREDIT_SUM_MISMATCH, null); } + GL_JOURNAL_ENTRY_INVALID_REASON.DEBIT_CREDIT_SUM_MISMATCH, null, null, null); } } /** @@ -166,6 +170,18 @@ public class GLJournalEntryWritePlatformServiceJpaRepositoryImpl implements GLJo for (SingleDebitOrCreditEntryCommand singleDebitOrCreditEntryCommand : singleDebitOrCreditEntryCommands) { GLAccount glAccount = glAccountRepository.findOne(singleDebitOrCreditEntryCommand.getGlAccountId()); if (glAccount == null) { throw new GLAccountNotFoundException(singleDebitOrCreditEntryCommand.getGlAccountId()); } + + /*** + * validate that the account allows manual adjustments and is not + * disabled + **/ + if (glAccount.isDisabled()) { + throw new GLJournalEntryInvalidException(GL_JOURNAL_ENTRY_INVALID_REASON.GL_ACCOUNT_DISABLED, null, glAccount.getName(), + glAccount.getGlCode()); + } else if (!glAccount.isManualEntriesAllowed()) { throw new GLJournalEntryInvalidException( + GL_JOURNAL_ENTRY_INVALID_REASON.GL_ACCOUNT_MANUAL_ENTRIES_NOT_PERMITTED, null, glAccount.getName(), + glAccount.getGlCode()); } + String comments = command.getComments(); if (!StringUtils.isBlank(singleDebitOrCreditEntryCommand.getComments())) { comments = singleDebitOrCreditEntryCommand.getComments();