SQL Retrievals for Hierarchical ChartofAccounts

Fixing Naming Convention for COA options

Tag ID for GLAccounts
This commit is contained in:
goutham-M
2013-05-08 20:15:06 +05:30
parent 0d18ddc034
commit 8b4de075a2
13 changed files with 216 additions and 25 deletions
@@ -0,0 +1 @@
ALTER TABLE `acc_gl_account` ADD COLUMN `hierarchy` varchar(50) AFTER `parent_id`;
@@ -0,0 +1,5 @@
ALTER TABLE `acc_gl_account`
ADD COLUMN `tag_id` INT(11) NULL DEFAULT NULL AFTER `classification_enum`,
ADD INDEX `FKGLACC000000002` (`tag_id`),
ADD CONSTRAINT `FKGLACC000000002` FOREIGN KEY (`tag_id`) REFERENCES `m_code_value` (`id`);
INSERT into m_code(`code_name`,`is_system_defined`) values ('AssetAccountTags',1),('LiabilityAccountTags',1),('EquityAccountTags',1),('IncomeAccountTags',1),('ExpenseAccountTags',1);
@@ -102,4 +102,10 @@ public class AccountingConstants {
} }
} }
public static final String ASSESTS_TAG_OPTION_CODE_NAME = "AssetAccountTags";
public static final String LIABILITIES_TAG_OPTION_CODE_NAME = "LiabilityAccountTags";
public static final String EQUITY_TAG_OPTION_CODE_NAME = "EquityAccountTags";
public static final String INCOME_TAG_OPTION_CODE_NAME = "IncomeAccountTags";
public static final String EXPENSES_TAG_OPTION_CODE_NAME = "ExpenseAccountTags";
} }
@@ -13,7 +13,7 @@ import java.util.Set;
***/ ***/
public enum GLAccountJsonInputParams { public enum GLAccountJsonInputParams {
ID("id"), NAME("name"), PARENT_ID("parentId"), GL_CODE("glCode"), DISABLED("disabled"), MANUAL_ENTRIES_ALLOWED("manualEntriesAllowed"), TYPE( ID("id"), NAME("name"), PARENT_ID("parentId"), GL_CODE("glCode"), DISABLED("disabled"), MANUAL_ENTRIES_ALLOWED("manualEntriesAllowed"), TYPE(
"type"), USAGE("usage"), DESCRIPTION("description"); "type"), USAGE("usage"), DESCRIPTION("description"), TAGID("tagId");
private final String value; private final String value;
@@ -6,6 +6,7 @@
package org.mifosplatform.accounting.glaccount.api; package org.mifosplatform.accounting.glaccount.api;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@@ -23,12 +24,16 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.UriInfo;
import org.mifosplatform.accounting.common.AccountingConstants;
import org.mifosplatform.accounting.common.AccountingDropdownReadPlatformService; import org.mifosplatform.accounting.common.AccountingDropdownReadPlatformService;
import org.mifosplatform.accounting.glaccount.data.GLAccountData; import org.mifosplatform.accounting.glaccount.data.GLAccountData;
import org.mifosplatform.accounting.glaccount.domain.GLAccountType;
import org.mifosplatform.accounting.glaccount.service.GLAccountReadPlatformService; import org.mifosplatform.accounting.glaccount.service.GLAccountReadPlatformService;
import org.mifosplatform.commands.domain.CommandWrapper; import org.mifosplatform.commands.domain.CommandWrapper;
import org.mifosplatform.commands.service.CommandWrapperBuilder; import org.mifosplatform.commands.service.CommandWrapperBuilder;
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService; import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.infrastructure.codes.service.CodeValueReadPlatformService;
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper; import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.EnumOptionData; import org.mifosplatform.infrastructure.core.data.EnumOptionData;
@@ -45,7 +50,9 @@ import org.springframework.stereotype.Component;
public class GLAccountsApiResource { public class GLAccountsApiResource {
private static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "name", "parentId", "glCode", private static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "name", "parentId", "glCode",
"disabled", "manualEntriesAllowed", "type", "usage", "description")); "disabled", "manualEntriesAllowed", "type", "usage", "description", "assetHeaderAccountOptions", "liabilityHeaderAccountOptions",
"equityHeaderAccountOptions", "incomeHeaderAccountOptions", "expenseHeaderAccountOptions", "nameDecorated", "tagId",
"allowedAssetsTagOptions", "allowedLiabilitiesTagOptions", "allowedEquityTagOptions", "allowedIncomeTagOptions", "allowedExpensesTagOptions"));
private final String resourceNameForPermission = "GLACCOUNT"; private final String resourceNameForPermission = "GLACCOUNT";
@@ -55,18 +62,20 @@ public class GLAccountsApiResource {
private final ApiRequestParameterHelper apiRequestParameterHelper; private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PlatformSecurityContext context; private final PlatformSecurityContext context;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final CodeValueReadPlatformService codeValueReadPlatformService;
@Autowired @Autowired
public GLAccountsApiResource(final PlatformSecurityContext context, final GLAccountReadPlatformService glAccountReadPlatformService, public GLAccountsApiResource(final PlatformSecurityContext context, final GLAccountReadPlatformService glAccountReadPlatformService,
final DefaultToApiJsonSerializer<GLAccountData> toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper, final DefaultToApiJsonSerializer<GLAccountData> toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
final AccountingDropdownReadPlatformService dropdownReadPlatformService) { final AccountingDropdownReadPlatformService dropdownReadPlatformService, final CodeValueReadPlatformService codeValueReadPlatformService) {
this.context = context; this.context = context;
this.apiRequestParameterHelper = apiRequestParameterHelper; this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
this.apiJsonSerializerService = toApiJsonSerializer; this.apiJsonSerializerService = toApiJsonSerializer;
this.glAccountReadPlatformService = glAccountReadPlatformService; this.glAccountReadPlatformService = glAccountReadPlatformService;
this.dropdownReadPlatformService = dropdownReadPlatformService; this.dropdownReadPlatformService = dropdownReadPlatformService;
this.codeValueReadPlatformService = codeValueReadPlatformService;
} }
@GET @GET
@@ -158,6 +167,27 @@ public class GLAccountsApiResource {
private GLAccountData handleTemplate(final GLAccountData glAccountData) { private GLAccountData handleTemplate(final GLAccountData glAccountData) {
final List<EnumOptionData> accountTypeOptions = this.dropdownReadPlatformService.retrieveGLAccountTypeOptions(); final List<EnumOptionData> accountTypeOptions = this.dropdownReadPlatformService.retrieveGLAccountTypeOptions();
final List<EnumOptionData> usageOptions = this.dropdownReadPlatformService.retrieveGLAccountUsageOptions(); final List<EnumOptionData> usageOptions = this.dropdownReadPlatformService.retrieveGLAccountUsageOptions();
return new GLAccountData(glAccountData, accountTypeOptions, usageOptions); final List<GLAccountData> assetHeaderAccountOptions = defaultIfEmpty(this.glAccountReadPlatformService.retrieveAllEnabledHeaderGLAccounts(GLAccountType.ASSET));
final List<GLAccountData> liabilityHeaderAccountOptions = defaultIfEmpty(this.glAccountReadPlatformService.retrieveAllEnabledHeaderGLAccounts(GLAccountType.LIABILITY));
final List<GLAccountData> equityHeaderAccountOptions = defaultIfEmpty(this.glAccountReadPlatformService.retrieveAllEnabledHeaderGLAccounts(GLAccountType.EQUITY));
final List<GLAccountData> incomeHeaderAccountOptions = defaultIfEmpty(this.glAccountReadPlatformService.retrieveAllEnabledHeaderGLAccounts(GLAccountType.INCOME));
final List<GLAccountData> expenseHeaderAccountOptions = defaultIfEmpty(this.glAccountReadPlatformService.retrieveAllEnabledHeaderGLAccounts(GLAccountType.EXPENSE));
final Collection<CodeValueData> allowedAssetsTagOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode(AccountingConstants.ASSESTS_TAG_OPTION_CODE_NAME);
final Collection<CodeValueData> allowedLiabilitiesTagOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode(AccountingConstants.LIABILITIES_TAG_OPTION_CODE_NAME);
final Collection<CodeValueData> allowedEquityTagOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode(AccountingConstants.EQUITY_TAG_OPTION_CODE_NAME);
final Collection<CodeValueData> allowedIncomeTagOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode(AccountingConstants.INCOME_TAG_OPTION_CODE_NAME);
final Collection<CodeValueData> allowedExpensesTagOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode(AccountingConstants.EXPENSES_TAG_OPTION_CODE_NAME);
return new GLAccountData(glAccountData, accountTypeOptions, usageOptions, assetHeaderAccountOptions, liabilityHeaderAccountOptions,
equityHeaderAccountOptions, incomeHeaderAccountOptions, expenseHeaderAccountOptions, allowedAssetsTagOptions,
allowedLiabilitiesTagOptions, allowedEquityTagOptions, allowedIncomeTagOptions, allowedExpensesTagOptions);
}
private List<GLAccountData> defaultIfEmpty(final List<GLAccountData> list) {
List<GLAccountData> returnList = null;
if (list != null && !list.isEmpty()) {
returnList = list;
}
return returnList;
} }
} }
@@ -30,9 +30,10 @@ public class GLAccountCommand {
private final Integer usage; private final Integer usage;
private final Integer type; private final Integer type;
private final String description; private final String description;
private final Long tagId;
public GLAccountCommand(final Long id, final String name, final Long parentId, final String glCode, final Boolean disabled, public GLAccountCommand(final Long id, final String name, final Long parentId, final String glCode, final Boolean disabled,
final Boolean manualEntriesAllowed, final Integer type, final Integer usage, final String description) { final Boolean manualEntriesAllowed, final Integer type, final Integer usage, final String description, final Long tagId) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.parentId = parentId; this.parentId = parentId;
@@ -42,6 +43,7 @@ public class GLAccountCommand {
this.type = type; this.type = type;
this.usage = usage; this.usage = usage;
this.description = description; this.description = description;
this.tagId = tagId;
} }
public void validateForCreate() { public void validateForCreate() {
@@ -70,6 +72,8 @@ public class GLAccountCommand {
baseDataValidator.reset().parameter(GLAccountJsonInputParams.MANUAL_ENTRIES_ALLOWED.getValue()).value(this.manualEntriesAllowed) baseDataValidator.reset().parameter(GLAccountJsonInputParams.MANUAL_ENTRIES_ALLOWED.getValue()).value(this.manualEntriesAllowed)
.notBlank(); .notBlank();
baseDataValidator.reset().parameter(GLAccountJsonInputParams.TAGID.getValue()).value(this.tagId).ignoreIfNull().longGreaterThanZero();
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); } "Validation errors exist.", dataValidationErrors); }
} }
@@ -102,6 +106,7 @@ public class GLAccountCommand {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); } "Validation errors exist.", dataValidationErrors); }
baseDataValidator.reset().parameter(GLAccountJsonInputParams.TAGID.getValue()).value(this.tagId).ignoreIfNull().longGreaterThanZero();
} }
public boolean isHeaderAccount() { public boolean isHeaderAccount() {
@@ -5,11 +5,13 @@
*/ */
package org.mifosplatform.accounting.glaccount.data; package org.mifosplatform.accounting.glaccount.data;
import java.util.Collection;
import java.util.List; import java.util.List;
import org.mifosplatform.accounting.common.AccountingEnumerations; import org.mifosplatform.accounting.common.AccountingEnumerations;
import org.mifosplatform.accounting.glaccount.domain.GLAccountType; import org.mifosplatform.accounting.glaccount.domain.GLAccountType;
import org.mifosplatform.accounting.glaccount.domain.GLAccountUsage; import org.mifosplatform.accounting.glaccount.domain.GLAccountUsage;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData; import org.mifosplatform.infrastructure.core.data.EnumOptionData;
/** /**
@@ -29,13 +31,26 @@ public class GLAccountData {
private final EnumOptionData type; private final EnumOptionData type;
private final EnumOptionData usage; private final EnumOptionData usage;
private final String description; private final String description;
private final String nameDecorated;
private final CodeValueData tagId;
// templates // templates
final List<EnumOptionData> accountTypeOptions; final List<EnumOptionData> accountTypeOptions;
final List<EnumOptionData> usageOptions; final List<EnumOptionData> usageOptions;
final List<GLAccountData> assetHeaderAccountOptions;
final List<GLAccountData> liabilityHeaderAccountOptions;
final List<GLAccountData> equityHeaderAccountOptions;
final List<GLAccountData> incomeHeaderAccountOptions;
final List<GLAccountData> expenseHeaderAccountOptions;
final Collection<CodeValueData> allowedAssetsTagOptions;
final Collection<CodeValueData> allowedLiabilitiesTagOptions;
final Collection<CodeValueData> allowedEquityTagOptions;
final Collection<CodeValueData> allowedIncomeTagOptions;
final Collection<CodeValueData> allowedExpensesTagOptions;
public GLAccountData(final Long id, final String name, final Long parentId, final String glCode, final boolean disabled, public GLAccountData(final Long id, final String name, final Long parentId, final String glCode, final boolean disabled,
final boolean manualEntriesAllowed, final EnumOptionData type, final EnumOptionData usage, final String description) { final boolean manualEntriesAllowed, final EnumOptionData type, final EnumOptionData usage, final String description,
final String nameDecorated, final CodeValueData tagId) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.parentId = parentId; this.parentId = parentId;
@@ -45,12 +60,29 @@ public class GLAccountData {
this.type = type; this.type = type;
this.usage = usage; this.usage = usage;
this.description = description; this.description = description;
this.nameDecorated = nameDecorated;
this.tagId = tagId;
this.accountTypeOptions = null; this.accountTypeOptions = null;
this.usageOptions = null; this.usageOptions = null;
this.assetHeaderAccountOptions = null;
this.liabilityHeaderAccountOptions = null;
this.equityHeaderAccountOptions = null;
this.incomeHeaderAccountOptions = null;
this.expenseHeaderAccountOptions = null;
this.allowedAssetsTagOptions = null;
this.allowedLiabilitiesTagOptions = null;
this.allowedEquityTagOptions=null;
this.allowedIncomeTagOptions=null;
this.allowedExpensesTagOptions=null;
} }
public GLAccountData(final GLAccountData accountData, final List<EnumOptionData> accountTypeOptions, public GLAccountData(final GLAccountData accountData, final List<EnumOptionData> accountTypeOptions,
final List<EnumOptionData> usageOptions) { final List<EnumOptionData> usageOptions, final List<GLAccountData> assetHeaderAccountOptions,
final List<GLAccountData> liabilityHeaderAccountOptions, final List<GLAccountData> equityHeaderAccountOptions,
final List<GLAccountData> incomeHeaderAccountOptions, final List<GLAccountData> expenseHeaderAccountOptions,
final Collection<CodeValueData> allowedAssetsTagOptions, final Collection<CodeValueData> allowedLiabilitiesTagOptions,
final Collection<CodeValueData> allowedEquityTagOptions, final Collection<CodeValueData> allowedIncomeTagOptions,
final Collection<CodeValueData> allowedExpensesTagOptions) {
this.id = accountData.id; this.id = accountData.id;
this.name = accountData.name; this.name = accountData.name;
this.parentId = accountData.parentId; this.parentId = accountData.parentId;
@@ -60,8 +92,20 @@ public class GLAccountData {
this.type = accountData.type; this.type = accountData.type;
this.usage = accountData.usage; this.usage = accountData.usage;
this.description = accountData.description; this.description = accountData.description;
this.nameDecorated = accountData.nameDecorated;
this.tagId = accountData.tagId;
this.accountTypeOptions = accountTypeOptions; this.accountTypeOptions = accountTypeOptions;
this.usageOptions = usageOptions; this.usageOptions = usageOptions;
this.assetHeaderAccountOptions = assetHeaderAccountOptions;
this.liabilityHeaderAccountOptions = liabilityHeaderAccountOptions;
this.equityHeaderAccountOptions = equityHeaderAccountOptions;
this.incomeHeaderAccountOptions = incomeHeaderAccountOptions;
this.expenseHeaderAccountOptions = expenseHeaderAccountOptions;
this.allowedAssetsTagOptions = allowedAssetsTagOptions;
this.allowedLiabilitiesTagOptions = allowedLiabilitiesTagOptions;
this.allowedEquityTagOptions = allowedEquityTagOptions;
this.allowedIncomeTagOptions = allowedIncomeTagOptions;
this.allowedExpensesTagOptions = allowedExpensesTagOptions;
} }
public static GLAccountData sensibleDefaultsForNewGLAccountCreation() { public static GLAccountData sensibleDefaultsForNewGLAccountCreation() {
@@ -74,6 +118,9 @@ public class GLAccountData {
final EnumOptionData type = AccountingEnumerations.gLAccountType(GLAccountType.ASSET); final EnumOptionData type = AccountingEnumerations.gLAccountType(GLAccountType.ASSET);
final EnumOptionData usage = AccountingEnumerations.gLAccountUsage(GLAccountUsage.DETAIL); final EnumOptionData usage = AccountingEnumerations.gLAccountUsage(GLAccountUsage.DETAIL);
final String description = null; final String description = null;
return new GLAccountData(id, name, parentId, glCode, disabled, manualEntriesAllowed, type, usage, description); final String nameDecorated = null;
final CodeValueData tagId = null;
return new GLAccountData(id, name, parentId, glCode, disabled, manualEntriesAllowed, type, usage, description, nameDecorated, tagId);
} }
} }
@@ -22,6 +22,7 @@ import javax.persistence.UniqueConstraint;
import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.mifosplatform.accounting.glaccount.api.GLAccountJsonInputParams; import org.mifosplatform.accounting.glaccount.api.GLAccountJsonInputParams;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.springframework.data.jpa.domain.AbstractPersistable; import org.springframework.data.jpa.domain.AbstractPersistable;
@@ -29,11 +30,13 @@ import org.springframework.data.jpa.domain.AbstractPersistable;
@Table(name = "acc_gl_account", uniqueConstraints = { @UniqueConstraint(columnNames = { "gl_code" }, name = "acc_gl_code") }) @Table(name = "acc_gl_account", uniqueConstraints = { @UniqueConstraint(columnNames = { "gl_code" }, name = "acc_gl_code") })
public class GLAccount extends AbstractPersistable<Long> { public class GLAccount extends AbstractPersistable<Long> {
@SuppressWarnings("unused") @ManyToOne(fetch = FetchType.LAZY)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id") @JoinColumn(name = "parent_id")
private GLAccount parent; private GLAccount parent;
@Column(name = "hierarchy", nullable = true, length = 50)
private String hierarchy;
@OneToMany(fetch = FetchType.LAZY) @OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id") @JoinColumn(name = "parent_id")
private final List<GLAccount> children = new LinkedList<GLAccount>(); private final List<GLAccount> children = new LinkedList<GLAccount>();
@@ -59,12 +62,17 @@ public class GLAccount extends AbstractPersistable<Long> {
@Column(name = "description", nullable = true, length = 500) @Column(name = "description", nullable = true, length = 500)
private String description; private String description;
@SuppressWarnings("unused")
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "tag_id")
private CodeValue tagId;
protected GLAccount() { protected GLAccount() {
// //
} }
private GLAccount(final GLAccount parent, final String name, final String glCode, final boolean disabled, private GLAccount(final GLAccount parent, final String name, final String glCode, final boolean disabled,
final boolean manualEntriesAllowed, final Integer type, final Integer usage, final String description) { final boolean manualEntriesAllowed, final Integer type, final Integer usage, final String description, final CodeValue tagId) {
this.name = StringUtils.defaultIfEmpty(name, null); this.name = StringUtils.defaultIfEmpty(name, null);
this.glCode = StringUtils.defaultIfEmpty(glCode, null); this.glCode = StringUtils.defaultIfEmpty(glCode, null);
this.disabled = BooleanUtils.toBooleanDefaultIfNull(disabled, false); this.disabled = BooleanUtils.toBooleanDefaultIfNull(disabled, false);
@@ -73,9 +81,10 @@ public class GLAccount extends AbstractPersistable<Long> {
this.type = type; this.type = type;
this.description = StringUtils.defaultIfEmpty(description, null); this.description = StringUtils.defaultIfEmpty(description, null);
this.parent = parent; this.parent = parent;
this.tagId = tagId;
} }
public static GLAccount fromJson(final GLAccount parent, final JsonCommand command) { public static GLAccount fromJson(final GLAccount parent, final JsonCommand command, CodeValue glAccountTagType) {
final String name = command.stringValueOfParameterNamed(GLAccountJsonInputParams.NAME.getValue()); final String name = command.stringValueOfParameterNamed(GLAccountJsonInputParams.NAME.getValue());
final String glCode = command.stringValueOfParameterNamed(GLAccountJsonInputParams.GL_CODE.getValue()); final String glCode = command.stringValueOfParameterNamed(GLAccountJsonInputParams.GL_CODE.getValue());
final boolean disabled = command.booleanPrimitiveValueOfParameterNamed(GLAccountJsonInputParams.DISABLED.getValue()); final boolean disabled = command.booleanPrimitiveValueOfParameterNamed(GLAccountJsonInputParams.DISABLED.getValue());
@@ -84,7 +93,7 @@ public class GLAccount extends AbstractPersistable<Long> {
final Integer usage = command.integerValueSansLocaleOfParameterNamed(GLAccountJsonInputParams.USAGE.getValue()); final Integer usage = command.integerValueSansLocaleOfParameterNamed(GLAccountJsonInputParams.USAGE.getValue());
final Integer type = command.integerValueSansLocaleOfParameterNamed(GLAccountJsonInputParams.TYPE.getValue()); final Integer type = command.integerValueSansLocaleOfParameterNamed(GLAccountJsonInputParams.TYPE.getValue());
final String description = command.stringValueOfParameterNamed(GLAccountJsonInputParams.DESCRIPTION.getValue()); final String description = command.stringValueOfParameterNamed(GLAccountJsonInputParams.DESCRIPTION.getValue());
return new GLAccount(parent, name, glCode, disabled, manualEntriesAllowed, type, usage, description); return new GLAccount(parent, name, glCode, disabled, manualEntriesAllowed, type, usage, description, glAccountTagType);
} }
public Map<String, Object> update(final JsonCommand command) { public Map<String, Object> update(final JsonCommand command) {
@@ -199,4 +208,20 @@ public class GLAccount extends AbstractPersistable<Long> {
return this.type; return this.type;
} }
public void generateHierarchy() {
if (parent != null) {
this.hierarchy = this.parent.hierarchyOf(this.getId());
} else {
this.hierarchy = ".";
}
}
private String hierarchyOf(final Long id) {
return this.hierarchy + id.toString() + ".";
}
public boolean isDetailAccount() {
return GLAccountUsage.DETAIL.getValue().equals(this.usage);
}
} }
@@ -66,4 +66,24 @@ public enum GLAccountType {
return name().toString(); return name().toString();
} }
public boolean isAssetType() {
return this.value.equals(GLAccountType.ASSET.getValue());
}
public boolean isLiabilityType() {
return this.value.equals(GLAccountType.LIABILITY.getValue());
}
public boolean isEquityType() {
return this.value.equals(GLAccountType.EQUITY.getValue());
}
public boolean isIncomeType() {
return this.value.equals(GLAccountType.INCOME.getValue());
}
public boolean isExpenseType() {
return this.value.equals(GLAccountType.EXPENSE.getValue());
}
} }
@@ -57,7 +57,8 @@ public final class GLAccountCommandFromApiJsonDeserializer extends AbstractFromA
final Integer type = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(GLAccountJsonInputParams.TYPE.getValue(), element); final Integer type = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(GLAccountJsonInputParams.TYPE.getValue(), element);
final Integer usage = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(GLAccountJsonInputParams.USAGE.getValue(), element); final Integer usage = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(GLAccountJsonInputParams.USAGE.getValue(), element);
final String description = this.fromApiJsonHelper.extractStringNamed(GLAccountJsonInputParams.DESCRIPTION.getValue(), element); final String description = this.fromApiJsonHelper.extractStringNamed(GLAccountJsonInputParams.DESCRIPTION.getValue(), element);
final Long tagId = this.fromApiJsonHelper.extractLongNamed(GLAccountJsonInputParams.TAGID.getValue(), element);
return new GLAccountCommand(id, name, parentId, glCode, disabled, manualEntriesAllowed, type, usage, description); return new GLAccountCommand(id, name, parentId, glCode, disabled, manualEntriesAllowed, type, usage, description, tagId);
} }
} }
@@ -22,4 +22,6 @@ public interface GLAccountReadPlatformService {
List<GLAccountData> retrieveAllEnabledDetailGLAccounts(GLAccountType accountType); List<GLAccountData> retrieveAllEnabledDetailGLAccounts(GLAccountType accountType);
GLAccountData retrieveNewGLAccountDetails(); GLAccountData retrieveNewGLAccountDetails();
List<GLAccountData> retrieveAllEnabledHeaderGLAccounts(GLAccountType accountType);
} }
@@ -17,6 +17,7 @@ import org.mifosplatform.accounting.glaccount.domain.GLAccountType;
import org.mifosplatform.accounting.glaccount.domain.GLAccountUsage; import org.mifosplatform.accounting.glaccount.domain.GLAccountUsage;
import org.mifosplatform.accounting.glaccount.exception.GLAccountInvalidClassificationException; import org.mifosplatform.accounting.glaccount.exception.GLAccountInvalidClassificationException;
import org.mifosplatform.accounting.glaccount.exception.GLAccountNotFoundException; import org.mifosplatform.accounting.glaccount.exception.GLAccountNotFoundException;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData; import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport; import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource; import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
@@ -30,6 +31,7 @@ import org.springframework.stereotype.Service;
public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformService { public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformService {
private final JdbcTemplate jdbcTemplate; private final JdbcTemplate jdbcTemplate;
private final static String nameDecoratedBaseOnHierarchy = "concat(substring('........................................', 1, ((LENGTH(hierarchy) - LENGTH(REPLACE(hierarchy, '.', '')) - 1) * 4)), name)";
@Autowired @Autowired
public GLAccountReadPlatformServiceImpl(final TenantAwareRoutingDataSource dataSource) { public GLAccountReadPlatformServiceImpl(final TenantAwareRoutingDataSource dataSource) {
@@ -39,9 +41,9 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
private static final class GLAccountMapper implements RowMapper<GLAccountData> { private static final class GLAccountMapper implements RowMapper<GLAccountData> {
public String schema() { public String schema() {
return " id as id, name as name, parent_id as parentId, gl_code as glCode, disabled as disabled, manual_journal_entries_allowed as manualEntriesAllowed, " return " gl.id as id, name as name, parent_id as parentId, gl_code as glCode, disabled as disabled, manual_journal_entries_allowed as manualEntriesAllowed, "
+ "classification_enum as classification, account_usage as accountUsage, description as description " + "classification_enum as classification, account_usage as accountUsage, description as description, "+nameDecoratedBaseOnHierarchy +"as nameDecorated, "
+ "from acc_gl_account"; + "cv.id as codeId, cv.code_value as codeValue from acc_gl_account gl left join m_code_value cv on tag_id=cv.id";
} }
@Override @Override
@@ -58,8 +60,11 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
final int usageId = JdbcSupport.getInteger(rs, "accountUsage"); final int usageId = JdbcSupport.getInteger(rs, "accountUsage");
final EnumOptionData usage = AccountingEnumerations.gLAccountUsage(usageId); final EnumOptionData usage = AccountingEnumerations.gLAccountUsage(usageId);
final String description = rs.getString("description"); final String description = rs.getString("description");
final String nameDecorated = rs.getString("nameDecorated");
return new GLAccountData(id, name, parentId, glCode, disabled, manualEntriesAllowed, accountType, usage, description); final Long codeId = rs.getLong("codeId");
final String codeValue = rs.getString("codeValue");
CodeValueData tagId = CodeValueData.instance(codeId, codeValue);
return new GLAccountData(id, name, parentId, glCode, disabled, manualEntriesAllowed, accountType, usage, description, nameDecorated, tagId);
} }
} }
@@ -151,7 +156,7 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
try { try {
final GLAccountMapper rm = new GLAccountMapper(); final GLAccountMapper rm = new GLAccountMapper();
final String sql = "select " + rm.schema() + " where id = ?"; final String sql = "select " + rm.schema() + " where gl.id = ?";
final GLAccountData glAccountData = this.jdbcTemplate.queryForObject(sql, rm, new Object[] { glAccountId }); final GLAccountData glAccountData = this.jdbcTemplate.queryForObject(sql, rm, new Object[] { glAccountId });
@@ -190,4 +195,9 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
return GLAccountData.sensibleDefaultsForNewGLAccountCreation(); return GLAccountData.sensibleDefaultsForNewGLAccountCreation();
} }
@Override
public List<GLAccountData> retrieveAllEnabledHeaderGLAccounts(GLAccountType accountType) {
return retrieveAllGLAccounts(accountType.getValue(), null, GLAccountUsage.HEADER.getValue(), null, false);
}
} }
@@ -8,10 +8,12 @@ package org.mifosplatform.accounting.glaccount.service;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.mifosplatform.accounting.common.AccountingConstants;
import org.mifosplatform.accounting.glaccount.api.GLAccountJsonInputParams; import org.mifosplatform.accounting.glaccount.api.GLAccountJsonInputParams;
import org.mifosplatform.accounting.glaccount.command.GLAccountCommand; import org.mifosplatform.accounting.glaccount.command.GLAccountCommand;
import org.mifosplatform.accounting.glaccount.domain.GLAccount; import org.mifosplatform.accounting.glaccount.domain.GLAccount;
import org.mifosplatform.accounting.glaccount.domain.GLAccountRepository; import org.mifosplatform.accounting.glaccount.domain.GLAccountRepository;
import org.mifosplatform.accounting.glaccount.domain.GLAccountType;
import org.mifosplatform.accounting.glaccount.exception.GLAccountDuplicateException; import org.mifosplatform.accounting.glaccount.exception.GLAccountDuplicateException;
import org.mifosplatform.accounting.glaccount.exception.GLAccountInvalidDeleteException; import org.mifosplatform.accounting.glaccount.exception.GLAccountInvalidDeleteException;
import org.mifosplatform.accounting.glaccount.exception.GLAccountInvalidDeleteException.GL_ACCOUNT_INVALID_DELETE_REASON; import org.mifosplatform.accounting.glaccount.exception.GLAccountInvalidDeleteException.GL_ACCOUNT_INVALID_DELETE_REASON;
@@ -22,6 +24,8 @@ import org.mifosplatform.accounting.glaccount.exception.GLAccountNotFoundExcepti
import org.mifosplatform.accounting.glaccount.serialization.GLAccountCommandFromApiJsonDeserializer; import org.mifosplatform.accounting.glaccount.serialization.GLAccountCommandFromApiJsonDeserializer;
import org.mifosplatform.accounting.journalentry.domain.JournalEntry; import org.mifosplatform.accounting.journalentry.domain.JournalEntry;
import org.mifosplatform.accounting.journalentry.domain.JournalEntryRepository; import org.mifosplatform.accounting.journalentry.domain.JournalEntryRepository;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.codes.domain.CodeValueRepositoryWrapper;
import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
@@ -41,13 +45,16 @@ public class GLAccountWritePlatformServiceJpaRepositoryImpl implements GLAccount
private final GLAccountRepository glAccountRepository; private final GLAccountRepository glAccountRepository;
private final JournalEntryRepository glJournalEntryRepository; private final JournalEntryRepository glJournalEntryRepository;
private final GLAccountCommandFromApiJsonDeserializer fromApiJsonDeserializer; private final GLAccountCommandFromApiJsonDeserializer fromApiJsonDeserializer;
private final CodeValueRepositoryWrapper codeValueRepositoryWrapper;
@Autowired @Autowired
public GLAccountWritePlatformServiceJpaRepositoryImpl(final GLAccountRepository glAccountRepository, public GLAccountWritePlatformServiceJpaRepositoryImpl(final GLAccountRepository glAccountRepository,
final JournalEntryRepository glJournalEntryRepository, final GLAccountCommandFromApiJsonDeserializer fromApiJsonDeserializer) { final JournalEntryRepository glJournalEntryRepository, final GLAccountCommandFromApiJsonDeserializer fromApiJsonDeserializer,
final CodeValueRepositoryWrapper codeValueRepositoryWrapper) {
this.glAccountRepository = glAccountRepository; this.glAccountRepository = glAccountRepository;
this.glJournalEntryRepository = glJournalEntryRepository; this.glJournalEntryRepository = glJournalEntryRepository;
this.fromApiJsonDeserializer = fromApiJsonDeserializer; this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.codeValueRepositoryWrapper = codeValueRepositoryWrapper;
} }
@Transactional @Transactional
@@ -63,10 +70,42 @@ public class GLAccountWritePlatformServiceJpaRepositoryImpl implements GLAccount
if (parentId != null) { if (parentId != null) {
parentGLAccount = validateParentGLAccount(parentId); parentGLAccount = validateParentGLAccount(parentId);
} }
final GLAccount glAccount = GLAccount.fromJson(parentGLAccount, command);
CodeValue glAccountTagType = null;
Long tagId = command.longValueOfParameterNamed(GLAccountJsonInputParams.TAGID.getValue());
Long type = command.longValueOfParameterNamed(GLAccountJsonInputParams.TYPE.getValue());
GLAccountType accountType = GLAccountType.fromInt(type.intValue());
if (accountType == null) {
// TODO:generate an appropriate exception type.
throw new RuntimeException("Invalid GLAccount Type");
}
if (accountType.isAssetType()) {
glAccountTagType = this.codeValueRepositoryWrapper.findOneByCodeNameAndIdWithNotFoundDetection(
AccountingConstants.ASSESTS_TAG_OPTION_CODE_NAME, tagId);
} else if (accountType.isLiabilityType()) {
glAccountTagType = this.codeValueRepositoryWrapper.findOneByCodeNameAndIdWithNotFoundDetection(
AccountingConstants.LIABILITIES_TAG_OPTION_CODE_NAME, tagId);
} else if (accountType.isEquityType()) {
glAccountTagType = this.codeValueRepositoryWrapper.findOneByCodeNameAndIdWithNotFoundDetection(
AccountingConstants.EQUITY_TAG_OPTION_CODE_NAME, tagId);
} else if (accountType.isIncomeType()) {
glAccountTagType = this.codeValueRepositoryWrapper.findOneByCodeNameAndIdWithNotFoundDetection(
AccountingConstants.INCOME_TAG_OPTION_CODE_NAME, tagId);
} else if (accountType.isExpenseType()) {
glAccountTagType = this.codeValueRepositoryWrapper.findOneByCodeNameAndIdWithNotFoundDetection(
AccountingConstants.EXPENSES_TAG_OPTION_CODE_NAME, tagId);
}
final GLAccount glAccount = GLAccount.fromJson(parentGLAccount, command, glAccountTagType);
this.glAccountRepository.saveAndFlush(glAccount); this.glAccountRepository.saveAndFlush(glAccount);
glAccount.generateHierarchy();
this.glAccountRepository.save(glAccount);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(glAccount.getId()).build(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(glAccount.getId()).build();
} catch (final DataIntegrityViolationException dve) { } catch (final DataIntegrityViolationException dve) {
handleGLAccountDataIntegrityIssues(command, dve); handleGLAccountDataIntegrityIssues(command, dve);
@@ -147,7 +186,7 @@ public class GLAccountWritePlatformServiceJpaRepositoryImpl implements GLAccount
parentGLAccount = this.glAccountRepository.findOne(parentAccountId); parentGLAccount = this.glAccountRepository.findOne(parentAccountId);
if (parentGLAccount == null) { throw new GLAccountNotFoundException(parentAccountId); } if (parentGLAccount == null) { throw new GLAccountNotFoundException(parentAccountId); }
// ensure parent is not a detail account // ensure parent is not a detail account
if (parentGLAccount.isHeaderAccount()) { throw new GLAccountInvalidParentException(parentAccountId); } if (parentGLAccount.isDetailAccount()) { throw new GLAccountInvalidParentException(parentAccountId); }
return parentGLAccount; return parentGLAccount;
} }