Merge pull request #255 from vishwasbabu/mifosx-286

removing autoposting code
This commit is contained in:
Vishwas Babu A J
2013-05-03 04:45:27 -07:00
18 changed files with 3 additions and 1111 deletions
+3
View File
@@ -0,0 +1,3 @@
drop table `acc_auto_posting`;
@@ -1,139 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.api;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.mifosplatform.accounting.closure.data.GLClosureData;
import org.mifosplatform.accounting.closure.service.GLClosureReadPlatformService;
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;
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.office.service.OfficeReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/autopostingrules")
@Component
@Scope("singleton")
public class AutoPostingApiResource {
private static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "officeId", "officeName",
"closingDate", "deleted", "createdDate", "lastUpdatedDate", "createdByUserId", "createdByUsername", "lastUpdatedByUserId",
"lastUpdatedByUsername"));
private final String resourceNameForPermission = "GLCLOSURE";
private final GLClosureReadPlatformService glClosureReadPlatformService;
private final OfficeReadPlatformService officeReadPlatformService;
private final DefaultToApiJsonSerializer<GLClosureData> apiJsonSerializerService;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PlatformSecurityContext context;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@Autowired
public AutoPostingApiResource(final PlatformSecurityContext context, final GLClosureReadPlatformService glClosureReadPlatformService,
final DefaultToApiJsonSerializer<GLClosureData> toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
final OfficeReadPlatformService officeReadPlatformService) {
this.context = context;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
this.apiJsonSerializerService = toApiJsonSerializer;
this.glClosureReadPlatformService = glClosureReadPlatformService;
this.officeReadPlatformService = officeReadPlatformService;
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllClosures(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
final List<GLClosureData> glClosureDatas = this.glClosureReadPlatformService.retrieveAllGLClosures(officeId);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.apiJsonSerializerService.serialize(settings, glClosureDatas, RESPONSE_DATA_PARAMETERS);
}
@GET
@Path("{glClosureId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retreiveClosure(@PathParam("glClosureId") final Long glClosureId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
final GLClosureData glClosureData = this.glClosureReadPlatformService.retrieveGLClosureById(glClosureId);
if (settings.isTemplate()) {
// glClosureData.setAllowedOffices(new
// ArrayList<OfficeLookup>(this.officeReadPlatformService.retrieveAllOfficesForLookup()));
}
return this.apiJsonSerializerService.serialize(settings, glClosureData, RESPONSE_DATA_PARAMETERS);
}
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createGLClosure(final String jsonRequestBody) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createGLClosure().withJson(jsonRequestBody).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.apiJsonSerializerService.serialize(result);
}
@PUT
@Path("{glClosureId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateGLClosure(@PathParam("glClosureId") final Long glClosureId, final String jsonRequestBody) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateGLClosure(glClosureId).withJson(jsonRequestBody).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.apiJsonSerializerService.serialize(result);
}
@DELETE
@Path("{glClosureId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteGLClosure(@PathParam("glClosureId") final Long glClosureId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteGLClosure(glClosureId).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.apiJsonSerializerService.serialize(result);
}
}
@@ -1,64 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.command;
import java.util.ArrayList;
import java.util.List;
import org.joda.time.LocalDate;
import org.mifosplatform.accounting.closure.api.GLClosureJsonInputParams;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
/**
* Immutable command for adding an accounting closure
*/
public class AutoPostingCommand {
@SuppressWarnings("unused")
private final Long id;
private final Long officeId;
private final LocalDate closingDate;
private final String comments;
public AutoPostingCommand(final Long id, final Long officeId, final LocalDate closingDate, final String comments) {
this.id = id;
this.officeId = officeId;
this.closingDate = closingDate;
this.comments = comments;
}
public void validateForCreate() {
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("GLClosure");
baseDataValidator.reset().parameter(GLClosureJsonInputParams.CLOSING_DATE.getValue()).value(this.closingDate).notBlank();
baseDataValidator.reset().parameter(GLClosureJsonInputParams.OFFICE_ID.getValue()).value(this.officeId).notNull()
.integerGreaterThanZero();
baseDataValidator.reset().parameter(GLClosureJsonInputParams.COMMENTS.getValue()).value(this.comments).ignoreIfNull()
.notExceedingLengthOf(500);
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
public void validateForUpdate() {
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("GLClosure");
baseDataValidator.reset().parameter(GLClosureJsonInputParams.COMMENTS.getValue()).value(this.comments).ignoreIfNull()
.notExceedingLengthOf(500);
baseDataValidator.reset().anyOfNotNull(this.comments);
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -1,113 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.data;
import java.util.ArrayList;
import java.util.List;
import org.mifosplatform.accounting.rule.data.AccountingRuleData;
import org.mifosplatform.infrastructure.codes.data.CodeData;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.mifosplatform.portfolio.savings.data.SavingsProductData;
/**
* Immutable object representing a Auto posting rule
*
* Note: no getter/setters required as google-gson will produce json from fields
* of object.
*/
public class AutoPostingData {
@SuppressWarnings("unused")
private final Long id;
@SuppressWarnings("unused")
private final String name;
@SuppressWarnings("unused")
private String description;
@SuppressWarnings("unused")
private OfficeData officeData;
@SuppressWarnings("unused")
private EnumOptionData productType;
@SuppressWarnings("unused")
private LoanProductData loanProductData;
@SuppressWarnings("unused")
private SavingsProductData savingProductData;
@SuppressWarnings("unused")
private ChargeData charge;
@SuppressWarnings("unused")
private CodeData event;
@SuppressWarnings("unused")
private CodeValueData eventAttribute;
@SuppressWarnings("unused")
private AccountingRuleData accountingRule;
// template
@SuppressWarnings("unused")
private List<EnumOptionData> allowedProductTypes = new ArrayList<EnumOptionData>();
@SuppressWarnings("unused")
private List<OfficeData> allowedOffices = new ArrayList<OfficeData>();
@SuppressWarnings("unused")
private List<SavingsProductData> allowedSavingProducts = new ArrayList<SavingsProductData>();
@SuppressWarnings("unused")
private List<LoanProductData> allowedLoanProducts = new ArrayList<LoanProductData>();
@SuppressWarnings("unused")
private List<CodeValue> allowedEventAttributes = new ArrayList<CodeValue>();
public AutoPostingData(Long id, String name, String description, OfficeData officeData, EnumOptionData productType,
LoanProductData loanProductData, SavingsProductData savingsProductData, ChargeData charge, CodeData event,
CodeValueData eventAttribute, AccountingRuleData accountingRule) {
this(id, name, description, officeData, productType, loanProductData, savingsProductData, charge, event, eventAttribute,
accountingRule, null, null, null, null, null);
}
private AutoPostingData(Long id, String name, String description, OfficeData officeData, EnumOptionData productType,
LoanProductData loanProductData, SavingsProductData savingsProductData, ChargeData charge, CodeData event,
CodeValueData eventAttribute, AccountingRuleData accountingRule, List<EnumOptionData> allowedProductTypes,
List<OfficeData> allowedOffices, List<SavingsProductData> allowedSavingProducts, List<LoanProductData> allowedLoanProducts,
List<CodeValue> allowedEventAttributes) {
this.id = id;
this.name = name;
this.description = description;
this.officeData = officeData;
this.productType = productType;
this.loanProductData = loanProductData;
this.savingProductData = savingsProductData;
this.charge = charge;
this.event = event;
this.eventAttribute = eventAttribute;
this.accountingRule = accountingRule;
this.allowedProductTypes = allowedProductTypes;
this.allowedOffices = allowedOffices;
this.allowedSavingProducts = allowedSavingProducts;
this.allowedLoanProducts = allowedLoanProducts;
this.allowedEventAttributes = allowedEventAttributes;
}
public void setAllowedProductTypes(List<EnumOptionData> allowedProductTypes) {
this.allowedProductTypes = allowedProductTypes;
}
public void setAllowedOffices(List<OfficeData> allowedOffices) {
this.allowedOffices = allowedOffices;
}
public void setAllowedSavingProducts(List<SavingsProductData> allowedSavingProducts) {
this.allowedSavingProducts = allowedSavingProducts;
}
public void setAllowedLoanProducts(List<LoanProductData> allowedLoanProducts) {
this.allowedLoanProducts = allowedLoanProducts;
}
public void setAllowedEventAttributes(List<CodeValue> allowedEventAttributes) {
this.allowedEventAttributes = allowedEventAttributes;
}
}
@@ -1,197 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.domain;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.mifosplatform.accounting.autoposting.api.AutoPostingJsonInputParams;
import org.mifosplatform.accounting.rule.domain.AccountingRule;
import org.mifosplatform.infrastructure.codes.domain.Code;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.portfolio.charge.domain.Charge;
import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity
@Table(name = "acc_auto_posting", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "auto_posting_name_unique") })
public class AutoPosting extends AbstractPersistable<Long> {
@Column(name = "name", nullable = true, length = 100)
private String name;
@Column(name = "description", nullable = true, length = 500)
private String description;
@ManyToOne
@JoinColumn(name = "office_id", nullable = true)
private Office office;
@Column(name = "type_enum", nullable = false)
private Integer productTypeEnum;
@Column(name = "product_id", nullable = true)
private Long productId;
@ManyToOne
@JoinColumn(name = "charge_id", nullable = true)
private Charge charge;
@ManyToOne
@JoinColumn(name = "event", nullable = false)
private Code event;
@ManyToOne
@JoinColumn(name = "event_attribute", nullable = true)
private CodeValue eventAttribute;
@ManyToOne
@JoinColumn(name = "accounting_rule_id", nullable = true)
private AccountingRule accountingRule;
protected AutoPosting() {
//
}
private AutoPosting(Office office, Charge charge, Code event, CodeValue eventAttribute, AccountingRule accountingRule, String name,
String description, Integer productTypeEnum, Long productId) {
this.name = name;
this.description = description;
this.office = office;
this.productTypeEnum = productTypeEnum;
this.productId = productId;
this.charge = charge;
this.event = event;
this.eventAttribute = eventAttribute;
this.accountingRule = accountingRule;
}
public static AutoPosting fromJson(Office office, Charge charge, Code event, CodeValue eventAttribute, AccountingRule accountingRule,
JsonCommand command) {
final String name = command.stringValueOfParameterNamed(AutoPostingJsonInputParams.NAME.getValue());
final String description = command.stringValueOfParameterNamed(AutoPostingJsonInputParams.DESCRIPTION.getValue());
final Integer productTypeEnum = command.integerValueSansLocaleOfParameterNamed(AutoPostingJsonInputParams.PRODUCT_TYPE_ENUM
.getValue());
final Long productId = command.longValueOfParameterNamed(AutoPostingJsonInputParams.PRODUCT_ID.getValue());
return new AutoPosting(office, charge, event, eventAttribute, accountingRule, name, description, productTypeEnum, productId);
}
public Map<String, Object> update(final JsonCommand command) {
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(5);
handlePropertyUpdate(command, actualChanges, AutoPostingJsonInputParams.OFFICE_ID.getValue(), 0L);
handlePropertyUpdate(command, actualChanges, AutoPostingJsonInputParams.CHARGE_ID.getValue(), 0L);
handlePropertyUpdate(command, actualChanges, AutoPostingJsonInputParams.EVENT_ID.getValue(), 0L);
handlePropertyUpdate(command, actualChanges, AutoPostingJsonInputParams.EVENT_ATTRIBUTE_ID.getValue(), 0L);
handlePropertyUpdate(command, actualChanges, AutoPostingJsonInputParams.ACCOUNTING_RULE_ID.getValue(), 0L);
handlePropertyUpdate(command, actualChanges, AutoPostingJsonInputParams.NAME.getValue(), this.name);
handlePropertyUpdate(command, actualChanges, AutoPostingJsonInputParams.DESCRIPTION.getValue(), this.description);
handlePropertyUpdate(command, actualChanges, AutoPostingJsonInputParams.PRODUCT_TYPE_ENUM.getValue(), this.productTypeEnum, true);
handlePropertyUpdate(command, actualChanges, AutoPostingJsonInputParams.PRODUCT_ID.getValue(), this.productId);
return actualChanges;
}
private void handlePropertyUpdate(final JsonCommand command, final Map<String, Object> actualChanges, final String paramName,
final String propertyToBeUpdated) {
if (command.isChangeInStringParameterNamed(paramName, propertyToBeUpdated)) {
final String newValue = command.stringValueOfParameterNamed(paramName);
actualChanges.put(paramName, newValue);
// now update actual property
if (paramName.equals(AutoPostingJsonInputParams.DESCRIPTION.getValue())) {
this.description = newValue;
} else if (paramName.equals(AutoPostingJsonInputParams.NAME.getValue())) {
this.name = newValue;
}
}
}
private void handlePropertyUpdate(final JsonCommand command, final Map<String, Object> actualChanges, final String paramName,
Integer propertyToBeUpdated, boolean sansLocale) {
if (command.isChangeInIntegerParameterNamed(paramName, propertyToBeUpdated)) {
Integer newValue = null;
if (sansLocale) {
newValue = command.integerValueSansLocaleOfParameterNamed(paramName);
} else {
newValue = command.integerValueOfParameterNamed(paramName);
}
actualChanges.put(paramName, newValue);
propertyToBeUpdated = newValue;
// now update actual property
if (paramName.equals(AutoPostingJsonInputParams.PRODUCT_TYPE_ENUM.getValue())) {
this.productTypeEnum = newValue;
}
}
}
private void handlePropertyUpdate(final JsonCommand command, final Map<String, Object> actualChanges, final String paramName,
final Long propertyToBeUpdated) {
if (command.isChangeInLongParameterNamed(paramName, propertyToBeUpdated)) {
final Long newValue = command.longValueOfParameterNamed(paramName);
actualChanges.put(paramName, newValue);
// now update actual property
if (paramName.equals(AutoPostingJsonInputParams.OFFICE_ID.getValue())) {
// do nothing as this is a nested property
} else if (paramName.equals(AutoPostingJsonInputParams.CHARGE_ID.getValue())) {
// do nothing as this is a nested property
} else if (paramName.equals(AutoPostingJsonInputParams.EVENT_ID.getValue())) {
// do nothing as this is a nested property
} else if (paramName.equals(AutoPostingJsonInputParams.EVENT_ATTRIBUTE_ID.getValue())) {
// do nothing as this is a nested property
} else if (paramName.equals(AutoPostingJsonInputParams.ACCOUNTING_RULE_ID.getValue())) {
// do nothing as this is a nested property
}
}
}
public Office getOffice() {
return this.office;
}
public void setOffice(Office office) {
this.office = office;
}
public Charge getCharge() {
return this.charge;
}
public void setCharge(Charge charge) {
this.charge = charge;
}
public Code getEvent() {
return this.event;
}
public void setEvent(Code event) {
this.event = event;
}
public CodeValue getEventAttribute() {
return this.eventAttribute;
}
public void setEventAttribute(CodeValue eventAttribute) {
this.eventAttribute = eventAttribute;
}
public AccountingRule getAccountingRule() {
return this.accountingRule;
}
public void setAccountingRule(AccountingRule accountingRule) {
this.accountingRule = accountingRule;
}
}
@@ -1,17 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface AutoPostingRepository extends JpaRepository<AutoPosting, Long>, JpaSpecificationExecutor<AutoPosting> {
@Query("from GLClosure closure where closure.closingDate = (select max(closure1.closingDate) from GLClosure closure1 where closure1.office.id=:officeId) and closure.office.id= :officeId")
AutoPosting getLatestGLClosureByBranch(@Param("officeId") Long officeId);
}
@@ -1,19 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
/**
* A {@link RuntimeException} thrown when a Auto posting rule is already present
*/
public class AutoPostingDuplicateException extends AbstractPlatformDomainRuleException {
public AutoPostingDuplicateException(final String autoPostingName) {
super("error.msg.auto.posting.duplicate", "An autoposting rule with the name " + autoPostingName + " already exists",
autoPostingName);
}
}
@@ -1,21 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.exception;
import java.util.Date;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
/**
* A {@link RuntimeException} thrown when a GL Closure Delte command is invalid
*/
public class AutoPostingInvalidDeleteException extends AbstractPlatformDomainRuleException {
public AutoPostingInvalidDeleteException(final Long officeId, final String officeName, final Date latestclosureDate) {
super("error.msg.glclosure.invalid.delete", "The latest closure for office with Id " + officeId + " and name " + officeName
+ " is on " + latestclosureDate.toString() + ", please delete this closure first", latestclosureDate);
}
}
@@ -1,39 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.exception;
import java.util.Date;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
/**
* A {@link RuntimeException} thrown when a GL Closure is Invalid
*/
public class AutoPostingInvalidException extends AbstractPlatformDomainRuleException {
/*** enum of reasons for invalid Accounting Closure **/
public static enum GL_CLOSURE_INVALID_REASON {
FUTURE_DATE, ACCOUNTING_CLOSED;
public String errorMessage() {
if (name().toString().equalsIgnoreCase("FUTURE_DATE")) {
return "Accounting closures cannot be made for a future date";
} else if (name().toString().equalsIgnoreCase("ACCOUNTING_CLOSED")) { return "Accounting Closure for this branch has already been defined for a greater date"; }
return name().toString();
}
public String errorCode() {
if (name().toString().equalsIgnoreCase("FUTURE_DATE")) {
return "error.msg.glclosure.invalid.future.date";
} else if (name().toString().equalsIgnoreCase("ACCOUNTING_CLOSED")) { return "error.msg.glclosure.invalid.accounting.closed"; }
return name().toString();
}
}
public AutoPostingInvalidException(final GL_CLOSURE_INVALID_REASON reason, final Date date) {
super(reason.errorCode(), reason.errorMessage(), date);
}
}
@@ -1,18 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
/**
* A {@link RuntimeException} thrown when Auto posting rule is not found.
*/
public class AutoPostingNotFoundException extends AbstractPlatformResourceNotFoundException {
public AutoPostingNotFoundException(final Long id) {
super("error.msg.autoposting.id.invalid", "Autoposting rule with identifier " + id + " does not exist", id);
}
}
@@ -1,32 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.handler;
import org.mifosplatform.accounting.autoposting.service.AutoPostingWritePlatformService;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class CreateAutoPostingCommandHandler implements NewCommandSourceHandler {
private final AutoPostingWritePlatformService writePlatformService;
@Autowired
public CreateAutoPostingCommandHandler(final AutoPostingWritePlatformService writePlatformService) {
this.writePlatformService = writePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.createAutoPostingRule(command);
}
}
@@ -1,31 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.handler;
import org.mifosplatform.accounting.autoposting.service.AutoPostingWritePlatformService;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class DeleteAutoPostingCommandHandler implements NewCommandSourceHandler {
private final AutoPostingWritePlatformService writePlatformService;
@Autowired
public DeleteAutoPostingCommandHandler(final AutoPostingWritePlatformService writePlatformService) {
this.writePlatformService = writePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.deleteAutoPostingRule(command.entityId());
}
}
@@ -1,31 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.handler;
import org.mifosplatform.accounting.autoposting.service.AutoPostingWritePlatformService;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UpdateAutoPostingCommandHandler implements NewCommandSourceHandler {
private final AutoPostingWritePlatformService writePlatformService;
@Autowired
public UpdateAutoPostingCommandHandler(final AutoPostingWritePlatformService writePlatformService) {
this.writePlatformService = writePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.updateAutoPostingRule(command.entityId(), command);
}
}
@@ -1,59 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.serialization;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.accounting.closure.api.GLClosureJsonInputParams;
import org.mifosplatform.accounting.closure.command.GLClosureCommand;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.portfolio.loanaccount.guarantor.command.GuarantorCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
/**
* Implementation of {@link FromApiJsonDeserializer} for
* {@link GuarantorCommand}'s.
*/
@Component
public final class AutoPostingCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer<GLClosureCommand> {
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public AutoPostingCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonfromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonfromApiJsonHelper;
}
@Override
public GLClosureCommand commandFromApiJson(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
final Set<String> supportedParameters = GLClosureJsonInputParams.getAllValues();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
final JsonElement element = this.fromApiJsonHelper.parse(json);
final Long id = this.fromApiJsonHelper.extractLongNamed(GLClosureJsonInputParams.ID.getValue(), element);
final Long officeId = this.fromApiJsonHelper.extractLongNamed(GLClosureJsonInputParams.OFFICE_ID.getValue(), element);
final String comments = this.fromApiJsonHelper.extractStringNamed(GLClosureJsonInputParams.COMMENTS.getValue(), element);
final LocalDate closingDate = this.fromApiJsonHelper.extractLocalDateNamed(GLClosureJsonInputParams.CLOSING_DATE.getValue(),
element);
return new GLClosureCommand(id, officeId, closingDate, comments);
}
}
@@ -1,18 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.service;
import java.util.List;
import org.mifosplatform.accounting.autoposting.data.AutoPostingData;
public interface AutoPostingReadPlatformService {
List<AutoPostingData> retrieveAllAutoPostingRules();
AutoPostingData retrieveAutoPostingRuleById(long autopostingId);
}
@@ -1,152 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.mifosplatform.accounting.autoposting.data.AutoPostingData;
import org.mifosplatform.accounting.closure.exception.GLClosureNotFoundException;
import org.mifosplatform.accounting.common.AccountingEnumerations;
import org.mifosplatform.accounting.producttoaccountmapping.domain.PortfolioProductType;
import org.mifosplatform.accounting.rule.data.AccountingRuleData;
import org.mifosplatform.infrastructure.codes.data.CodeData;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.mifosplatform.portfolio.savings.data.SavingsProductData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
public class AutoPostingReadPlatformServiceImpl implements AutoPostingReadPlatformService {
private final JdbcTemplate jdbcTemplate;
@Autowired
public AutoPostingReadPlatformServiceImpl(final TenantAwareRoutingDataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
private static final class AutoPostingMapper implements RowMapper<AutoPostingData> {
private final String schemaSql;
public AutoPostingMapper() {
final StringBuilder sqlBuilder = new StringBuilder(400);
sqlBuilder
.append("select autoposting.id as id, autoposting.name as name, autoposting.description as description,")
.append(" autoposting.office_id as officeId, office.name as officeName, autoposting.product_type_enum as productTypeEnum,")
.append(" autoposting.product_id as productId, autoposting.charge_id as chargeId, autoposting.event as event,")
.append(" autoposting.event_attribute as eventAttribute, autoposting.accounting_rule_id as accountingRuleId,")
.append(" savingsproduct.name as savingProductName, loanproduct.name as loanProductName,")
.append(" charge.name as chargeName, charge.is_penalty as isPenalty,")
.append(" event.code_name as eventName, eventAttribute.code_value as eventAttributeName")
.append(" accountingRule.debit_account_id as debitAccountId, accountingRule.credit_account_id as creditAccountId")
.append(" from acc_auto_posting autoposting left join m_office office on autoposting.office_id=office.id")
.append(" left join m_savings_product savingsproduct on autoposting.product_id=savingsproduct.id")
.append(" left join m_product_loan loanproduct on autoposting.product_id=loanproduct.id")
.append(" left join m_charge charge on autoposting.charge_id=charge.id")
.append(" left join m_code event on autoposting.event=event.id")
.append(" left join m_code_value eventAttribute on autoposting.event_attribute=eventAttribute.id")
.append(" left join acc_accounting_rule accountingRule on autoposting.accounting_rule_id= accountingRule.id");
this.schemaSql = sqlBuilder.toString();
}
public String schema() {
return this.schemaSql;
}
@Override
public AutoPostingData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final String name = rs.getString("name");
final String description = rs.getString("description");
final Long officeId = JdbcSupport.getLong(rs, "officeId");
final String officeName = rs.getString("officeName");
final int productTypeEnum = rs.getInt("productTypeEnum");
final Long productId = JdbcSupport.getLong(rs, "productId");
final Long chargeId = JdbcSupport.getLong(rs, "chargeId");
final Long accountingRuleId = JdbcSupport.getLong(rs, "accountingRuleId");
final Long eventId = JdbcSupport.getLong(rs, "eventId");
final Long eventAttributeId = JdbcSupport.getLong(rs, "eventAttributeId");
final Long debitAccountId = JdbcSupport.getLong(rs, "debitAccountId");
final Long creditAccountId = JdbcSupport.getLong(rs, "creditAccountId");
final String savingProductName = rs.getString("savingProductName");
final String loanProductName = rs.getString("loanProductName");
final String chargeName = rs.getString("chargeName");
final String eventName = rs.getString("eventName");
final String eventAttributeName = rs.getString("eventAttributeName");
final boolean chargeIsPenalty = rs.getBoolean("isPenalty");
OfficeData officeData = null;
if (officeId != null) {
officeData = OfficeData.dropdown(officeId, officeName, null);
}
SavingsProductData savingsProductData = null;
LoanProductData loanProductData = null;
PortfolioProductType portfolioProductType = PortfolioProductType.fromInt(productTypeEnum);
EnumOptionData productType = AccountingEnumerations.portfolioProductType(portfolioProductType);
if (portfolioProductType.isLoanProduct() && productId != null) {
savingsProductData = SavingsProductData.lookup(productId, savingProductName);
} else if (portfolioProductType.isSavingProduct() && productId != null) {
loanProductData = LoanProductData.lookup(productId, loanProductName);
}
ChargeData chargeData = null;
if (chargeId != null) {
chargeData = ChargeData.lookup(chargeId, chargeName, chargeIsPenalty);
}
CodeData event = CodeData.instance(eventId, eventName, true);
CodeValueData eventAttribute = null;
if (eventAttributeId != null) {
eventAttribute = CodeValueData.instance(eventAttributeId, eventAttributeName);
}
AccountingRuleData accountingRuleData = new AccountingRuleData(accountingRuleId, debitAccountId, creditAccountId);
return new AutoPostingData(id, name, description, officeData, productType, loanProductData, savingsProductData, chargeData,
event, eventAttribute, accountingRuleData);
}
}
@Override
public List<AutoPostingData> retrieveAllAutoPostingRules() {
final AutoPostingMapper rm = new AutoPostingMapper();
String sql = "select " + rm.schema();
return this.jdbcTemplate.query(sql, rm, new Object[] {});
}
@Override
public AutoPostingData retrieveAutoPostingRuleById(final long autopostingId) {
try {
final AutoPostingMapper rm = new AutoPostingMapper();
final String sql = "select " + rm.schema() + " and glClosure.id = ?";
final AutoPostingData autoPostingData = this.jdbcTemplate.queryForObject(sql, rm, new Object[] { autopostingId });
return autoPostingData;
} catch (final EmptyResultDataAccessException e) {
throw new GLClosureNotFoundException(autopostingId);
}
}
}
@@ -1,19 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.service;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
public interface AutoPostingWritePlatformService {
CommandProcessingResult createAutoPostingRule(JsonCommand command);
CommandProcessingResult updateAutoPostingRule(Long autoPostingId, JsonCommand command);
CommandProcessingResult deleteAutoPostingRule(Long autoPostingId);
}
@@ -1,142 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.accounting.autoposting.service;
import java.util.Date;
import java.util.Map;
import org.mifosplatform.accounting.autoposting.api.AutoPostingJsonInputParams;
import org.mifosplatform.accounting.autoposting.exception.AutoPostingDuplicateException;
import org.mifosplatform.accounting.closure.api.GLClosureJsonInputParams;
import org.mifosplatform.accounting.closure.command.GLClosureCommand;
import org.mifosplatform.accounting.closure.domain.GLClosure;
import org.mifosplatform.accounting.closure.domain.GLClosureRepository;
import org.mifosplatform.accounting.closure.exception.GLClosureInvalidDeleteException;
import org.mifosplatform.accounting.closure.exception.GLClosureInvalidException;
import org.mifosplatform.accounting.closure.exception.GLClosureInvalidException.GL_CLOSURE_INVALID_REASON;
import org.mifosplatform.accounting.closure.exception.GLClosureNotFoundException;
import org.mifosplatform.accounting.closure.serialization.GLClosureCommandFromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.office.domain.OfficeRepository;
import org.mifosplatform.organisation.office.exception.OfficeNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class AutoPostingWritePlatformServiceJpaRepositoryImpl implements AutoPostingWritePlatformService {
private final static Logger logger = LoggerFactory.getLogger(AutoPostingWritePlatformServiceJpaRepositoryImpl.class);
private final GLClosureRepository glClosureRepository;
private final OfficeRepository officeRepository;
private final GLClosureCommandFromApiJsonDeserializer fromApiJsonDeserializer;
@Autowired
public AutoPostingWritePlatformServiceJpaRepositoryImpl(final GLClosureRepository glClosureRepository,
final OfficeRepository officeRepository, final GLClosureCommandFromApiJsonDeserializer fromApiJsonDeserializer) {
this.glClosureRepository = glClosureRepository;
this.officeRepository = officeRepository;
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
}
@Transactional
@Override
public CommandProcessingResult createAutoPostingRule(final JsonCommand command) {
try {
final GLClosureCommand closureCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json());
closureCommand.validateForCreate();
// check office is valid
final Long officeId = command.longValueOfParameterNamed(GLClosureJsonInputParams.OFFICE_ID.getValue());
final Office office = this.officeRepository.findOne(officeId);
if (office == null) { throw new OfficeNotFoundException(officeId); }
// TODO: Get Tenant specific date
// ensure closure date is not in the future
final Date todaysDate = new Date();
final Date closureDate = command.DateValueOfParameterNamed(GLClosureJsonInputParams.CLOSING_DATE.getValue());
if (closureDate.after(todaysDate)) { throw new GLClosureInvalidException(GL_CLOSURE_INVALID_REASON.FUTURE_DATE, closureDate); }
// shouldn't be before an existing accounting closure
final GLClosure latestGLClosure = this.glClosureRepository.getLatestGLClosureByBranch(officeId);
if (latestGLClosure != null) {
if (latestGLClosure.getClosingDate().after(closureDate)) { throw new GLClosureInvalidException(
GL_CLOSURE_INVALID_REASON.ACCOUNTING_CLOSED, latestGLClosure.getClosingDate()); }
}
final GLClosure glClosure = GLClosure.fromJson(office, command);
this.glClosureRepository.saveAndFlush(glClosure);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(officeId)
.withEntityId(glClosure.getId()).build();
} catch (final DataIntegrityViolationException dve) {
handleAutoPostingIntegrityIssues(command, dve);
return CommandProcessingResult.empty();
}
}
@Transactional
@Override
public CommandProcessingResult updateAutoPostingRule(final Long autoPostingId, final JsonCommand command) {
final GLClosureCommand closureCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json());
closureCommand.validateForUpdate();
// is the glClosure valid
final GLClosure glClosure = this.glClosureRepository.findOne(autoPostingId);
if (glClosure == null) { throw new GLClosureNotFoundException(autoPostingId); }
final Map<String, Object> changesOnly = glClosure.update(command);
if (!changesOnly.isEmpty()) {
this.glClosureRepository.saveAndFlush(glClosure);
}
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(glClosure.getOffice().getId())
.withEntityId(glClosure.getId()).with(changesOnly).build();
}
@Transactional
@Override
public CommandProcessingResult deleteAutoPostingRule(final Long autoPostingId) {
final GLClosure glClosure = this.glClosureRepository.findOne(autoPostingId);
if (glClosure == null) { throw new GLClosureNotFoundException(autoPostingId); }
/**
* check if any closures are present for this branch at a later date
* than this closure date
**/
final Date closureDate = glClosure.getClosingDate();
final GLClosure latestGLClosure = this.glClosureRepository.getLatestGLClosureByBranch(glClosure.getOffice().getId());
if (latestGLClosure.getClosingDate().after(closureDate)) { throw new GLClosureInvalidDeleteException(latestGLClosure.getOffice()
.getId(), latestGLClosure.getOffice().getName(), latestGLClosure.getClosingDate()); }
this.glClosureRepository.delete(glClosure);
return new CommandProcessingResultBuilder().withOfficeId(glClosure.getOffice().getId()).withEntityId(glClosure.getId()).build();
}
/**
* @param command
* @param dve
*/
private void handleAutoPostingIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) {
final Throwable realCause = dve.getMostSpecificCause();
if (realCause.getMessage().contains("auto_posting_name_unique")) { throw new AutoPostingDuplicateException(
command.stringValueOfParameterNamed(AutoPostingJsonInputParams.NAME.getValue())); }
logger.error(dve.getMessage(), dve);
throw new PlatformDataIntegrityException("error.msg.glClosure.unknown.data.integrity.issue",
"Unknown data integrity issue with resource GL Closure: " + realCause.getMessage());
}
}