accounting wip: addressing review comments

This commit is contained in:
Vishwas Babu AJ
2013-01-22 03:08:44 +05:30
parent 0a30e4e08c
commit 72e712de24
29 changed files with 700 additions and 214 deletions
+45
View File
@@ -0,0 +1,45 @@
-- Make classification an enumeration for GL Account table
update acc_gl_account
set acc_gl_account.classification=1 where acc_gl_account.classification="ASSET";
update acc_gl_account
set acc_gl_account.classification=2 where acc_gl_account.classification="LIABILITY";
update acc_gl_account
set acc_gl_account.classification=3 where acc_gl_account.classification="EQUITY";
update acc_gl_account
set acc_gl_account.classification=4 where acc_gl_account.classification="INCOME";
update acc_gl_account
set acc_gl_account.classification=5 where acc_gl_account.classification="EXPENSE";
ALTER TABLE `acc_gl_account`
ALTER `classification` DROP DEFAULT;
ALTER TABLE `acc_gl_account`
CHANGE COLUMN `classification` `classification_enum` SMALLINT(5) NOT NULL AFTER `header_account`;
-- Rename is header account to usage in GL Account Table
update acc_gl_account
set acc_gl_account.header_account=2 where acc_gl_account.header_account=1;
update acc_gl_account
set acc_gl_account.header_account=1 where acc_gl_account.header_account=0;
ALTER TABLE `acc_gl_account`
CHANGE COLUMN `header_account` `account_usage` TINYINT(1) NOT NULL DEFAULT '2' AFTER `manual_journal_entries_allowed`;
-- Update Type in journal entries table
update acc_gl_journal_entry
set acc_gl_journal_entry.type=1 where acc_gl_journal_entry.type="CREDIT";
update acc_gl_journal_entry
set acc_gl_journal_entry.type=2 where acc_gl_journal_entry.type="DEBIT";
ALTER TABLE `acc_gl_journal_entry`
ALTER `type` DROP DEFAULT;
ALTER TABLE `acc_gl_journal_entry`
CHANGE COLUMN `type` `type_enum` SMALLINT(50) NOT NULL AFTER `entry_date`;
@@ -5,68 +5,6 @@ import java.util.Map;
public class AccountingConstants {
/*** Categories for Accounting **/
public static enum GL_ACCOUNT_CLASSIFICATION {
ASSET, LIABILITY, INCOME, EXPENSE, EQUITY;
@Override
public String toString() {
return name().toString();
}
}
/** Types of Journal Entries **/
public static enum JOURNAL_ENTRY_TYPE {
DEBIT, CREDIT;
@Override
public String toString() {
return name().toString();
}
}
/** USAGES of Accounts **/
public static enum GL_ACCOUNT_USAGE {
HEADER, DETAIL;
@Override
public String toString() {
return name().toString();
}
}
/*** Types of portfolio products ***/
public static enum PORTFOLIO_PRODUCT_TYPE {
LOAN(1), SAVING(2);
private final Integer value;
private PORTFOLIO_PRODUCT_TYPE(final Integer value) {
this.value = value;
}
@Override
public String toString() {
return name().toString().replaceAll("_", " ");
}
public Integer getValue() {
return this.value;
}
private static final Map<Integer, PORTFOLIO_PRODUCT_TYPE> intToEnumMap = new HashMap<Integer, PORTFOLIO_PRODUCT_TYPE>();
static {
for (PORTFOLIO_PRODUCT_TYPE type : PORTFOLIO_PRODUCT_TYPE.values()) {
intToEnumMap.put(type.value, type);
}
}
public static PORTFOLIO_PRODUCT_TYPE fromInt(int i) {
PORTFOLIO_PRODUCT_TYPE type = intToEnumMap.get(Integer.valueOf(i));
return type;
}
}
/*** Accounting placeholders for cash based accounting for loan products ***/
public static enum CASH_ACCOUNTS_FOR_LOAN {
FUND_SOURCE(1), LOAN_PORTFOLIO(2), INTEREST_ON_LOANS(3), INCOME_FROM_FEES(4), INCOME_FROM_PENALTIES(5), LOSSES_WRITTEN_OFF(6);
@@ -21,10 +21,12 @@ import org.mifosplatform.accounting.api.commands.GLAccountCommand;
import org.mifosplatform.accounting.api.data.GLAccountData;
import org.mifosplatform.accounting.api.infrastructure.AccountingApiDataConversionService;
import org.mifosplatform.accounting.api.infrastructure.AccountingApiJsonSerializerService;
import org.mifosplatform.accounting.service.AccountingDropdownReadPlatformService;
import org.mifosplatform.accounting.service.GLAccountReadPlatformService;
import org.mifosplatform.accounting.service.GLAccountWritePlatformService;
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
@@ -47,6 +49,9 @@ public class GLAccountsApiResource {
@Autowired
private AccountingApiJsonSerializerService apiJsonSerializerService;
@Autowired
private AccountingDropdownReadPlatformService dropdownReadPlatformService;
private final String entityType = "GL_ACCOUNT";
@Autowired
@@ -65,8 +70,8 @@ public class GLAccountsApiResource {
@GET
@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("usage") final String usage,
public String retrieveAllAccounts(@Context final UriInfo uriInfo, @QueryParam("classification") final Integer classification,
@QueryParam("searchParam") final String searchParam, @QueryParam("usage") final Integer usage,
@QueryParam("manualAdjustmentsAllowed") final Boolean manualTransactionsAllowed, @QueryParam("disabled") final Boolean disabled) {
context.authenticatedUser().validateHasReadPermission(entityType);
@@ -79,6 +84,22 @@ public class GLAccountsApiResource {
return this.apiJsonSerializerService.serializeGLAccountDataToJson(prettyPrint, responseParameters, glAccountDatas);
}
@GET
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveNewLoanProductDetails(@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
GLAccountData glAccountData = this.glAccountReadPlatformService.retrieveNewGLAccountDetails();
glAccountData = handleTemplate(glAccountData);
final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
return this.apiJsonSerializerService.serializeGLAccountDataToJson(prettyPrint, responseParameters, glAccountData);
}
@GET
@Path("{glAccountId}")
@@ -92,9 +113,9 @@ public class GLAccountsApiResource {
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
final GLAccountData glAccountData = this.glAccountReadPlatformService.retrieveGLAccountById(glAccountId);
GLAccountData glAccountData = this.glAccountReadPlatformService.retrieveGLAccountById(glAccountId);
if (template) {
// TODO: define templates
glAccountData = handleTemplate(glAccountData);
}
return this.apiJsonSerializerService.serializeGLAccountDataToJson(prettyPrint, responseParameters, glAccountData);
@@ -135,4 +156,10 @@ public class GLAccountsApiResource {
return Response.ok(new CommandProcessingResult(glAccountId)).build();
}
private GLAccountData handleTemplate(GLAccountData glAccountData) {
List<EnumOptionData> accountTypeOptions = dropdownReadPlatformService.retrieveGLAccountTypeOptions();
List<EnumOptionData> usageOptions = dropdownReadPlatformService.retrieveGLAccountUsageOptions();
return new GLAccountData(glAccountData, accountTypeOptions, usageOptions);
}
}
@@ -2,6 +2,8 @@ package org.mifosplatform.accounting.api.commands;
import java.util.Set;
import org.mifosplatform.accounting.domain.GLAccountUsage;
/**
* Immutable command for adding a general Ledger Account
*/
@@ -13,15 +15,15 @@ public class GLAccountCommand {
private final String glCode;
private final Boolean disabled;
private final Boolean manualEntriesAllowed;
private final Boolean headerAccount;
private final String classification;
private final Integer usage;
private final Integer classification;
private final String description;
private final Set<String> parametersPassedInRequest;
public GLAccountCommand(final Set<String> modifiedParameters, final Long id, final String name, final Long parentId,
final String glCode, final Boolean disabled, final Boolean manualEntriesAllowed, final String classification,
final Boolean headerAccount, final String description) {
final String glCode, final Boolean disabled, final Boolean manualEntriesAllowed, final Integer classification,
final Integer usage, final String description) {
this.parametersPassedInRequest = modifiedParameters;
this.id = id;
this.name = name;
@@ -30,10 +32,14 @@ public class GLAccountCommand {
this.disabled = disabled;
this.manualEntriesAllowed = manualEntriesAllowed;
this.classification = classification;
this.headerAccount = headerAccount;
this.usage = usage;
this.description = description;
}
public boolean isHeaderAccount() {
return GLAccountUsage.HEADER.getValue().equals(this.usage);
}
public boolean isNameChanged() {
return this.parametersPassedInRequest.contains("name");
}
@@ -58,8 +64,8 @@ public class GLAccountCommand {
return this.parametersPassedInRequest.contains("classification");
}
public boolean isHeaderAccountFlagChanged() {
return this.parametersPassedInRequest.contains("headerAccount");
public boolean isUsageChanged() {
return this.parametersPassedInRequest.contains("usage");
}
public boolean isDescriptionChanged() {
@@ -90,15 +96,15 @@ public class GLAccountCommand {
return manualEntriesAllowed;
}
public Boolean getHeaderAccount() {
return headerAccount;
public Integer getUsage() {
return this.usage;
}
public String getDescription() {
return description;
}
public String getClassification() {
public Integer getClassification() {
return classification;
}
}
@@ -1,5 +1,12 @@
package org.mifosplatform.accounting.api.data;
import java.util.List;
import org.mifosplatform.accounting.domain.GLAccountType;
import org.mifosplatform.accounting.domain.GLAccountUsage;
import org.mifosplatform.accounting.service.AccountingEnumerations;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
/**
* Immutable object representing a General Ledger Account
*
@@ -8,35 +15,59 @@ package org.mifosplatform.accounting.api.data;
*/
public class GLAccountData {
@SuppressWarnings("unused")
private final Long id;
@SuppressWarnings("unused")
private final String name;
@SuppressWarnings("unused")
private final Long parentId;
@SuppressWarnings("unused")
private final String glCode;
@SuppressWarnings("unused")
private final boolean disabled;
@SuppressWarnings("unused")
private final boolean manualEntriesAllowed;
@SuppressWarnings("unused")
private final String classification;
@SuppressWarnings("unused")
private final Boolean headerAccount;
@SuppressWarnings("unused")
private final EnumOptionData type;
private final EnumOptionData usage;
private final String description;
// templates
final List<EnumOptionData> accountTypeOptions;
final List<EnumOptionData> usageOptions;
public GLAccountData(final Long id, final String name, final Long parentId, final String glCode, final boolean disabled,
final boolean manualEntriesAllowed, final String classification, final boolean headerAccount, final String description) {
final boolean manualEntriesAllowed, final EnumOptionData type, final EnumOptionData usage, final String description) {
this.id = id;
this.name = name;
this.parentId = parentId;
this.glCode = glCode;
this.disabled = disabled;
this.manualEntriesAllowed = manualEntriesAllowed;
this.classification = classification;
this.headerAccount = headerAccount;
this.type = type;
this.usage = usage;
this.description = description;
this.accountTypeOptions = null;
this.usageOptions = null;
}
public GLAccountData(GLAccountData accountData, List<EnumOptionData> accountTypeOptions, List<EnumOptionData> usageOptions) {
this.id = accountData.id;
this.name = accountData.name;
this.parentId = accountData.parentId;
this.glCode = accountData.glCode;
this.disabled = accountData.disabled;
this.manualEntriesAllowed = accountData.manualEntriesAllowed;
this.type = accountData.type;
this.usage = accountData.usage;
this.description = accountData.description;
this.accountTypeOptions = accountTypeOptions;
this.usageOptions = usageOptions;
}
public static GLAccountData sensibleDefaultsForNewGLAccountCreation() {
final Long id = null;
final String name = null;
final Long parentId = null;
final String glCode = null;
final boolean disabled = false;
final boolean manualEntriesAllowed = true;
final EnumOptionData type = AccountingEnumerations.gLAccountType(GLAccountType.ASSET);
final EnumOptionData usage = AccountingEnumerations.gLAccountUsage(GLAccountUsage.DETAIL);
final String description = null;
return new GLAccountData(id, name, parentId, glCode, disabled, manualEntriesAllowed, type, usage, description);
}
}
@@ -3,6 +3,7 @@ package org.mifosplatform.accounting.api.data;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
/**
* Immutable object representing a General Ledger Account
@@ -23,11 +24,11 @@ public class GLJournalEntryData {
@SuppressWarnings("unused")
private final Long glAccountId;
@SuppressWarnings("unused")
private final String glAccountClassification;
private final EnumOptionData glAccountClassification;
@SuppressWarnings("unused")
private final LocalDate entryDate;
@SuppressWarnings("unused")
private final String entryType;
private final EnumOptionData entryType;
@SuppressWarnings("unused")
private final BigDecimal amount;
@SuppressWarnings("unused")
@@ -50,7 +51,7 @@ public class GLJournalEntryData {
private final Boolean reversed;
public GLJournalEntryData(Long id, Long officeId, String officeName, String glAccountName, Long glAccountId,
String glAccountClassification, LocalDate entryDate, String entryType, BigDecimal amount, String transactionId,
EnumOptionData glAccountClassification, LocalDate entryDate, EnumOptionData entryType, BigDecimal amount, String transactionId,
Boolean portfolioGenerated, String entityType, Long entityId, Long createdByUserId, LocalDate createdDate,
String createdByUserName, String comments, Boolean reversed) {
this.id = id;
@@ -61,7 +61,7 @@ public class AccountingApiDataConversionServiceImpl implements AccountingApiData
final Map<String, Object> requestMap = gsonConverter.fromJson(json, typeOfMap);
final Set<String> supportedParams = new HashSet<String>(Arrays.asList("name", "parentId", "glCode", "disabled",
"manualEntriesAllowed", "classification", "headerAccount", "description", "locale", "dateFormat"));
"manualEntriesAllowed", "classification", "usage", "description", "locale", "dateFormat"));
checkForUnsupportedParameters(requestMap, supportedParams);
@@ -75,16 +75,18 @@ public class AccountingApiDataConversionServiceImpl implements AccountingApiData
final String glCode = helper.extractStringNamed("glCode", element, requestParamatersDetected);
final Boolean disabled = helper.extractBooleanNamed("disabled", element, requestParamatersDetected);
final Boolean manualEntriesAllowed = helper.extractBooleanNamed("manualEntriesAllowed", element, requestParamatersDetected);
final String category = helper.extractStringNamed("classification", element, requestParamatersDetected);
final Boolean headerAccount = helper.extractBooleanNamed("headerAccount", element, requestParamatersDetected);
final Integer category = helper.extractIntegerFromUnFormattedStringNamed("classification", element, requestParamatersDetected);
final Integer usage = helper.extractIntegerFromUnFormattedStringNamed("usage", element, requestParamatersDetected);
final String description = helper.extractStringNamed("description", element, requestParamatersDetected);
return new GLAccountCommand(requestParamatersDetected, resourceIdentifier, name, parentId, glCode, disabled, manualEntriesAllowed,
category, headerAccount, description);
category, usage, description);
}
@Override
public GLClosureCommand convertJsonToGLClosureCommand(Long resourceIdentifier, String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
final Map<String, Object> requestMap = gsonConverter.fromJson(json, typeOfMap);
@@ -107,6 +109,8 @@ public class AccountingApiDataConversionServiceImpl implements AccountingApiData
@Override
public GLJournalEntryCommand convertJsonToGLJournalEntryCommand(String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
final Map<String, Object> requestMap = gsonConverter.fromJson(json, typeOfMap);
@@ -43,19 +43,19 @@ public class GLAccount extends AbstractPersistable<Long> {
private boolean manualEntriesAllowed = true;
@SuppressWarnings("unused")
@Column(name = "classification", nullable = false, length = 45)
private String classification;
@Column(name = "classification_enum", nullable = false)
private Integer classification;
@Column(name = "header_account", nullable = false)
private boolean headerAccount;
@Column(name = "account_usage", nullable = false)
private Integer usage;
@SuppressWarnings("unused")
@Column(name = "description", nullable = true, length = 500)
private String description;
public static GLAccount createNew(final GLAccount parent, final String name, final String glCode, final boolean disabled,
final boolean manualEntriesAllowed, final String classification, final boolean headerAccount, final String description) {
return new GLAccount(parent, name, glCode, disabled, manualEntriesAllowed, classification, headerAccount, description);
final boolean manualEntriesAllowed, final Integer classification, final Integer usage, final String description) {
return new GLAccount(parent, name, glCode, disabled, manualEntriesAllowed, classification, usage, description);
}
protected GLAccount() {
@@ -63,13 +63,13 @@ public class GLAccount extends AbstractPersistable<Long> {
}
private GLAccount(final GLAccount parent, final String name, final String glCode, final boolean disabled,
final boolean manualEntriesAllowed, final String classification, final boolean headerAccount, final String description) {
final boolean manualEntriesAllowed, final Integer classification, final Integer usage, final String description) {
this.parent = parent;
this.name = StringUtils.defaultIfEmpty(name, null);
this.glCode = StringUtils.defaultIfEmpty(glCode, null);
this.disabled = BooleanUtils.toBooleanDefaultIfNull(disabled, false);
this.manualEntriesAllowed = BooleanUtils.toBooleanDefaultIfNull(manualEntriesAllowed, true);
this.headerAccount = BooleanUtils.toBooleanDefaultIfNull(headerAccount, false);
this.usage = usage;
this.classification = classification;
this.description = StringUtils.defaultIfEmpty(description, null);
}
@@ -87,8 +87,8 @@ public class GLAccount extends AbstractPersistable<Long> {
if (command.isGLCodeChanged()) {
this.glCode = command.getGlCode();
}
if (command.isHeaderAccountFlagChanged()) {
this.headerAccount = command.getHeaderAccount();
if (command.isUsageChanged()) {
this.usage = command.getUsage();
}
if (command.isManualEntriesAllowedFlagChanged()) {
this.manualEntriesAllowed = command.getManualEntriesAllowed();
@@ -102,7 +102,11 @@ public class GLAccount extends AbstractPersistable<Long> {
}
public boolean isHeaderAccount() {
return headerAccount;
return GLAccountUsage.HEADER.getValue().equals(this.usage);
}
public Integer getUsage() {
return this.usage;
}
public List<GLAccount> getChildren() {
@@ -0,0 +1,64 @@
package org.mifosplatform.accounting.domain;
import java.util.HashMap;
import java.util.Map;
public enum GLAccountType {
ASSET(1, "accountType.asset"), LIABILITY(2, "accountType.liability"), EQUITY(3, "accountType.equity"), INCOME(4, "accountType.income"), EXPENSE(
5, "accountType.expense"), ;
private final Integer value;
private final String code;
private GLAccountType(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return code;
}
private static final Map<Integer, GLAccountType> intToEnumMap = new HashMap<Integer, GLAccountType>();
private static int minValue;
private static int maxValue;
static {
int i = 0;
for (GLAccountType type : GLAccountType.values()) {
if (i == 0) {
minValue = type.value;
}
intToEnumMap.put(type.value, type);
if (minValue >= type.value) {
minValue = type.value;
}
if (maxValue < type.value) {
maxValue = type.value;
}
i = i + 1;
}
}
public static GLAccountType fromInt(int i) {
GLAccountType type = intToEnumMap.get(Integer.valueOf(i));
return type;
}
public static int getMinValue() {
return minValue;
}
public static int getMaxValue() {
return maxValue;
}
@Override
public String toString() {
return name().toString();
}
}
@@ -0,0 +1,64 @@
package org.mifosplatform.accounting.domain;
import java.util.HashMap;
import java.util.Map;
public enum GLAccountUsage {
DETAIL(1, "accountUsage.detail"), HEADER(2, "accountUsage.header");
private final Integer value;
private final String code;
private GLAccountUsage(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return code;
}
private static final Map<Integer, GLAccountUsage> intToEnumMap = new HashMap<Integer, GLAccountUsage>();
private static int minValue;
private static int maxValue;
static {
int i = 0;
for (GLAccountUsage type : GLAccountUsage.values()) {
if (i == 0) {
minValue = type.value;
}
intToEnumMap.put(type.value, type);
if (minValue >= type.value) {
minValue = type.value;
}
if (maxValue < type.value) {
maxValue = type.value;
}
i = i + 1;
}
}
public static GLAccountUsage fromInt(int i) {
GLAccountUsage type = intToEnumMap.get(Integer.valueOf(i));
return type;
}
public static int getMinValue() {
return minValue;
}
public static int getMaxValue() {
return maxValue;
}
@Override
public String toString() {
return name().toString();
}
}
@@ -50,8 +50,8 @@ public class GLJournalEntry extends AbstractAuditableCustom<AppUser, Long> {
@Temporal(TemporalType.DATE)
private Date entryDate;
@Column(name = "type", nullable = false, length = 50)
private String type;
@Column(name = "type_enum", nullable = false, length = 50)
private Integer type;
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
private BigDecimal amount;
@@ -69,9 +69,9 @@ public class GLJournalEntry extends AbstractAuditableCustom<AppUser, Long> {
private Long entityId;
public static GLJournalEntry createNew(Office office, GLAccount glAccount, String transactionId, boolean portfolioGenerated,
Date entryDate, String type, BigDecimal amount, String description, String entityType, Long entityId) {
return new GLJournalEntry(office, glAccount, transactionId, portfolioGenerated, entryDate, type, amount, description, entityType,
entityId);
Date entryDate, JournalEntryType journalEntryType, BigDecimal amount, String description, String entityType, Long entityId) {
return new GLJournalEntry(office, glAccount, transactionId, portfolioGenerated, entryDate, journalEntryType.getValue(), amount,
description, entityType, entityId);
}
protected GLJournalEntry() {
@@ -79,7 +79,7 @@ public class GLJournalEntry extends AbstractAuditableCustom<AppUser, Long> {
}
public GLJournalEntry(Office office, GLAccount glAccount, String transactionId, boolean portfolioGenerated, Date entryDate,
String type, BigDecimal amount, String description, String entityType, Long entityId) {
Integer type, BigDecimal amount, String description, String entityType, Long entityId) {
this.office = office;
this.glAccount = glAccount;
this.reversalJournalEntry = null;
@@ -94,7 +94,11 @@ public class GLJournalEntry extends AbstractAuditableCustom<AppUser, Long> {
this.entityId = entityId;
}
public String getType() {
public boolean isDebitEntry() {
return JournalEntryType.DEBIT.getValue().equals(type);
}
public Integer getType() {
return this.type;
}
@@ -0,0 +1,44 @@
package org.mifosplatform.accounting.domain;
import java.util.HashMap;
import java.util.Map;
public enum JournalEntryType {
CREDIT(1, "journalEntryType.credit"), DEBIT(2, "journalEntrytType.debit");
private final Integer value;
private final String code;
private JournalEntryType(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return code;
}
private static final Map<Integer, JournalEntryType> intToEnumMap = new HashMap<Integer, JournalEntryType>();
static {
for (JournalEntryType type : JournalEntryType.values()) {
intToEnumMap.put(type.value, type);
}
}
public static JournalEntryType fromInt(int i) {
JournalEntryType type = intToEnumMap.get(Integer.valueOf(i));
return type;
}
@Override
public String toString() {
return name().toString();
}
}
@@ -0,0 +1,42 @@
package org.mifosplatform.accounting.domain;
import java.util.HashMap;
import java.util.Map;
public enum PortfolioProductType {
LOAN(1, "productType.loan"), SAVING(2, "productType.saving");
private final Integer value;
private final String code;
private PortfolioProductType(final Integer value, final String code) {
this.value = value;
this.code = code;
}
@Override
public String toString() {
return name().toString().replaceAll("_", " ");
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return code;
}
private static final Map<Integer, PortfolioProductType> intToEnumMap = new HashMap<Integer, PortfolioProductType>();
static {
for (PortfolioProductType type : PortfolioProductType.values()) {
intToEnumMap.put(type.value, type);
}
}
public static PortfolioProductType fromInt(int i) {
PortfolioProductType type = intToEnumMap.get(Integer.valueOf(i));
return type;
}
}
@@ -4,11 +4,11 @@ import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRul
/**
* A {@link RuntimeException} thrown when trying to fetch accounts belonging to
* an Invalid Type
* an Invalid Usage Type
*/
public class GLAccountInvalidClassificationException extends AbstractPlatformDomainRuleException {
public GLAccountInvalidClassificationException(final String classification) {
super("error.msg.glaccount.classification.invalid", "The following COA classification is invalid: " + classification);
public GLAccountInvalidClassificationException(final Integer usage) {
super("error.msg.glaccount.usage.invalid", "The following COA usage is invalid: " + usage);
}
}
@@ -0,0 +1,14 @@
package org.mifosplatform.accounting.exceptions;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
/**
* A {@link RuntimeException} thrown when trying to fetch accounts belonging to
* an Invalid Type
*/
public class GLAccountInvalidUsageException extends AbstractPlatformDomainRuleException {
public GLAccountInvalidUsageException(final Integer type) {
super("error.msg.glaccount.classification.invalid", "The following COA type is invalid: " + type);
}
}
@@ -1,6 +1,6 @@
package org.mifosplatform.accounting.exceptions;
import org.mifosplatform.accounting.AccountingConstants.PORTFOLIO_PRODUCT_TYPE;
import org.mifosplatform.accounting.domain.PortfolioProductType;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
/**
@@ -9,7 +9,7 @@ import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceN
*/
public class ProductToGLAccountMappingNotFoundException extends AbstractPlatformResourceNotFoundException {
public ProductToGLAccountMappingNotFoundException(final PORTFOLIO_PRODUCT_TYPE type, final Long productId, String accountType) {
public ProductToGLAccountMappingNotFoundException(final PortfolioProductType type, final Long productId, String accountType) {
super("error.msg.productTyAccountMapping.not.found", "Mapping for product of type" + type.toString() + " with Id " + productId
+ " does not exist for an account of type " + accountType, type.toString(), productId, accountType);
}
@@ -0,0 +1,14 @@
package org.mifosplatform.accounting.service;
import java.util.List;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
public interface AccountingDropdownReadPlatformService {
public List<EnumOptionData> retrieveGLAccountTypeOptions();
public List<EnumOptionData> retrieveGLAccountUsageOptions();
public List<EnumOptionData> retrieveJournalEntryTypeOptions();
}
@@ -0,0 +1,76 @@
package org.mifosplatform.accounting.service;
import java.util.ArrayList;
import java.util.List;
import org.mifosplatform.accounting.domain.GLAccountType;
import org.mifosplatform.accounting.domain.GLAccountUsage;
import org.mifosplatform.accounting.domain.JournalEntryType;
import org.mifosplatform.accounting.domain.PortfolioProductType;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
public class AccountingEnumerations {
public static EnumOptionData gLAccountType(final int id) {
return gLAccountType(GLAccountType.fromInt(id));
}
public static EnumOptionData gLAccountType(final GLAccountType accountType) {
EnumOptionData optionData = new EnumOptionData(accountType.getValue().longValue(), accountType.getCode(), accountType.toString());
return optionData;
}
public static List<EnumOptionData> gLAccountType(GLAccountType[] accountTypes) {
List<EnumOptionData> optionDatas = new ArrayList<EnumOptionData>();
for (GLAccountType accountType : accountTypes) {
optionDatas.add(gLAccountType(accountType));
}
return optionDatas;
}
public static EnumOptionData gLAccountUsage(final int id) {
return gLAccountUsage(GLAccountUsage.fromInt(id));
}
public static EnumOptionData gLAccountUsage(final GLAccountUsage accountUsage) {
EnumOptionData optionData = new EnumOptionData(accountUsage.getValue().longValue(), accountUsage.getCode(), accountUsage.toString());
return optionData;
}
public static List<EnumOptionData> gLAccountUsage(GLAccountUsage[] accountUsages) {
List<EnumOptionData> optionDatas = new ArrayList<EnumOptionData>();
for (GLAccountUsage accountUsage : accountUsages) {
optionDatas.add(gLAccountUsage(accountUsage));
}
return optionDatas;
}
public static EnumOptionData journalEntryType(final int id) {
return journalEntryType(JournalEntryType.fromInt(id));
}
public static EnumOptionData journalEntryType(final JournalEntryType journalEntryType) {
EnumOptionData optionData = new EnumOptionData(journalEntryType.getValue().longValue(), journalEntryType.getCode(),
journalEntryType.toString());
return optionData;
}
public static List<EnumOptionData> journalEntryTypes(JournalEntryType[] journalEntryTypes) {
List<EnumOptionData> optionDatas = new ArrayList<EnumOptionData>();
for (JournalEntryType journalEntryType : journalEntryTypes) {
optionDatas.add(journalEntryType(journalEntryType));
}
return optionDatas;
}
public static EnumOptionData portfolioProductType(final int id) {
return portfolioProductType(PortfolioProductType.fromInt(id));
}
public static EnumOptionData portfolioProductType(final PortfolioProductType portfolioProductType) {
EnumOptionData optionData = new EnumOptionData(portfolioProductType.getValue().longValue(), portfolioProductType.getCode(),
portfolioProductType.toString());
return optionData;
}
}
@@ -4,6 +4,8 @@ import java.util.ArrayList;
import java.util.List;
import org.mifosplatform.accounting.api.commands.GLAccountCommand;
import org.mifosplatform.accounting.domain.GLAccountType;
import org.mifosplatform.accounting.domain.GLAccountUsage;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
@@ -28,7 +30,11 @@ public class GLAccountCommandValidator {
baseDataValidator.reset().parameter("parentId").value(command.getParentId()).ignoreIfNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("classification").value(command.getClassification()).notBlank().notExceedingLengthOf(45);
baseDataValidator.reset().parameter("classification").value(command.getClassification())
.inMinMaxRange(GLAccountType.getMinValue(), GLAccountType.getMaxValue());
baseDataValidator.reset().parameter("usage").value(command.getUsage())
.inMinMaxRange(GLAccountUsage.getMinValue(), GLAccountUsage.getMaxValue());
baseDataValidator.reset().parameter("description").value(command.getDescription()).ignoreIfNull().notExceedingLengthOf(500);
@@ -49,8 +55,10 @@ public class GLAccountCommandValidator {
baseDataValidator.reset().parameter("parentId").value(command.getParentId()).ignoreIfNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("classification").value(command.getClassification()).ignoreIfNull().notBlank()
.notExceedingLengthOf(45);
baseDataValidator.reset().parameter("classification").value(command.getClassification()).ignoreIfNull()
.inMinMaxRange(GLAccountType.getMinValue(), GLAccountType.getMaxValue());
baseDataValidator.reset().parameter("usage").value(command.getUsage()).ignoreIfNull()
.inMinMaxRange(GLAccountUsage.getMinValue(), GLAccountUsage.getMaxValue());
baseDataValidator.reset().parameter("description").value(command.getDescription()).ignoreIfNull().notBlank()
.notExceedingLengthOf(500);
@@ -2,16 +2,18 @@ package org.mifosplatform.accounting.service;
import java.util.List;
import org.mifosplatform.accounting.AccountingConstants;
import org.mifosplatform.accounting.api.data.GLAccountData;
import org.mifosplatform.accounting.domain.GLAccountType;
public interface GLAccountReadPlatformService {
List<GLAccountData> retrieveAllGLAccounts(String accountClassification, String searchParam, String usage,
List<GLAccountData> retrieveAllGLAccounts(Integer accountClassification, String searchParam, Integer usage,
Boolean manualTransactionsAllowed, Boolean disabled);
GLAccountData retrieveGLAccountById(long glAccountId);
List<GLAccountData> retrieveAllEnabledDetailGLAccounts(AccountingConstants.GL_ACCOUNT_CLASSIFICATION classification);
List<GLAccountData> retrieveAllEnabledDetailGLAccounts(GLAccountType accountType);
GLAccountData retrieveNewGLAccountDetails();
}
@@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import org.mifosplatform.accounting.api.commands.GLJournalEntryCommand;
import org.mifosplatform.accounting.api.commands.SingleDebitOrCreditEntryCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
@@ -28,8 +29,50 @@ public class GLJournalEntryCommandValidator {
baseDataValidator.reset().parameter("comments").value(command.getComments()).ignoreIfNull().notExceedingLengthOf(500);
baseDataValidator.reset().parameter("credits").value(command.getCredits()).notNull();
baseDataValidator.reset().parameter("debits").value(command.getDebits()).notNull();
// validation for credit array elements
if (command.getCredits() != null) {
if (command.getCredits().length == 0) {
validateSingleDebitOrCredit(baseDataValidator, "credits", 0, new SingleDebitOrCreditEntryCommand(null, null, null, null));
} else {
int i = 0;
for (SingleDebitOrCreditEntryCommand credit : command.getCredits()) {
validateSingleDebitOrCredit(baseDataValidator, "credits", i, credit);
i++;
}
}
}
// validation for debit array elements
if (command.getDebits() != null) {
if (command.getDebits().length == 0) {
validateSingleDebitOrCredit(baseDataValidator, "credits", 0, new SingleDebitOrCreditEntryCommand(null, null, null, null));
} else {
int i = 0;
for (SingleDebitOrCreditEntryCommand debit : command.getDebits()) {
validateSingleDebitOrCredit(baseDataValidator, "debits", i, debit);
i++;
}
}
}
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
/**
* @param baseDataValidator
* @param i
* @param credit
*/
private void validateSingleDebitOrCredit(DataValidatorBuilder baseDataValidator, String paramSuffix, int arrayPos,
SingleDebitOrCreditEntryCommand credit) {
baseDataValidator.reset().parameter(paramSuffix + "[" + arrayPos + "].glAccountId").value(credit.getGlAccountId()).notNull()
.integerGreaterThanZero();
baseDataValidator.reset().parameter(paramSuffix + "[" + arrayPos + "].amount").value(credit.getAmount()).notNull()
.zeroOrPositiveAmount();
}
}
@@ -0,0 +1,31 @@
package org.mifosplatform.accounting.service.impl;
import java.util.List;
import org.mifosplatform.accounting.domain.GLAccountType;
import org.mifosplatform.accounting.domain.GLAccountUsage;
import org.mifosplatform.accounting.domain.JournalEntryType;
import org.mifosplatform.accounting.service.AccountingDropdownReadPlatformService;
import org.mifosplatform.accounting.service.AccountingEnumerations;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.springframework.stereotype.Service;
@Service
public class AccountingDropdownReadPlatformServiceImpl implements AccountingDropdownReadPlatformService {
@Override
public List<EnumOptionData> retrieveGLAccountTypeOptions() {
return AccountingEnumerations.gLAccountType(GLAccountType.values());
}
@Override
public List<EnumOptionData> retrieveGLAccountUsageOptions() {
return AccountingEnumerations.gLAccountUsage(GLAccountUsage.values());
}
@Override
public List<EnumOptionData> retrieveJournalEntryTypeOptions() {
return AccountingEnumerations.journalEntryTypes(JournalEntryType.values());
}
}
@@ -6,13 +6,15 @@ import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.mifosplatform.accounting.AccountingConstants;
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.domain.GLAccountType;
import org.mifosplatform.accounting.domain.GLAccountUsage;
import org.mifosplatform.accounting.exceptions.GLAccountInvalidClassificationException;
import org.mifosplatform.accounting.exceptions.GLAccountNotFoundException;
import org.mifosplatform.accounting.service.AccountingEnumerations;
import org.mifosplatform.accounting.service.GLAccountReadPlatformService;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
@@ -34,7 +36,7 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
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, "
+ "classification as classification, header_account as headerAccount, description as description "
+ "classification_enum as classification, account_usage as accountUsage, description as description "
+ "from acc_gl_account";
}
@@ -47,20 +49,25 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
String glCode = rs.getString("glCode");
boolean disabled = rs.getBoolean("disabled");
boolean manualEntriesAllowed = rs.getBoolean("manualEntriesAllowed");
String classification = rs.getString("classification");
boolean headerAccount = rs.getBoolean("headerAccount");
final int accountTypeId = JdbcSupport.getInteger(rs, "classification");
final EnumOptionData accountType = AccountingEnumerations.gLAccountType(accountTypeId);
final int usageId = JdbcSupport.getInteger(rs, "accountUsage");
final EnumOptionData usage = AccountingEnumerations.gLAccountUsage(usageId);
String description = rs.getString("description");
return new GLAccountData(id, name, parentId, glCode, disabled, manualEntriesAllowed, classification, headerAccount, description);
return new GLAccountData(id, name, parentId, glCode, disabled, manualEntriesAllowed, accountType, usage, description);
}
}
@Override
public List<GLAccountData> retrieveAllGLAccounts(String accountClassification, String searchParam, String usage,
public List<GLAccountData> retrieveAllGLAccounts(Integer accountClassification, String searchParam, Integer usage,
Boolean manualTransactionsAllowed, Boolean disabled) {
if (StringUtils.isNotBlank(accountClassification)) {
if (!checkValidGLAccountClassification(accountClassification)) { throw new GLAccountInvalidClassificationException(
accountClassification); }
if (accountClassification != null) {
if (!checkValidGLAccountType(accountClassification)) { throw new GLAccountInvalidClassificationException(accountClassification); }
}
if (usage != null) {
if (!checkValidGLAccountUsage(usage)) { throw new GLAccountInvalidClassificationException(accountClassification); }
}
GLAccountMapper rm = new GLAccountMapper();
@@ -68,7 +75,7 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
Object[] paramaterArray = new Object[3];
int arrayPos = 0;
boolean filtersPresent = false;
if (StringUtils.isNotBlank(accountClassification) || StringUtils.isNotBlank(searchParam) || StringUtils.isNotBlank(usage)
if ((accountClassification != null) || StringUtils.isNotBlank(searchParam) || (usage != null)
|| (manualTransactionsAllowed != null) || (disabled != null)) {
filtersPresent = true;
sql += " where";
@@ -76,8 +83,8 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
if (filtersPresent) {
boolean firstWhereConditionAdded = false;
if (StringUtils.isNotBlank(accountClassification)) {
sql += " classification like ?";
if (accountClassification != null) {
sql += " classification_enum like ?";
paramaterArray[arrayPos] = accountClassification;
arrayPos = arrayPos + 1;
firstWhereConditionAdded = true;
@@ -93,16 +100,14 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
arrayPos = arrayPos + 1;
firstWhereConditionAdded = true;
}
if (StringUtils.isNotBlank(usage)) {
if (usage != null) {
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 {
if (GLAccountUsage.HEADER.getValue().equals(usage)) {
sql += " account_usage = 2 ";
} else if (GLAccountUsage.DETAIL.getValue().equals(usage)) {
sql += " account_usage = 1 ";
}
firstWhereConditionAdded = true;
}
@@ -153,15 +158,27 @@ public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformSe
}
@Override
public List<GLAccountData> retrieveAllEnabledDetailGLAccounts(GL_ACCOUNT_CLASSIFICATION classification) {
return retrieveAllGLAccounts(classification.toString(), null, AccountingConstants.GL_ACCOUNT_USAGE.DETAIL.toString(), null, false);
public List<GLAccountData> retrieveAllEnabledDetailGLAccounts(GLAccountType accountType) {
return retrieveAllGLAccounts(accountType.getValue(), null, GLAccountUsage.DETAIL.getValue(), null, false);
}
private static boolean checkValidGLAccountClassification(final String entityType) {
for (GL_ACCOUNT_CLASSIFICATION classification : GL_ACCOUNT_CLASSIFICATION.values()) {
if (classification.name().toString().equalsIgnoreCase(entityType)) { return true; }
private static boolean checkValidGLAccountType(final int type) {
for (GLAccountType accountType : GLAccountType.values()) {
if (accountType.getValue().equals(type)) { return true; }
}
return false;
}
private static boolean checkValidGLAccountUsage(final int type) {
for (GLAccountUsage accountUsage : GLAccountUsage.values()) {
if (accountUsage.getValue().equals(type)) { return true; }
}
return false;
}
@Override
public GLAccountData retrieveNewGLAccountDetails() {
return GLAccountData.sensibleDefaultsForNewGLAccountCreation();
}
}
@@ -2,20 +2,17 @@ package org.mifosplatform.accounting.service.impl;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.mifosplatform.accounting.AccountingConstants.GL_ACCOUNT_CLASSIFICATION;
import org.mifosplatform.accounting.api.commands.GLAccountCommand;
import org.mifosplatform.accounting.domain.GLAccount;
import org.mifosplatform.accounting.domain.GLAccountRepository;
import org.mifosplatform.accounting.domain.GLJournalEntry;
import org.mifosplatform.accounting.domain.GLJournalEntryRepository;
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.GLAccountInvalidUpdateException.GL_ACCOUNT_INVALID_UPDATE_REASON;
import org.mifosplatform.accounting.exceptions.GLAccountNotFoundException;
import org.mifosplatform.accounting.service.GLAccountCommandValidator;
import org.mifosplatform.accounting.service.GLAccountWritePlatformService;
@@ -49,18 +46,13 @@ public class GLAccountWritePlatformServiceJpaRepositoryImpl implements GLAccount
GLAccountCommandValidator validator = new GLAccountCommandValidator(command);
validator.validateForCreate();
if (StringUtils.isNotBlank(command.getClassification())) {
if (!checkValidGLAccountClassification(command.getClassification())) { throw new GLAccountInvalidClassificationException(
command.getClassification()); }
}
// check parent is valid
GLAccount parentGLAccount = null;
if (command.getParentId() != null) {
parentGLAccount = validateParentGLAccount(command);
}
GLAccount glAccount = GLAccount.createNew(parentGLAccount, command.getName(), command.getGlCode(), false,
command.getManualEntriesAllowed(), command.getClassification(), command.getHeaderAccount(), command.getDescription());
command.getManualEntriesAllowed(), command.getClassification(), command.getUsage(), command.getDescription());
this.glAccountRepository.saveAndFlush(glAccount);
@@ -87,18 +79,12 @@ public class GLAccountWritePlatformServiceJpaRepositoryImpl implements GLAccount
parentGLAccount = validateParentGLAccount(command);
}
// validate new classification
if (command.isClassificationChanged()) {
if (!checkValidGLAccountClassification(command.getClassification())) { throw new GLAccountInvalidClassificationException(
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) {
if (command.isUsageChanged()) {
if (command.isHeaderAccount()) {
List<GLJournalEntry> journalEntriesForAccount = glJournalEntryRepository.findFirstJournalEntryForAccount(glAccountId);
if (journalEntriesForAccount.size() > 0) { throw new GLAccountInvalidUpdateException(
GL_ACCOUNT_INVALID_UPDATE_REASON.TRANSANCTIONS_LOGGED, glAccountId); }
@@ -161,10 +147,4 @@ public class GLAccountWritePlatformServiceJpaRepositoryImpl implements GLAccount
"Unknown data integrity issue with resource GL Account: " + realCause.getMessage());
}
private static boolean checkValidGLAccountClassification(final String entityType) {
for (GL_ACCOUNT_CLASSIFICATION classification : GL_ACCOUNT_CLASSIFICATION.values()) {
if (classification.name().toString().equalsIgnoreCase(entityType)) { return true; }
}
return false;
}
}
@@ -12,7 +12,9 @@ import java.util.List;
import org.joda.time.LocalDate;
import org.mifosplatform.accounting.api.data.GLJournalEntryData;
import org.mifosplatform.accounting.exceptions.GLJournalEntriesNotFoundException;
import org.mifosplatform.accounting.service.AccountingEnumerations;
import org.mifosplatform.accounting.service.GLJournalEntryReadPlatformService;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.springframework.beans.factory.annotation.Autowired;
@@ -34,11 +36,11 @@ public class GLJournalEntryReadPlatformServiceImpl implements GLJournalEntryRead
private static final class GLJournalEntryMapper implements RowMapper<GLJournalEntryData> {
public String schema() {
return " journalEntry.id as journalEntryId, glAccount.classification as classification ,"
return " journalEntry.id as journalEntryId, glAccount.classification_enum as classification ,"
+ " glAccount.name as glAccountName, journalEntry.account_id as glAccountId,"
+ " journalEntry.office_id as officeId, office.name as officeName, "
+ " journalEntry.portfolio_generated as portfolioGenerated,journalEntry.entry_date as entryDate, "
+ " journalEntry.type as entryType,journalEntry.amount as amount, journalEntry.transaction_id as transactionId,"
+ " journalEntry.type_enum as entryType,journalEntry.amount as amount, journalEntry.transaction_id as transactionId,"
+ " journalEntry.entity_type as entityType, journalEntry.entity_id as entityId, creatingUser.id as createdByUserId, "
+ " creatingUser.username as createdByUserName, journalEntry.description as comments, "
+ " journalEntry.created_date as createdDate, journalEntry.reversed as reversed "
@@ -55,22 +57,24 @@ public class GLJournalEntryReadPlatformServiceImpl implements GLJournalEntryRead
String officeName = rs.getString("officeName");
String glAccountName = rs.getString("glAccountName");
Long glAccountId = rs.getLong("glAccountId");
String glAccountClassification = rs.getString("classification");
final int accountTypeId = JdbcSupport.getInteger(rs, "classification");
final EnumOptionData accountType = AccountingEnumerations.gLAccountType(accountTypeId);
LocalDate entryDate = JdbcSupport.getLocalDate(rs, "entryDate");
Boolean portfolioGenerated = rs.getBoolean("portfolioGenerated");
BigDecimal amount = rs.getBigDecimal("amount");
String entryType = rs.getString("entryType");
int entryTypeId = JdbcSupport.getInteger(rs, "entryType");
final EnumOptionData entryType = AccountingEnumerations.journalEntryType(entryTypeId);
String transactionId = rs.getString("transactionId");
String entityType = rs.getString("entityType");
Long entityId = rs.getLong("entityId");
Long entityId = JdbcSupport.getLong(rs, "entityId");
Long createdByUserId = rs.getLong("createdByUserId");
LocalDate createdDate = JdbcSupport.getLocalDate(rs, "createdDate");
String createdByUserName = rs.getString("createdByUserName");
String comments = rs.getString("comments");
Boolean reversed = rs.getBoolean("reversed");
return new GLJournalEntryData(journalEntryId, officeId, officeName, glAccountName, glAccountId, glAccountClassification,
entryDate, entryType, amount, transactionId, portfolioGenerated, entityType, entityId, createdByUserId, createdDate,
return new GLJournalEntryData(journalEntryId, officeId, officeName, glAccountName, glAccountId, accountType, entryDate,
entryType, amount, transactionId, portfolioGenerated, entityType, entityId, createdByUserId, createdDate,
createdByUserName, comments, reversed);
}
}
@@ -8,8 +8,6 @@ import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.accounting.AccountingConstants.CASH_ACCOUNTS_FOR_LOAN;
import org.mifosplatform.accounting.AccountingConstants.JOURNAL_ENTRY_TYPE;
import org.mifosplatform.accounting.AccountingConstants.PORTFOLIO_PRODUCT_TYPE;
import org.mifosplatform.accounting.api.commands.GLJournalEntryCommand;
import org.mifosplatform.accounting.api.commands.SingleDebitOrCreditEntryCommand;
import org.mifosplatform.accounting.api.data.LoanDTO;
@@ -20,6 +18,8 @@ import org.mifosplatform.accounting.domain.GLClosure;
import org.mifosplatform.accounting.domain.GLClosureRepository;
import org.mifosplatform.accounting.domain.GLJournalEntry;
import org.mifosplatform.accounting.domain.GLJournalEntryRepository;
import org.mifosplatform.accounting.domain.JournalEntryType;
import org.mifosplatform.accounting.domain.PortfolioProductType;
import org.mifosplatform.accounting.domain.ProductToGLAccountMapping;
import org.mifosplatform.accounting.domain.ProductToGLAccountMappingRepository;
import org.mifosplatform.accounting.exceptions.GLAccountNotFoundException;
@@ -78,9 +78,9 @@ public class GLJournalEntryWritePlatformServiceJpaRepositoryImpl implements GLJo
Date entryDate = command.getEntryDate().toDateMidnight().toDate();
String transactionId = generateTransactionId();
saveAllDebitOrCreditEntries(command, office, entryDate, command.getDebits(), transactionId, JOURNAL_ENTRY_TYPE.DEBIT);
saveAllDebitOrCreditEntries(command, office, entryDate, command.getDebits(), transactionId, JournalEntryType.DEBIT);
saveAllDebitOrCreditEntries(command, office, entryDate, command.getCredits(), transactionId, JOURNAL_ENTRY_TYPE.CREDIT);
saveAllDebitOrCreditEntries(command, office, entryDate, command.getCredits(), transactionId, JournalEntryType.CREDIT);
return transactionId;
} catch (DataIntegrityViolationException dve) {
@@ -104,14 +104,14 @@ public class GLJournalEntryWritePlatformServiceJpaRepositoryImpl implements GLJo
GLJournalEntry reversalJournalEntry;
String reversalComment = "Reversal entry for Journal Entry with Entry Id :" + journalEntry.getId() + " and transaction Id "
+ transactionId;
if (journalEntry.getType().equalsIgnoreCase(JOURNAL_ENTRY_TYPE.DEBIT.toString())) {
if (journalEntry.isDebitEntry()) {
reversalJournalEntry = GLJournalEntry.createNew(journalEntry.getOffice(), journalEntry.getGlAccount(),
reversalTransactionId, false, journalEntry.getEntryDate(), JOURNAL_ENTRY_TYPE.CREDIT.toString(),
journalEntry.getAmount(), reversalComment, null, null);
reversalTransactionId, false, journalEntry.getEntryDate(), JournalEntryType.CREDIT, journalEntry.getAmount(),
reversalComment, null, null);
} else {
reversalJournalEntry = GLJournalEntry.createNew(journalEntry.getOffice(), journalEntry.getGlAccount(),
reversalTransactionId, false, journalEntry.getEntryDate(), JOURNAL_ENTRY_TYPE.DEBIT.toString(),
journalEntry.getAmount(), reversalComment, null, null);
reversalTransactionId, false, journalEntry.getEntryDate(), JournalEntryType.DEBIT, journalEntry.getAmount(),
reversalComment, null, null);
}
// save the reversal entry
this.glJournalEntryRepository.saveAndFlush(reversalJournalEntry);
@@ -267,21 +267,21 @@ public class GLJournalEntryWritePlatformServiceJpaRepositoryImpl implements GLJo
private GLAccount getLinkedFinAccountForLoanProduct(Long loanProductId, CASH_ACCOUNTS_FOR_LOAN finAccountType) {
ProductToGLAccountMapping accountMapping = accountMappingRepository.findByProductIdAndProductTypeAndFinancialAccountType(
loanProductId, PORTFOLIO_PRODUCT_TYPE.LOAN.getValue(), finAccountType.getValue());
loanProductId, PortfolioProductType.LOAN.getValue(), finAccountType.getValue());
return accountMapping.getGlAccount();
}
private void createCreditJournalEntryForLoanProduct(Office office, GLAccount account, Long loanId, String transactionId,
Date entryDate, BigDecimal amount) {
GLJournalEntry journalEntry = GLJournalEntry.createNew(office, account, transactionId, true, entryDate,
JOURNAL_ENTRY_TYPE.CREDIT.toString(), amount, null, PORTFOLIO_PRODUCT_TYPE.LOAN.toString(), loanId);
GLJournalEntry journalEntry = GLJournalEntry.createNew(office, account, transactionId, true, entryDate, JournalEntryType.CREDIT,
amount, null, PortfolioProductType.LOAN.toString(), loanId);
glJournalEntryRepository.saveAndFlush(journalEntry);
}
private void createDebitJournalEntryForLoanProduct(Office office, GLAccount account, Long loanId, String transactionId, Date entryDate,
BigDecimal amount) {
GLJournalEntry journalEntry = GLJournalEntry.createNew(office, account, transactionId, true, entryDate,
JOURNAL_ENTRY_TYPE.DEBIT.toString(), amount, null, PORTFOLIO_PRODUCT_TYPE.LOAN.toString(), loanId);
GLJournalEntry journalEntry = GLJournalEntry.createNew(office, account, transactionId, true, entryDate, JournalEntryType.DEBIT,
amount, null, PortfolioProductType.LOAN.toString(), loanId);
glJournalEntryRepository.saveAndFlush(journalEntry);
}
@@ -336,7 +336,7 @@ public class GLJournalEntryWritePlatformServiceJpaRepositoryImpl implements GLJo
* @param transactionId
*/
private void saveAllDebitOrCreditEntries(GLJournalEntryCommand command, final Office office, Date entryDate,
SingleDebitOrCreditEntryCommand[] singleDebitOrCreditEntryCommands, String transactionId, JOURNAL_ENTRY_TYPE type) {
SingleDebitOrCreditEntryCommand[] singleDebitOrCreditEntryCommands, String transactionId, JournalEntryType type) {
for (SingleDebitOrCreditEntryCommand singleDebitOrCreditEntryCommand : singleDebitOrCreditEntryCommands) {
GLAccount glAccount = glAccountRepository.findOne(singleDebitOrCreditEntryCommand.getGlAccountId());
if (glAccount == null) { throw new GLAccountNotFoundException(singleDebitOrCreditEntryCommand.getGlAccountId()); }
@@ -356,7 +356,7 @@ public class GLJournalEntryWritePlatformServiceJpaRepositoryImpl implements GLJo
if (!StringUtils.isBlank(singleDebitOrCreditEntryCommand.getComments())) {
comments = singleDebitOrCreditEntryCommand.getComments();
}
GLJournalEntry glJournalEntry = GLJournalEntry.createNew(office, glAccount, transactionId, false, entryDate, type.toString(),
GLJournalEntry glJournalEntry = GLJournalEntry.createNew(office, glAccount, transactionId, false, entryDate, type,
singleDebitOrCreditEntryCommand.getAmount(), comments, null, null);
glJournalEntryRepository.saveAndFlush(glJournalEntry);
}
@@ -4,13 +4,12 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.mifosplatform.accounting.AccountingConstants;
import org.mifosplatform.accounting.AccountingConstants.ACCRUAL_ACCOUNTS_FOR_LOAN;
import org.mifosplatform.accounting.AccountingConstants.CASH_ACCOUNTS_FOR_LOAN;
import org.mifosplatform.accounting.AccountingConstants.LOAN_PRODUCT_ACCOUNTING_PARAMS;
import org.mifosplatform.accounting.AccountingConstants.PORTFOLIO_PRODUCT_TYPE;
import org.mifosplatform.accounting.domain.GLAccount;
import org.mifosplatform.accounting.domain.GLAccountRepository;
import org.mifosplatform.accounting.domain.PortfolioProductType;
import org.mifosplatform.accounting.domain.ProductToGLAccountMapping;
import org.mifosplatform.accounting.domain.ProductToGLAccountMappingRepository;
import org.mifosplatform.accounting.exceptions.GLAccountNotFoundException;
@@ -181,7 +180,7 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
GLAccount glAccount = accountRepository.findOne(glAccountId);
if (glAccount == null) { throw new GLAccountNotFoundException(glAccountId); }
ProductToGLAccountMapping accountMapping = new ProductToGLAccountMapping(glAccount, productId,
AccountingConstants.PORTFOLIO_PRODUCT_TYPE.LOAN.getValue(), accountTypeId);
PortfolioProductType.LOAN.getValue(), accountTypeId);
accountMappingRepository.save(accountMapping);
}
@@ -189,8 +188,8 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
String accountParamValue, Map<String, Object> changes) {
// get the existing product
ProductToGLAccountMapping accountMapping = accountMappingRepository.findByProductIdAndProductTypeAndFinancialAccountType(productId,
PORTFOLIO_PRODUCT_TYPE.LOAN.getValue(), accountTypeId);
if (accountMapping == null) { throw new ProductToGLAccountMappingNotFoundException(PORTFOLIO_PRODUCT_TYPE.LOAN, productId,
PortfolioProductType.LOAN.getValue(), accountTypeId);
if (accountMapping == null) { throw new ProductToGLAccountMappingNotFoundException(PortfolioProductType.LOAN, productId,
accountTypeName); }
if (accountMapping.getGlAccount().getId() != glAccountId) {
GLAccount glAccount = accountRepository.findOne(glAccountId);
@@ -204,7 +203,7 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
@Override
public void deleteLoanProductToGLAccountMapping(Long loanProductId) {
List<ProductToGLAccountMapping> productToGLAccountMappings = accountMappingRepository.findByProductIdAndProductType(loanProductId,
PORTFOLIO_PRODUCT_TYPE.LOAN.getValue());
PortfolioProductType.LOAN.getValue());
if (productToGLAccountMappings != null && productToGLAccountMappings.size() > 0) {
accountMappingRepository.deleteInBatch(productToGLAccountMappings);
}
@@ -132,6 +132,33 @@ public class JsonParserHelper {
}
return value;
}
/** Method used to extract integers from unformatted strings.
* Ex: "1" , "100002" etc
*
* Please note that this method does not support extracting Integers from locale
* specific formatted strings Ex "1,000" etc
*
* @param parameterName
* @param element
* @param parametersPassedInRequest
* @return
*/
public Integer extractIntegerFromUnFormattedStringNamed(final String parameterName, final JsonElement element, final Set<String> parametersPassedInRequest) {
Integer intValue = null;
if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) {
parametersPassedInRequest.add(parameterName);
JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
final String stringValue = primitive.getAsString();
if (StringUtils.isNotBlank(stringValue)) {
intValue = Integer.valueOf(stringValue);
}
}
}
return intValue;
}
public String extractDateFormatParameter(final JsonObject element) {
String value = null;
@@ -17,16 +17,13 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.mifosplatform.commands.domain.CommandWrapper;
import org.mifosplatform.commands.service.CommandWrapperBuilder;
import org.mifosplatform.accounting.AccountingConstants.GL_ACCOUNT_CLASSIFICATION;
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;
import org.mifosplatform.accounting.service.ProductToGLAccountMappingReadPlatformService;
import org.mifosplatform.commands.domain.CommandWrapper;
import org.mifosplatform.commands.service.CommandWrapperBuilder;
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
@@ -194,9 +191,9 @@ public class LoanProductsApiResource {
final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions = this.dropdownReadPlatformService
.retreiveTransactionProcessingStrategies();
final List<GLAccountData> assetAccountOptions = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GL_ACCOUNT_CLASSIFICATION.ASSET);
final List<GLAccountData> incomeAccountOptions = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GL_ACCOUNT_CLASSIFICATION.INCOME);;
final List<GLAccountData> expenseAccountOptions = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GL_ACCOUNT_CLASSIFICATION.EXPENSE);;
final List<GLAccountData> assetAccountOptions = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GLAccountType.ASSET);
final List<GLAccountData> incomeAccountOptions = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GLAccountType.INCOME);;
final List<GLAccountData> expenseAccountOptions = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GLAccountType.EXPENSE);;
return new LoanProductData(productData, chargeOptions, currencyOptions, amortizationTypeOptions, interestTypeOptions,
interestCalculationPeriodTypeOptions, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions,