Generate center/group collection sheet using meeting calendar dates

This commit is contained in:
ashok-conflux
2013-05-09 19:04:56 +05:30
parent 57791b8f37
commit e14a8bbe1f
17 changed files with 338 additions and 165 deletions
@@ -0,0 +1,3 @@
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'SAVECOLLECTIONSHEET_GROUP', 'GROUP', 'SAVECOLLECTIONSHEET', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'SAVECOLLECTIONSHEET_CENTER', 'CENTER', 'SAVECOLLECTIONSHEET', 0);
@@ -484,6 +484,10 @@ public class CommandWrapper {
public boolean isGroupResource() {
return this.entityName.equalsIgnoreCase("GROUP");
}
public boolean isSaveGroupCollectionSheet(){
return this.entityName.equalsIgnoreCase("GROUP") && this.actionName.equalsIgnoreCase("SAVECOLLECTIONSHEET");
}
public boolean isCollectionSheetResource() {
return this.entityName.equals("COLLECTIONSHEET");
@@ -493,6 +497,10 @@ public class CommandWrapper {
return this.entityName.equalsIgnoreCase("CENTER");
}
public boolean isSaveCenterCollectionSheet(){
return this.entityName.equalsIgnoreCase("CENTER") && this.actionName.equalsIgnoreCase("SAVECOLLECTIONSHEET");
}
public boolean isReportResource() {
return this.entityName.equalsIgnoreCase("REPORT");
}
@@ -847,7 +847,16 @@ public class CommandWrapperBuilder {
this.href = "/groups/" + groupId + "?command=activate";
return this;
}
public CommandWrapperBuilder saveGroupCollectionSheet(final Long groupId) {
this.actionName = "SAVECOLLECTIONSHEET";
this.entityName = "GROUP";
this.entityId = groupId;
this.groupId = groupId;
this.href = "/groups/" + groupId + "?command=saveCollectionSheet";
return this;
}
public CommandWrapperBuilder deleteGroup(final Long groupId) {
this.actionName = "DELETE";
this.entityName = "GROUP";
@@ -951,6 +960,14 @@ public class CommandWrapperBuilder {
return this;
}
public CommandWrapperBuilder saveCenterCollectionSheet(final Long centerId) {
this.actionName = "SAVECOLLECTIONSHEET";
this.entityName = "CENTER";
this.entityId = centerId;
this.href = "/centers/" + centerId + "?command=saveCollectionSheet";
return this;
}
public CommandWrapperBuilder createAccountingRule() {
this.actionName = "CREATE";
this.entityName = "ACCOUNTINGRULE";
@@ -404,6 +404,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
handler = applicationContext.getBean("associateClientsToGroupCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isDisassociateClients()) {
handler = applicationContext.getBean("disassociateClientsFromGroupCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isSaveGroupCollectionSheet()) {
handler = applicationContext.getBean("saveGroupCollectionSheetCommandHandler", NewCommandSourceHandler.class);
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
@@ -416,6 +418,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
handler = applicationContext.getBean("deleteCenterCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isCenterActivation()) {
handler = applicationContext.getBean("activateCenterCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isSaveCenterCollectionSheet()) {
handler = applicationContext.getBean("saveCenterCollectionSheetCommandHandler", NewCommandSourceHandler.class);
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
@@ -1,128 +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.portfolio.collectionsheet.api;
import java.util.ArrayList;
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.GET;
import javax.ws.rs.POST;
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.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
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.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer;
import org.mifosplatform.infrastructure.core.service.DateUtils;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetData;
import org.mifosplatform.portfolio.collectionsheet.service.CollectionSheetReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
/*
* At present API supports groups/{groupId}
* Future version supports staffs/{staffId}
* Future version supports offices/{officeId}
*/
@Path("/groups/{groupId}/collectionsheet")
@Component
@Scope("singleton")
public class CollectionSheetApiResource {
private final Set<String> COLLECTIONSHEET_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("dueDate", "loanProducts", "groups"));
/*
* dueDate format is ISO 8601 Calendar Date (YYYYMMDD)
*/
private final String datePattern = "yyyyMMdd";
private final PlatformSecurityContext context;
private final CollectionSheetReadPlatformService collectionSheetReadPlatformService;
private final ToApiJsonSerializer<JLGCollectionSheetData> toApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@Autowired
public CollectionSheetApiResource(final PlatformSecurityContext context,
final CollectionSheetReadPlatformService collectionSheetReadPlatformService,
final ToApiJsonSerializer<JLGCollectionSheetData> toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper, final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
this.context = context;
this.collectionSheetReadPlatformService = collectionSheetReadPlatformService;
this.toApiJsonSerializer = toApiJsonSerializer;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String collectionSheetData(@Context final UriInfo uriInfo, @PathParam("groupId") final Long groupId,
@QueryParam("dueDate") final String dueDate) {
this.context.authenticatedUser().validateHasReadPermission("COLLECTIONSHEET");
validateRequest(groupId, dueDate);
LocalDate localDate = null;
if(StringUtils.isBlank(dueDate)){
localDate = DateUtils.getLocalDateOfTenant();
}else{
localDate = DateUtils.parseLocalDate(dueDate, datePattern);
}
final JLGCollectionSheetData collectionSheet = this.collectionSheetReadPlatformService.retriveCollectionSheet(localDate, groupId);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, collectionSheet, this.COLLECTIONSHEET_DATA_PARAMETERS);
}
private void validateRequest(Long groupId, String dueDate) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("collectionsheet");
baseDataValidator.reset().parameter("groupId").value(groupId).notBlank().longGreaterThanZero();
baseDataValidator.reset().parameter("dueDate").value(dueDate).notBlank();
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateCalendar(@PathParam("groupId") final Long groupId, final String jsonRequestBody) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateCollectionSheet(groupId).withJson(jsonRequestBody).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
}
@@ -0,0 +1,69 @@
/**
* 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.portfolio.collectionsheet.serialization;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
@Component
public class CollectionSheetGenerateCommandFromApiJsonDeserializer {
/**
* The parameters supported for this command.
*/
final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("dueDate", "locale", "dateFormat"));
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public CollectionSheetGenerateCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
public void validateForGenerateCollectionSheet(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters);
final JsonElement element = this.fromApiJsonHelper.parse(json);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("collectionsheet");
final String dueDateParameterName = "dueDate";
final String dueDateStr = this.fromApiJsonHelper.extractStringNamed(dueDateParameterName, element);
baseDataValidator.reset().parameter(dueDateParameterName).value(dueDateStr).notBlank();
if(!StringUtils.isBlank(dueDateStr)){
final LocalDate dueDate = this.fromApiJsonHelper.extractLocalDateNamed(dueDateParameterName, element);
baseDataValidator.reset().parameter(dueDateParameterName).value(dueDate).notNull();
}
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -8,12 +8,17 @@ package org.mifosplatform.portfolio.collectionsheet.service;
import java.util.Collection;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.api.JsonQuery;
import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetData;
import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetFlatData;
public interface CollectionSheetReadPlatformService {
JLGCollectionSheetData retriveCollectionSheet(LocalDate localDate, Long groupId);
JLGCollectionSheetData generateGroupCollectionSheet(final Long groupId, final JsonQuery query);
JLGCollectionSheetData generateCenterCollectionSheet(final Long groupId, final JsonQuery query);
Collection<JLGCollectionSheetFlatData> retriveJLGCollectionSheet(String groupHierarchy, String officeHierarchy, LocalDate dueDate);
@@ -17,6 +17,7 @@ import java.util.List;
import java.util.Set;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.api.JsonQuery;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
@@ -26,8 +27,11 @@ import org.mifosplatform.portfolio.collectionsheet.data.JLGClientsData;
import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetData;
import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetFlatData;
import org.mifosplatform.portfolio.collectionsheet.data.LoanDueData;
import org.mifosplatform.portfolio.collectionsheet.serialization.CollectionSheetGenerateCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.group.data.CenterData;
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
import org.mifosplatform.portfolio.group.service.CenterReadPlatformService;
import org.mifosplatform.portfolio.group.service.GroupReadPlatformService;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
@@ -43,13 +47,17 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
private final PlatformSecurityContext context;
private final NamedParameterJdbcTemplate namedParameterjdbcTemplate;
private final CenterReadPlatformService centerReadPlatformService;
private final GroupReadPlatformService groupReadPlatformService;
private final CollectionSheetGenerateCommandFromApiJsonDeserializer collectionSheetGenerateCommandFromApiJsonDeserializer;
@Autowired
public CollectionSheetReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource,
final CenterReadPlatformService centerReadPlatformService) {
final CenterReadPlatformService centerReadPlatformService, final GroupReadPlatformService groupReadPlatformService, final CollectionSheetGenerateCommandFromApiJsonDeserializer collectionSheetGenerateCommandFromApiJsonDeserializer) {
this.context = context;
this.centerReadPlatformService = centerReadPlatformService;
this.namedParameterjdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
this.collectionSheetGenerateCommandFromApiJsonDeserializer = collectionSheetGenerateCommandFromApiJsonDeserializer;
this.groupReadPlatformService = groupReadPlatformService;
}
@Override
@@ -61,8 +69,10 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
final CenterData center = this.centerReadPlatformService.retrieveOne(centerId);
final String groupHierarchy = center.getHierarchy() + "%";
final JLGCollectionSheetData jlgCollectionSheetData = buildJLGCollectionSheet(groupHierarchy, officeHierarchy, dueDate);
Collection<JLGCollectionSheetFlatData> collectionSheetFlatDatas = this.retriveJLGCollectionSheet(groupHierarchy, officeHierarchy, dueDate);
final JLGCollectionSheetData jlgCollectionSheetData = buildJLGCollectionSheet(dueDate, collectionSheetFlatDatas);
return jlgCollectionSheetData;
}
@@ -73,11 +83,7 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
* Groups >> Clients >> Loans.
*/
@SuppressWarnings("null")
private JLGCollectionSheetData buildJLGCollectionSheet(final String groupHierarchy, final String officeHierarchy,
final LocalDate dueDate) {
final Collection<JLGCollectionSheetFlatData> jlgCollectionSheetFlatData = retriveJLGCollectionSheet(groupHierarchy,
officeHierarchy, dueDate);
private JLGCollectionSheetData buildJLGCollectionSheet(final LocalDate dueDate, final Collection<JLGCollectionSheetFlatData> jlgCollectionSheetFlatData) {
boolean firstTime = true;
Long prevGroupId = null;
@@ -191,13 +197,14 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
+ "ln.product_id As productId, "
+ "ln.currency_code as currencyCode, ln.currency_digits as currencyDigits, rc.`name` as currencyName, rc.display_symbol as currencyDisplaySymbol, rc.internationalized_name_code as currencyNameCode, "
+ "if(ln.loan_status_id = 200 , ln.principal_amount , null) As disbursementAmount, "
+ "sum(ifnull(ls.principal_amount, 0.0) - ifnull(ls.principal_completed_derived, 0.0)) As principalDue, "
+ "sum(ifnull(if(ln.loan_status_id = 300, ls.principal_amount, 0.0), 0.0) - ifnull(if(ln.loan_status_id = 300, ls.principal_completed_derived, 0.0), 0.0)) As principalDue, "
+ "ln.principal_repaid_derived As principalPaid, "
+ "sum(ifnull(ls.interest_amount, 0.0) - ifnull(ls.interest_completed_derived, 0.0)) As interestDue, "
+ "sum(ifnull(if(ln.loan_status_id = 300, ls.interest_amount, 0.0), 0.0) - ifnull(if(ln.loan_status_id = 300, ls.interest_completed_derived, 0.0), 0.0)) As interestDue, "
+ "ln.interest_repaid_derived As interestPaid, "
+ "sum(lc.amount_outstanding_derived) as chargesDue "
+ "sum(if(ln.loan_status_id = 300, lc.amount_outstanding_derived, 0.0)) as chargesDue "
+ "FROM m_group gp "
+ "LEFT JOIN m_office of ON of.id = gp.office_id AND of.hierarchy like :officeHierarchy "
//+ "LEFT JOIN m_office of ON of.id = gp.office_id "
+ "JOIN m_group_level gl ON gl.id = gp.level_Id "
+ "LEFT JOIN m_staff sf ON sf.id = gp.staff_id "
+ "JOIN m_group_client gc ON gc.group_id = gp.id "
@@ -206,8 +213,8 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
+ "LEFT JOIN m_product_loan pl ON pl.id = ln.product_id "
+ "JOIN m_currency rc on rc.`code` = ln.currency_code "
+ "LEFT JOIN m_loan_repayment_schedule ls ON ls.loan_id = ln.id AND ls.completed_derived = 0 AND ls.duedate <= :dueDate "
+ "LEFT JOIN m_loan_charge lc ON lc.loan_id = ln.id AND lc.is_paid_derived = 0 AND ( lc.due_for_collection_as_of_date <= :dueDate OR lc.charge_time_enum = 1) "
+ "WHERE gp.hierarchy like :hierarchy " + "GROUP BY gp.id ,cl.id , ln.id " + "ORDER BY gp.id , cl.id , ln.id ";
+ "LEFT JOIN m_loan_charge lc ON lc.loan_id = ln.id AND lc.is_paid_derived = 0 AND ( lc.due_for_collection_as_of_date <= :dueDate OR lc.charge_time_enum = 1) ";
//+ "WHERE gp.hierarchy like :hierarchy " + "GROUP BY gp.id ,cl.id , ln.id " + "ORDER BY gp.id , cl.id , ln.id ";
}
@Override
@@ -248,4 +255,63 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
}
}
@Override
public JLGCollectionSheetData generateGroupCollectionSheet(final Long groupId, final JsonQuery query) {
this.collectionSheetGenerateCommandFromApiJsonDeserializer.validateForGenerateCollectionSheet(query.json());
final AppUser currentUser = this.context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
final String officeHierarchy = hierarchy + "%";
final GroupGeneralData group = this.groupReadPlatformService.retrieveOne(groupId);
final LocalDate dueDate = query.localDateValueOfParameterNamed("dueDate");
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
final String dueDateStr = df.format(dueDate.toDate());
final JLGCollectionSheetFaltDataMapper mapper = new JLGCollectionSheetFaltDataMapper();
String sql = mapper.collectionSheetSchema();
sql += "WHERE gp.id = :groupId GROUP BY gp.id ,cl.id , ln.id ORDER BY gp.id , cl.id , ln.id";
final SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("dueDate", dueDateStr).addValue("groupId", group.getId())
.addValue("officeHierarchy", officeHierarchy);
final Collection<JLGCollectionSheetFlatData> collectionSheetFlatDatas = this.namedParameterjdbcTemplate.query(sql, namedParameters,
mapper);
return buildJLGCollectionSheet(dueDate, collectionSheetFlatDatas);
}
@Override
public JLGCollectionSheetData generateCenterCollectionSheet(final Long centerId, final JsonQuery query) {
this.collectionSheetGenerateCommandFromApiJsonDeserializer.validateForGenerateCollectionSheet(query.json());
final AppUser currentUser = this.context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
final String officeHierarchy = hierarchy + "%";
final CenterData center = this.centerReadPlatformService.retrieveOne(centerId);
final LocalDate dueDate = query.localDateValueOfParameterNamed("dueDate");
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
final String dueDateStr = df.format(dueDate.toDate());
final JLGCollectionSheetFaltDataMapper mapper = new JLGCollectionSheetFaltDataMapper();
String sql = mapper.collectionSheetSchema();
sql += "WHERE gp.parent_id = :centerId GROUP BY gp.id ,cl.id , ln.id ORDER BY gp.id , cl.id , ln.id";
final SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("dueDate", dueDateStr).addValue("centerId", center.getId())
.addValue("officeHierarchy", officeHierarchy);
final Collection<JLGCollectionSheetFlatData> collectionSheetFlatDatas = this.namedParameterjdbcTemplate.query(sql, namedParameters,
mapper);
return buildJLGCollectionSheet(dueDate, collectionSheetFlatDatas);
}
}
@@ -28,12 +28,16 @@ import org.mifosplatform.commands.service.CommandWrapperBuilder;
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
import org.mifosplatform.infrastructure.core.api.JsonQuery;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.exception.UnrecognizedQueryParamException;
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer;
import org.mifosplatform.infrastructure.core.service.Page;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetData;
import org.mifosplatform.portfolio.collectionsheet.service.CollectionSheetReadPlatformService;
import org.mifosplatform.portfolio.group.data.CenterData;
import org.mifosplatform.portfolio.group.data.GroupAccountSummaryCollectionData;
import org.mifosplatform.portfolio.group.service.CenterReadPlatformService;
@@ -43,6 +47,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
@Path("/centers")
@Component
@Scope("singleton")
@@ -56,6 +62,8 @@ public class CentersApiResource {
private final ToApiJsonSerializer<GroupAccountSummaryCollectionData> groupSummaryToApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final CollectionSheetReadPlatformService collectionSheetReadPlatformService;
private final FromJsonHelper fromJsonHelper;
@Autowired
public CentersApiResource(final PlatformSecurityContext context, final CenterReadPlatformService centerReadPlatformService,
@@ -63,7 +71,8 @@ public class CentersApiResource {
final ToApiJsonSerializer<Object> toApiJsonSerializer,
final ToApiJsonSerializer<GroupAccountSummaryCollectionData> groupSummaryToApiJsonSerializer,
final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
final CollectionSheetReadPlatformService collectionSheetReadPlatformService, final FromJsonHelper fromJsonHelper) {
this.context = context;
this.centerReadPlatformService = centerReadPlatformService;
this.groupReadPlatformService = groupReadPlatformService;
@@ -72,6 +81,8 @@ public class CentersApiResource {
this.groupSummaryToApiJsonSerializer = groupSummaryToApiJsonSerializer;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
this.collectionSheetReadPlatformService = collectionSheetReadPlatformService;
this.fromJsonHelper = fromJsonHelper;
}
@GET
@@ -178,7 +189,7 @@ public class CentersApiResource {
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String activate(@PathParam("centerId") final Long centerId, @QueryParam("command") final String commandParam,
final String apiRequestBodyAsJson) {
final String apiRequestBodyAsJson, @Context final UriInfo uriInfo) {
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
@@ -186,14 +197,21 @@ public class CentersApiResource {
if (is(commandParam, "activate")) {
final CommandWrapper commandRequest = builder.activateCenter(centerId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}else if (is(commandParam, "generateCollectionSheet")) {
final JsonElement parsedQuery = this.fromJsonHelper.parse(apiRequestBodyAsJson);
final JsonQuery query = JsonQuery.from(apiRequestBodyAsJson, parsedQuery, this.fromJsonHelper);
final JLGCollectionSheetData collectionSheet = this.collectionSheetReadPlatformService.generateCenterCollectionSheet(centerId, query);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, collectionSheet, GroupingTypesApiConstants.COLLECTIONSHEET_DATA_PARAMETERS);
}else if (is(commandParam, "saveCollectionSheet")) {
final CommandWrapper commandRequest = builder.saveCenterCollectionSheet(centerId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
} else { //
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate", "generateCollectionSheet" });
}
if (result == null) {
//
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate" });
}
return this.toApiJsonSerializer.serialize(result);
}
private boolean is(final String commandParam, final String commandValue) {
@@ -71,4 +71,7 @@ public class GroupingTypesApiConstants {
public static final Set<String> ACTIVATION_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
dateFormatParamName, activationDateParamName));
public static final Set<String> COLLECTIONSHEET_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("dueDate", "loanProducts", "groups"));
}
@@ -29,14 +29,18 @@ import org.mifosplatform.commands.service.CommandWrapperBuilder;
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
import org.mifosplatform.infrastructure.core.api.JsonQuery;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.exception.UnrecognizedQueryParamException;
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer;
import org.mifosplatform.infrastructure.core.service.Page;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetData;
import org.mifosplatform.portfolio.collectionsheet.service.CollectionSheetReadPlatformService;
import org.mifosplatform.portfolio.group.data.GroupAccountSummaryCollectionData;
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
import org.mifosplatform.portfolio.group.service.CenterReadPlatformService;
@@ -47,6 +51,8 @@ import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import com.google.gson.JsonElement;
@Path("/groups")
@Component
@Scope("singleton")
@@ -61,6 +67,8 @@ public class GroupsApiResource {
private final ToApiJsonSerializer<GroupAccountSummaryCollectionData> groupSummaryToApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final CollectionSheetReadPlatformService collectionSheetReadPlatformService;
private final FromJsonHelper fromJsonHelper;
@Autowired
public GroupsApiResource(final PlatformSecurityContext context, final GroupReadPlatformService groupReadPlatformService,
@@ -69,7 +77,8 @@ public class GroupsApiResource {
final ToApiJsonSerializer<GroupGeneralData> groupTopOfHierarchyApiJsonSerializer,
final ToApiJsonSerializer<GroupAccountSummaryCollectionData> groupSummaryToApiJsonSerializer,
final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
final CollectionSheetReadPlatformService collectionSheetReadPlatformService, final FromJsonHelper fromJsonHelper) {
this.context = context;
this.groupReadPlatformService = groupReadPlatformService;
this.centerReadPlatformService = centerReadPlatformService;
@@ -79,6 +88,8 @@ public class GroupsApiResource {
this.groupSummaryToApiJsonSerializer = groupSummaryToApiJsonSerializer;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
this.collectionSheetReadPlatformService = collectionSheetReadPlatformService;
this.fromJsonHelper = fromJsonHelper;
}
@GET
@@ -214,8 +225,8 @@ public class GroupsApiResource {
@Path("{groupId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String activate(@PathParam("groupId") final Long groupId, @QueryParam("command") final String commandParam,
final String apiRequestBodyAsJson) {
public String activateOrGenerateCollectionSheet(@PathParam("groupId") final Long groupId, @QueryParam("command") final String commandParam,
final String apiRequestBodyAsJson, @Context final UriInfo uriInfo) {
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
@@ -223,20 +234,29 @@ public class GroupsApiResource {
if (is(commandParam, "activate")) {
final CommandWrapper commandRequest = builder.activateGroup(groupId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}else if (is(commandParam, "associateClients")) {
final CommandWrapper commandRequest = builder.associateClientsToGroup(groupId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}else if (is(commandParam, "disassociateClients")) {
final CommandWrapper commandRequest = builder.disassociateClientsFromGroup(groupId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}else if (is(commandParam, "generateCollectionSheet")) {
final JsonElement parsedQuery = this.fromJsonHelper.parse(apiRequestBodyAsJson);
final JsonQuery query = JsonQuery.from(apiRequestBodyAsJson, parsedQuery, this.fromJsonHelper);
final JLGCollectionSheetData collectionSheet = this.collectionSheetReadPlatformService.generateGroupCollectionSheet(groupId, query);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, collectionSheet, GroupingTypesApiConstants.COLLECTIONSHEET_DATA_PARAMETERS);
}else if (is(commandParam, "saveCollectionSheet")) {
final CommandWrapper commandRequest = builder.saveGroupCollectionSheet(groupId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
} else {
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate", "generateCollectionSheet", "saveCollectionSheet" });
}
if (result == null) {
//
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate" });
}
return this.toApiJsonSerializer.serialize(result);
}
private boolean is(final String commandParam, final String commandValue) {
@@ -147,4 +147,9 @@ public class GroupGeneralData {
public Long officeId() {
return this.officeId;
}
public String getHierarchy() {
return this.hierarchy;
}
}
@@ -0,0 +1,19 @@
/**
* 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.portfolio.group.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
/**
* A {@link RuntimeException} thrown when group resources are not found.
*/
public class CenterNotFoundException extends AbstractPlatformResourceNotFoundException {
public CenterNotFoundException(final Long id) {
super("error.msg.center.id.invalid", "Center with identifier " + id + " does not exist", id);
}
}
@@ -0,0 +1,32 @@
/**
* 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.portfolio.group.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.portfolio.collectionsheet.service.CollectionSheetWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class SaveCenterCollectionSheetCommandHandler implements NewCommandSourceHandler {
private final CollectionSheetWritePlatformService writePlatformService;
@Autowired
public SaveCenterCollectionSheetCommandHandler(final CollectionSheetWritePlatformService collectionSheetWritePlatformService) {
this.writePlatformService = collectionSheetWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.updateCollectionSheet(command);
}
}
@@ -0,0 +1,32 @@
/**
* 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.portfolio.group.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.portfolio.collectionsheet.service.CollectionSheetWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class SaveGroupCollectionSheetCommandHandler implements NewCommandSourceHandler {
private final CollectionSheetWritePlatformService writePlatformService;
@Autowired
public SaveGroupCollectionSheetCommandHandler(final CollectionSheetWritePlatformService collectionSheetWritePlatformService) {
this.writePlatformService = collectionSheetWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.updateCollectionSheet(command);
}
}
@@ -30,7 +30,7 @@ import org.mifosplatform.portfolio.group.data.CenterData;
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
import org.mifosplatform.portfolio.group.domain.GroupTypes;
import org.mifosplatform.portfolio.group.domain.GroupingTypeEnumerations;
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
import org.mifosplatform.portfolio.group.exception.CenterNotFoundException;
import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
@@ -289,7 +289,7 @@ public class CenterReadPlatformServiceImpl implements CenterReadPlatformService
return this.jdbcTemplate.queryForObject(sql, this.centerMapper, new Object[] { centerId, hierarchySearchString });
} catch (EmptyResultDataAccessException e) {
throw new GroupNotFoundException(centerId);
throw new CenterNotFoundException(centerId);
}
}
@@ -1394,16 +1394,16 @@ public class Loan extends AbstractPersistable<Long> {
}
if (disbursedOn.isAfter(new LocalDate())) {
final String errorMessage = "The date on which a loan is disbursed cannot be in the future.";
final String errorMessage = "The date on which a loan with identifier : " + this.accountNumber + " is disbursed cannot be in the future.";
throw new InvalidLoanStateTransitionException("disbursal", "cannot.be.a.future.date", errorMessage, disbursedOn);
}
LocalDate firstRepaymentDueDate = this.repaymentScheduleInstallments.get(0).getDueDate();
if (disbursedOn.isAfter(firstRepaymentDueDate)) {
final String errorMessage = "The date on which a loan is disbursed cannot be after the first expected repayment date: "
final String errorMessage = "The date on which a loan with identifier : " + this.accountNumber + " is disbursed cannot be after the first expected repayment date: "
+ firstRepaymentDueDate.toString();
throw new InvalidLoanStateTransitionException("disbursal", "cannot.be.after.first.repayment.due.date", errorMessage,
disbursedOn, firstRepaymentDueDate);
this.accountNumber, disbursedOn, firstRepaymentDueDate);
}
return disbursementTransaction;