MIFOSX-1742 : added collection sheet for individuals

This commit is contained in:
Pramod Nuthakki
2015-01-16 10:24:26 +05:30
parent bc38cf4ff9
commit 2bd1332da7
28 changed files with 1080 additions and 85 deletions
+155 -6
View File
@@ -1183,7 +1183,7 @@
</div> </div>
<div class="flybar-nav"> <div class="flybar-nav">
<h2 class="flybar-button">Group</h2> <h2 class="flybar-button">Group & Collection Sheet</h2>
<div id="toc-menu-loan" class="flybar-menu"> <div id="toc-menu-loan" class="flybar-menu">
<div class="tocMatrix"> <div class="tocMatrix">
<table class=matrixHeading> <table class=matrixHeading>
@@ -1437,6 +1437,24 @@
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td><a href="#centers">Collection Sheet</a></td>
<td>collectionsheet?command=generateCollectionSheet</td>
<td><a href="#generate_individual_collection_sheet">Generate Collection Sheet</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>collectionsheet?command=saveCollectionSheet</td>
<td><a href="#save_individual_collection_sheet">Save Collection Sheet</a></td>
<td></td>
<td></td>
<td></td>
</tr>
</table> </table>
</div> </div>
</div> </div>
@@ -5334,6 +5352,99 @@ Request Body:
</div> </div>
</div> </div>
<a id="generate_individual_collection_sheet" name="generate_individual_collection_sheet" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Generate Individual Collection Sheet</h4>
<p>This Api retrieves repayment details of all individual loans under a office as on a specified meeting date.</p>
</div>
<div class="method-example">
<code class="method-declaration">POST https://Domain Name/api/v1/collectionsheet?command=generateCollectionSheet</code>
<code class="method-request">POST collectionsheet?command=generateCollectionSheet
Content-Type: application/json
Request Body:
{
"dateFormat":"dd MMMM yyyy",
"locale":"en",
"transactionDate":"15 January 2015",
"officeId":3
}
</code>
<code class="method-response">
{
"dueDate": [
2015,
1,
15
],
"clients": [
{
"clientId": 74,
"clientName": "guarantee test",
"loans": [
{
"loanId": 307,
"accountId": "000000307",
"accountStatusId": 300,
"productShortName": "pr",
"productId": 60,
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"inMultiplesOf": 0,
"displaySymbol": "$",
"nameCode": "currency.USD",
"displayLabel": "US Dollar ($)"
},
"principalDue": 1126.23,
"principalPaid": 8873.77,
"interestDue": 0,
"interestPaid": 504.95,
"totalDue": 1126.23
}
],
"savings": [
{
"savingsId": 213,
"accountId": "000000213",
"accountStatusId": 300,
"productName": "11",
"productId": 30,
"currency": {
"code": "USD",
"name": "US Dollar",
"decimalPlaces": 2,
"inMultiplesOf": 0,
"displaySymbol": "$",
"nameCode": "currency.USD",
"displayLabel": "US Dollar ($)"
},
"dueAmount": 2000
}
]
}
],
"paymentTypeOptions": [
{
"id": 19,
"name": "receipt",
"position": 1,
"description": "rec"
},
{
"id": 20,
"name": "check",
"position": 2,
"description": "che"
}
]
}
</code>
</div>
</div>
<a id="centers_save_collectionsheet" name="centers_save_collectionsheet" class="old-syle-anchor">&nbsp;</a> <a id="centers_save_collectionsheet" name="centers_save_collectionsheet" class="old-syle-anchor">&nbsp;</a>
<div class="method-section"> <div class="method-section">
<div class="method-description"> <div class="method-description">
@@ -5364,17 +5475,55 @@ Request Body:
"changes": { "changes": {
"locale": "en", "locale": "en",
"dateFormat": "dd MMMM yyyy", "dateFormat": "dd MMMM yyyy",
"bulkTransations": { "loanTransactions": [10],
"loanId": 10, "SavingsTransactions": []
"transactionAmount": 1221.36, }
"transactionDate": [2014,5,4] }
} </code>
</div>
</div>
<a id="save_individual_collection_sheet" name="save_individual_collection_sheet" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Save Collection Sheet</h4>
<p>This Api allows the loan officer to perform bulk repayments of individual loans and deposit of mandatory savings on a given meeting date.</p>
</div>
<div class="method-example">
<code class="method-declaration">POST https://Domain Name/api/v1/collectionsheet?command=saveCollectionSheet</code>
<code class="method-request">POST collectionsheet?command=saveCollectionSheet
{
"dateFormat": "dd MMMM yyyy",
"locale": "en",
"transactionDate": "04 May 2014",
"actualDisbursementDate": "04 May 2014",
"bulkDisbursementTransactions": [],
"bulkRepaymentTransactions": [{
"loanId": 10,
"transactionAmount": 1221.36,
"paymentTypeId":19,
"receiptNumber":"1245356"
}],
"bulkSavingsDueTransactions":[]
}
</code>
<code class="method-response">
{
"groupId": 10,
"resourceId": 10,
"changes": {
"locale": "en",
"dateFormat": "dd MMMM yyyy",
"loanTransactions": [15],
"SavingsTransactions": []
} }
} }
</code> </code>
</div> </div>
</div> </div>
<a id="centers_update" name="centers_update" class="old-syle-anchor">&nbsp;</a> <a id="centers_update" name="centers_update" class="old-syle-anchor">&nbsp;</a>
<div class="method-section"> <div class="method-section">
<div class="method-description"> <div class="method-description">
+1 -1
View File
@@ -192,7 +192,7 @@ body {
.flybar-nav { .flybar-nav {
display: block; display: block;
float: left; float: left;
width: 90px; min-width: 90px;
position: relative; position: relative;
} }
@@ -697,6 +697,11 @@ public class CommandWrapper {
public boolean isCollectionSheetResource() { public boolean isCollectionSheetResource() {
return this.entityName.equals("COLLECTIONSHEET"); return this.entityName.equals("COLLECTIONSHEET");
} }
public boolean isSaveIndividualCollectionSheet() {
return isCollectionSheetResource() && this.actionName.equalsIgnoreCase("SAVE");
}
public boolean isCenterResource() { public boolean isCenterResource() {
return this.entityName.equalsIgnoreCase("CENTER"); return this.entityName.equalsIgnoreCase("CENTER");
@@ -1425,6 +1425,13 @@ public class CommandWrapperBuilder {
this.href = "/groups/" + groupId + "?command=saveCollectionSheet"; this.href = "/groups/" + groupId + "?command=saveCollectionSheet";
return this; return this;
} }
public CommandWrapperBuilder saveIndividualCollectionSheet() {
this.actionName = "SAVE";
this.entityName = "COLLECTIONSHEET";
this.href = "/collectionsheet?command=saveCollectionSheet";
return this;
}
public CommandWrapperBuilder deleteGroup(final Long groupId) { public CommandWrapperBuilder deleteGroup(final Long groupId) {
this.actionName = "DELETE"; this.actionName = "DELETE";
@@ -280,15 +280,15 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
} else if (wrapper.isDelete()) { } else if (wrapper.isDelete()) {
handler = this.applicationContext.getBean("deleteTellerCommandHandler", NewCommandSourceHandler.class); handler = this.applicationContext.getBean("deleteTellerCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isAllocateCashier()) { } else if (wrapper.isAllocateCashier()) {
handler = this.applicationContext.getBean("allocateCashierToTellerCommandHandler", NewCommandSourceHandler.class); handler = this.applicationContext.getBean("allocateCashierToTellerCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isUpdateCashierAllocation()) { } else if (wrapper.isUpdateCashierAllocation()) {
handler = this.applicationContext.getBean("updateCashierAllocationCommandHandler", NewCommandSourceHandler.class); handler = this.applicationContext.getBean("updateCashierAllocationCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isDeleteCashierAllocation()) { } else if (wrapper.isDeleteCashierAllocation()) {
handler = this.applicationContext.getBean("deleteCashierAllocationCommandHandler", NewCommandSourceHandler.class); handler = this.applicationContext.getBean("deleteCashierAllocationCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isAllocateCashToCashier()) { } else if (wrapper.isAllocateCashToCashier()) {
handler = this.applicationContext.getBean("allocateCashToCashierCommandHandler", NewCommandSourceHandler.class); handler = this.applicationContext.getBean("allocateCashToCashierCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isSettleCashFromCashier()) { } else if (wrapper.isSettleCashFromCashier()) {
handler = this.applicationContext.getBean("settleCashFromCashierCommandHandler", NewCommandSourceHandler.class); handler = this.applicationContext.getBean("settleCashFromCashierCommandHandler", NewCommandSourceHandler.class);
} else { } else {
throw new UnsupportedCommandException(wrapper.commandName()); throw new UnsupportedCommandException(wrapper.commandName());
} }
@@ -755,6 +755,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
} else if (wrapper.isCollectionSheetResource()) { } else if (wrapper.isCollectionSheetResource()) {
if (wrapper.isUpdate()) { if (wrapper.isUpdate()) {
handler = this.applicationContext.getBean("updateCollectionSheetCommandHandler", NewCommandSourceHandler.class); handler = this.applicationContext.getBean("updateCollectionSheetCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isSaveIndividualCollectionSheet()) {
handler = this.applicationContext.getBean("saveIndividualCollectionSheetCommandHandler", NewCommandSourceHandler.class);
} else { } else {
throw new UnsupportedCommandException(wrapper.commandName()); throw new UnsupportedCommandException(wrapper.commandName());
} }
@@ -9,6 +9,8 @@ import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.mifosplatform.portfolio.paymentdetail.PaymentDetailConstants;
public class CollectionSheetConstants { public class CollectionSheetConstants {
public static final String COLLECTIONSHEET_RESOURCE_NAME = "collectionsheet"; public static final String COLLECTIONSHEET_RESOURCE_NAME = "collectionsheet";
@@ -23,6 +25,8 @@ public class CollectionSheetConstants {
public static final String bulkSavingsDueTransactionsParamName = "bulkSavingsDueTransactions"; public static final String bulkSavingsDueTransactionsParamName = "bulkSavingsDueTransactions";
public static final String noteParamName = "note"; public static final String noteParamName = "note";
public static final String calendarIdParamName = "calendarId"; public static final String calendarIdParamName = "calendarId";
public static final String officeIdParamName = "officeId";
public static final String staffIdParamName = "staffId";
// attendance parameters // attendance parameters
public static final String clientsAttendanceParamName = "clientsAttendance"; public static final String clientsAttendanceParamName = "clientsAttendance";
@@ -35,5 +39,16 @@ public class CollectionSheetConstants {
public static final Set<String> COLLECTIONSHEET_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName, public static final Set<String> COLLECTIONSHEET_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
dateFormatParamName, transactionDateParamName, actualDisbursementDateParamName, bulkRepaymentTransactionsParamName, dateFormatParamName, transactionDateParamName, actualDisbursementDateParamName, bulkRepaymentTransactionsParamName,
bulkDisbursementTransactionsParamName, noteParamName, calendarIdParamName, clientsAttendanceParamName, bulkSavingsDueTransactionsParamName)); bulkDisbursementTransactionsParamName, noteParamName, calendarIdParamName, clientsAttendanceParamName,
bulkSavingsDueTransactionsParamName, PaymentDetailConstants.paymentTypeParamName,
PaymentDetailConstants.accountNumberParamName, PaymentDetailConstants.checkNumberParamName,
PaymentDetailConstants.routingCodeParamName, PaymentDetailConstants.receiptNumberParamName,
PaymentDetailConstants.bankNumberParamName));
public static final Set<String> INDIVIDUAL_COLLECTIONSHEET_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
dateFormatParamName, transactionDateParamName, actualDisbursementDateParamName, bulkRepaymentTransactionsParamName,
bulkDisbursementTransactionsParamName, noteParamName, bulkSavingsDueTransactionsParamName));
public static final Set<String> INDIVIDUAL_COLLECTIONSHEET_SUPPORTED_PARAMS = new HashSet<>(Arrays.asList(transactionDateParamName,
localeParamName, dateFormatParamName, officeIdParamName, staffIdParamName));
} }
@@ -0,0 +1,89 @@
/**
* 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 javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
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.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.api.JsonQuery;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
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.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants;
import org.mifosplatform.portfolio.collectionsheet.data.IndividualCollectionSheetData;
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;
import com.google.gson.JsonElement;
@Path("/collectionsheet")
@Component
@Scope("singleton")
public class CollectionSheetApiResourse {
private final CollectionSheetReadPlatformService collectionSheetReadPlatformService;
private final ToApiJsonSerializer<Object> toApiJsonSerializer;
private final FromJsonHelper fromJsonHelper;
private final ApiRequestParameterHelper apiRequestPrameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final PlatformSecurityContext context;
@Autowired
public CollectionSheetApiResourse(final CollectionSheetReadPlatformService collectionSheetReadPlatformService,
final ToApiJsonSerializer<Object> toApiJsonSerializer, final FromJsonHelper fromJsonHelper,
final ApiRequestParameterHelper apiRequestPrameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, final PlatformSecurityContext context) {
this.collectionSheetReadPlatformService = collectionSheetReadPlatformService;
this.toApiJsonSerializer = toApiJsonSerializer;
this.fromJsonHelper = fromJsonHelper;
this.apiRequestPrameterHelper = apiRequestPrameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
this.context = context;
}
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String generateCollectionSheet(@QueryParam("command") final String commandParam, final String apiRequestBodyAsJson,
@Context final UriInfo uriInfo) {
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
CommandProcessingResult result = null;
if (is(commandParam, "generateCollectionSheet")) {
this.context.authenticatedUser().validateHasReadPermission(CollectionSheetConstants.COLLECTIONSHEET_RESOURCE_NAME);
final JsonElement parsedQuery = this.fromJsonHelper.parse(apiRequestBodyAsJson);
final JsonQuery query = JsonQuery.from(apiRequestBodyAsJson, parsedQuery, this.fromJsonHelper);
final IndividualCollectionSheetData collectionSheet = this.collectionSheetReadPlatformService
.generateIndividualCollectionSheet(query);
final ApiRequestJsonSerializationSettings settings = this.apiRequestPrameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, collectionSheet);
} else if (is(commandParam, "saveCollectionSheet")) {
final CommandWrapper commandRequest = builder.saveIndividualCollectionSheet().build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
return null;
}
private boolean is(final String commandParam, final String commandValue) {
return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
}
}
@@ -8,6 +8,7 @@ package org.mifosplatform.portfolio.collectionsheet.command;
import java.math.BigDecimal; import java.math.BigDecimal;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
/** /**
* Immutable command for Single loan repayment. * Immutable command for Single loan repayment.
@@ -17,11 +18,14 @@ public class SingleRepaymentCommand {
private final Long loanId; private final Long loanId;
private final BigDecimal transactionAmount; private final BigDecimal transactionAmount;
private final LocalDate transactionDate; private final LocalDate transactionDate;
private final PaymentDetail paymentDetail;
public SingleRepaymentCommand(final Long loanId, final BigDecimal transactionAmount, final LocalDate transactionDate) { public SingleRepaymentCommand(final Long loanId, final BigDecimal transactionAmount, final LocalDate transactionDate,
final PaymentDetail paymentDetail) {
this.loanId = loanId; this.loanId = loanId;
this.transactionAmount = transactionAmount; this.transactionAmount = transactionAmount;
this.transactionDate = transactionDate; this.transactionDate = transactionDate;
this.paymentDetail = paymentDetail;
} }
public Long getLoanId() { public Long getLoanId() {
@@ -36,4 +40,7 @@ public class SingleRepaymentCommand {
return this.transactionDate; return this.transactionDate;
} }
public PaymentDetail getPaymentDetail() {
return this.paymentDetail;
}
} }
@@ -7,6 +7,7 @@ package org.mifosplatform.portfolio.collectionsheet.data;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.COLLECTIONSHEET_REQUEST_DATA_PARAMETERS; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.COLLECTIONSHEET_REQUEST_DATA_PARAMETERS;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.COLLECTIONSHEET_RESOURCE_NAME; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.COLLECTIONSHEET_RESOURCE_NAME;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.INDIVIDUAL_COLLECTIONSHEET_REQUEST_DATA_PARAMETERS;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.attendanceTypeParamName; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.attendanceTypeParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.bulkDisbursementTransactionsParamName; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.bulkDisbursementTransactionsParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.bulkRepaymentTransactionsParamName; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.bulkRepaymentTransactionsParamName;
@@ -15,8 +16,8 @@ import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstan
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.clientIdParamName; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.clientIdParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.clientsAttendanceParamName; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.clientsAttendanceParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.loanIdParamName; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.loanIdParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.savingsIdParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.noteParamName; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.noteParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.savingsIdParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.transactionAmountParamName; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.transactionAmountParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.transactionDateParamName; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.transactionDateParamName;
@@ -35,6 +36,7 @@ import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.portfolio.paymentdetail.PaymentDetailConstants;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -82,7 +84,39 @@ public class CollectionSheetTransactionDataValidator {
validateDisbursementTransactions(element, baseDataValidator); validateDisbursementTransactions(element, baseDataValidator);
validateRepaymentTransactions(element, baseDataValidator); validateRepaymentTransactions(element, baseDataValidator);
validateSavingsDueTransactions(element, baseDataValidator);
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(element.getAsJsonObject());
validatePaymentDetails(baseDataValidator, element, locale);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
public void validateIndividualCollectionSheet(final JsonCommand command) {
final String json = command.json();
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, INDIVIDUAL_COLLECTIONSHEET_REQUEST_DATA_PARAMETERS);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(COLLECTIONSHEET_RESOURCE_NAME);
final JsonElement element = this.fromApiJsonHelper.parse(json);
final LocalDate transactionDate = this.fromApiJsonHelper.extractLocalDateNamed(transactionDateParamName, element);
baseDataValidator.reset().parameter(transactionDateParamName).value(transactionDate).notNull();
final String note = this.fromApiJsonHelper.extractStringNamed(noteParamName, element);
if (StringUtils.isNotBlank(note)) {
baseDataValidator.reset().parameter(noteParamName).value(note).notExceedingLengthOf(1000);
}
validateDisbursementTransactions(element, baseDataValidator);
validateRepaymentTransactions(element, baseDataValidator);
validateSavingsDueTransactions(element, baseDataValidator); validateSavingsDueTransactions(element, baseDataValidator);
throwExceptionIfValidationWarningsExist(dataValidationErrors); throwExceptionIfValidationWarningsExist(dataValidationErrors);
@@ -147,11 +181,13 @@ public class CollectionSheetTransactionDataValidator {
.integerGreaterThanZero(); .integerGreaterThanZero();
baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].disbursement.amount").value(disbursementAmount) baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].disbursement.amount").value(disbursementAmount)
.notNull().zeroOrPositiveAmount(); .notNull().zeroOrPositiveAmount();
validatePaymentDetails(baseDataValidator, loanTransactionElement, locale);
} }
} }
} }
} }
private void validateSavingsDueTransactions(final JsonElement element, final DataValidatorBuilder baseDataValidator) { private void validateSavingsDueTransactions(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
final JsonObject topLevelJsonElement = element.getAsJsonObject(); final JsonObject topLevelJsonElement = element.getAsJsonObject();
final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement); final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
@@ -168,13 +204,27 @@ public class CollectionSheetTransactionDataValidator {
baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].savings.id").value(savingsId).notNull() baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].savings.id").value(savingsId).notNull()
.integerGreaterThanZero(); .integerGreaterThanZero();
baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].due.amount").value(dueAmount) baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].due.amount").value(dueAmount).notNull()
.notNull().zeroOrPositiveAmount(); .zeroOrPositiveAmount();
validatePaymentDetails(baseDataValidator, savingsTransactionElement, locale);
} }
} }
} }
} }
private void validatePaymentDetails(final DataValidatorBuilder baseDataValidator, final JsonElement element, final Locale locale) {
// Validate all string payment detail fields for max length
final Integer paymentTypeId = this.fromApiJsonHelper.extractIntegerNamed(PaymentDetailConstants.paymentTypeParamName, element,
locale);
baseDataValidator.reset().parameter(PaymentDetailConstants.paymentTypeParamName).value(paymentTypeId).ignoreIfNull()
.integerGreaterThanZero();
for (final String paymentDetailParameterName : PaymentDetailConstants.PAYMENT_CREATE_REQUEST_DATA_PARAMETERS) {
final String paymentDetailParameterValue = this.fromApiJsonHelper.extractStringNamed(paymentDetailParameterName, element);
baseDataValidator.reset().parameter(paymentDetailParameterName).value(paymentDetailParameterValue).ignoreIfNull()
.notExceedingLengthOf(50);
}
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) { private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
} }
@@ -0,0 +1,96 @@
/**
* 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.data;
import java.util.Collection;
/**
* Immutable data object for clients with loans due for disbursement or
* collection.
*/
public class IndividualClientData {
private final Long clientId;
private final String clientName;
private Collection<LoanDueData> loans;
private Collection<SavingsDueData> savings;
public static IndividualClientData instance(final Long clientId, final String clientName) {
final Collection<LoanDueData> loans = null;
final Collection<SavingsDueData> savings = null;
return new IndividualClientData(clientId, clientName, loans, savings);
}
public static IndividualClientData withSavings(final IndividualClientData client, final Collection<SavingsDueData> savings) {
return new IndividualClientData(client.clientId, client.clientName, client.loans, savings);
}
public static IndividualClientData withLoans(final IndividualClientData client, final Collection<LoanDueData> loans) {
return new IndividualClientData(client.clientId, client.clientName, loans, client.savings);
}
/**
* @param clientId
* @param clientName
* @param loans
* @param savings
*/
private IndividualClientData(Long clientId, String clientName, Collection<LoanDueData> loans, Collection<SavingsDueData> savings) {
this.clientId = clientId;
this.clientName = clientName;
this.loans = loans;
this.savings = savings;
}
public Long getClientId() {
return this.clientId;
}
public String getClientName() {
return this.clientName;
}
public Collection<LoanDueData> getLoans() {
return this.loans;
}
public void setLoans(final Collection<LoanDueData> loans) {
this.loans = loans;
}
public void addLoans(LoanDueData loans) {
if (this.loans != null) {
this.loans.add(loans);
}
}
public Collection<SavingsDueData> getSavings() {
return this.savings;
}
public void setSavings(Collection<SavingsDueData> savings) {
this.savings = savings;
}
public void addSavings(SavingsDueData savings) {
if (this.savings != null) {
this.savings.add(savings);
}
}
@Override
public boolean equals(final Object obj) {
final IndividualClientData clientData = (IndividualClientData) obj;
return clientData.clientId.compareTo(this.clientId) == 0;
}
@Override
public int hashCode() {
return this.clientId.hashCode();
}
}
@@ -0,0 +1,38 @@
/**
* 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.data;
import java.util.Collection;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
/**
* Immutable data object for collection sheet.
*/
public class IndividualCollectionSheetData {
@SuppressWarnings("unused")
private final LocalDate dueDate;
@SuppressWarnings("unused")
private final Collection<IndividualClientData> clients;
@SuppressWarnings("unused")
private final Collection<CodeValueData> paymentTypeOptions;
public static IndividualCollectionSheetData instance(final LocalDate date, final Collection<IndividualClientData> clients,
final Collection<CodeValueData> paymentTypeOptions) {
return new IndividualCollectionSheetData(date, clients, paymentTypeOptions);
}
private IndividualCollectionSheetData(final LocalDate dueDate, final Collection<IndividualClientData> clients,
final Collection<CodeValueData> paymentTypeOptions) {
this.dueDate = dueDate;
this.clients = clients;
this.paymentTypeOptions = paymentTypeOptions;
}
}
@@ -0,0 +1,118 @@
/**
* 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.data;
import java.math.BigDecimal;
import org.mifosplatform.organisation.monetary.data.CurrencyData;
/**
* Immutable data object for extracting flat data for joint liability group's
* collection sheet.
*/
public class IndividualCollectionSheetLoanFlatData {
private final String clientName;
private final Long clientId;
private final Long loanId;
private final String accountId;
private final Integer accountStatusId;
private final String productShortName;
private final Long productId;
private final CurrencyData currency;
private BigDecimal disbursementAmount = BigDecimal.ZERO;
private BigDecimal principalDue = BigDecimal.ZERO;
private BigDecimal principalPaid = BigDecimal.ZERO;
private BigDecimal interestDue = BigDecimal.ZERO;
private BigDecimal interestPaid = BigDecimal.ZERO;
private BigDecimal chargesDue = BigDecimal.ZERO;
public IndividualCollectionSheetLoanFlatData(final String clientName, final Long clientId, final Long loanId, final String accountId,
final Integer accountStatusId, final String productShortName, final Long productId, final CurrencyData currency,
final BigDecimal disbursementAmount, final BigDecimal principalDue, final BigDecimal principalPaid,
final BigDecimal interestDue, final BigDecimal interestPaid, final BigDecimal chargesDue) {
this.clientName = clientName;
this.clientId = clientId;
this.loanId = loanId;
this.accountId = accountId;
this.accountStatusId = accountStatusId;
this.productShortName = productShortName;
this.productId = productId;
this.currency = currency;
this.disbursementAmount = disbursementAmount;
this.principalDue = principalDue;
this.principalPaid = principalPaid;
this.interestDue = interestDue;
this.interestPaid = interestPaid;
this.chargesDue = chargesDue;
}
public String getClientName() {
return this.clientName;
}
public Long getClientId() {
return this.clientId;
}
public Long getLoanId() {
return this.loanId;
}
public String getAccountId() {
return this.accountId;
}
public Integer getAccountStatusId() {
return this.accountStatusId;
}
public String getProductShortName() {
return this.productShortName;
}
public Long getProductId() {
return this.productId;
}
public CurrencyData getCurrency() {
return this.currency;
}
public BigDecimal getDisbursementAmount() {
return this.disbursementAmount;
}
public BigDecimal getPrincipalDue() {
return this.principalDue;
}
public BigDecimal getPrincipalPaid() {
return this.principalPaid;
}
public BigDecimal getInterestDue() {
return this.interestDue;
}
public BigDecimal getInterestPaid() {
return this.interestPaid;
}
public BigDecimal getChargesDue() {
return this.chargesDue;
}
public LoanDueData getLoanDueData() {
return new LoanDueData(this.loanId, this.accountId, this.accountStatusId, this.productShortName, this.productId, this.currency,
this.disbursementAmount, this.principalDue, this.principalPaid, this.interestDue, this.interestPaid, this.chargesDue);
}
public IndividualClientData getClientData() {
return IndividualClientData.instance(this.clientId, this.clientName);
}
}
@@ -9,6 +9,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData; import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData; import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.mifosplatform.portfolio.savings.data.SavingsProductData; import org.mifosplatform.portfolio.savings.data.SavingsProductData;
@@ -24,25 +25,30 @@ public class JLGCollectionSheetData {
private final Collection<SavingsProductData> savingsProducts; private final Collection<SavingsProductData> savingsProducts;
private final Collection<JLGGroupData> groups; private final Collection<JLGGroupData> groups;
private final List<EnumOptionData> attendanceTypeOptions; private final List<EnumOptionData> attendanceTypeOptions;
private final Collection<CodeValueData> paymentTypeOptions;
public static JLGCollectionSheetData instance(final LocalDate date, final Collection<LoanProductData> loanProducts, public static JLGCollectionSheetData instance(final LocalDate date, final Collection<LoanProductData> loanProducts,
final Collection<JLGGroupData> groups, final List<EnumOptionData> attendanceTypeOptions) { final Collection<JLGGroupData> groups, final List<EnumOptionData> attendanceTypeOptions,
return new JLGCollectionSheetData(date, loanProducts, null, groups, attendanceTypeOptions); final Collection<CodeValueData> paymentTypeOptions) {
return new JLGCollectionSheetData(date, loanProducts, null, groups, attendanceTypeOptions, paymentTypeOptions);
} }
public static JLGCollectionSheetData withSavingsProducts(final JLGCollectionSheetData data, public static JLGCollectionSheetData withSavingsProducts(final JLGCollectionSheetData data,
final Collection<SavingsProductData> savingsProducts) { final Collection<SavingsProductData> savingsProducts) {
return new JLGCollectionSheetData(data.dueDate, data.loanProducts, savingsProducts, data.groups, data.attendanceTypeOptions); return new JLGCollectionSheetData(data.dueDate, data.loanProducts, savingsProducts, data.groups, data.attendanceTypeOptions,
data.paymentTypeOptions);
} }
private JLGCollectionSheetData(LocalDate dueDate, Collection<LoanProductData> loanProducts, private JLGCollectionSheetData(LocalDate dueDate, Collection<LoanProductData> loanProducts,
Collection<SavingsProductData> savingsProducts, Collection<JLGGroupData> groups, List<EnumOptionData> attendanceTypeOptions) { Collection<SavingsProductData> savingsProducts, Collection<JLGGroupData> groups, List<EnumOptionData> attendanceTypeOptions,
final Collection<CodeValueData> paymentTypeOptions) {
this.dueDate = dueDate; this.dueDate = dueDate;
this.loanProducts = loanProducts; this.loanProducts = loanProducts;
this.savingsProducts = savingsProducts; this.savingsProducts = savingsProducts;
this.groups = groups; this.groups = groups;
this.attendanceTypeOptions = attendanceTypeOptions; this.attendanceTypeOptions = attendanceTypeOptions;
this.paymentTypeOptions = paymentTypeOptions;
} }
public LocalDate getDate() { public LocalDate getDate() {
@@ -0,0 +1,33 @@
/**
* 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.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 SaveIndividualCollectionSheetCommandHandler implements NewCommandSourceHandler {
private final CollectionSheetWritePlatformService collectionSheetWritePlatformService;
@Autowired
public SaveIndividualCollectionSheetCommandHandler(final CollectionSheetWritePlatformService collectionSheetWritePlatformService) {
this.collectionSheetWritePlatformService = collectionSheetWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.collectionSheetWritePlatformService.saveIndividualCollectionSheet(command);
}
}
@@ -16,6 +16,8 @@ import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializ
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkRepaymentCommand; import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkRepaymentCommand;
import org.mifosplatform.portfolio.collectionsheet.command.SingleRepaymentCommand; import org.mifosplatform.portfolio.collectionsheet.command.SingleRepaymentCommand;
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetailAssembler;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -32,16 +34,28 @@ public final class CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer ex
AbstractFromApiJsonDeserializer<CollectionSheetBulkRepaymentCommand> { AbstractFromApiJsonDeserializer<CollectionSheetBulkRepaymentCommand> {
private final FromJsonHelper fromApiJsonHelper; private final FromJsonHelper fromApiJsonHelper;
private final PaymentDetailAssembler paymentDetailAssembler;
@Autowired @Autowired
public CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) { public CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper,
final PaymentDetailAssembler paymentDetailAssembler) {
this.fromApiJsonHelper = fromApiJsonHelper; this.fromApiJsonHelper = fromApiJsonHelper;
this.paymentDetailAssembler = paymentDetailAssembler;
} }
@Override @Override
public CollectionSheetBulkRepaymentCommand commandFromApiJson(final String json) { public CollectionSheetBulkRepaymentCommand commandFromApiJson(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final JsonElement element = this.fromApiJsonHelper.parse(json);
final PaymentDetail paymentDetail = this.paymentDetailAssembler.fetchPaymentDetail(element.getAsJsonObject());
return commandFromApiJson(json, paymentDetail);
}
public CollectionSheetBulkRepaymentCommand commandFromApiJson(final String json, final PaymentDetail paymentDetail) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final JsonElement element = this.fromApiJsonHelper.parse(json); final JsonElement element = this.fromApiJsonHelper.parse(json);
final LocalDate transactionDate = this.fromApiJsonHelper.extractLocalDateNamed("transactionDate", element); final LocalDate transactionDate = this.fromApiJsonHelper.extractLocalDateNamed("transactionDate", element);
@@ -63,7 +77,12 @@ public final class CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer ex
final Long loanId = this.fromApiJsonHelper.extractLongNamed("loanId", loanTransactionElement); final Long loanId = this.fromApiJsonHelper.extractLongNamed("loanId", loanTransactionElement);
final BigDecimal transactionAmount = this.fromApiJsonHelper.extractBigDecimalNamed("transactionAmount", final BigDecimal transactionAmount = this.fromApiJsonHelper.extractBigDecimalNamed("transactionAmount",
loanTransactionElement, locale); loanTransactionElement, locale);
loanRepaymentTransactions[i] = new SingleRepaymentCommand(loanId, transactionAmount, transactionDate); PaymentDetail detail = paymentDetail;
if (paymentDetail == null) {
detail = this.paymentDetailAssembler.fetchPaymentDetail(loanTransactionElement);
}
loanRepaymentTransactions[i] = new SingleRepaymentCommand(loanId, transactionAmount, transactionDate, detail);
} }
} }
} }
@@ -5,9 +5,12 @@
*/ */
package org.mifosplatform.portfolio.collectionsheet.serialization; package org.mifosplatform.portfolio.collectionsheet.serialization;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.INDIVIDUAL_COLLECTIONSHEET_SUPPORTED_PARAMS;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.calendarIdParamName; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.calendarIdParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.dateFormatParamName; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.dateFormatParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.localeParamName; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.localeParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.officeIdParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.staffIdParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.transactionDateParamName; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.transactionDateParamName;
import java.lang.reflect.Type; import java.lang.reflect.Type;
@@ -37,8 +40,8 @@ public class CollectionSheetGenerateCommandFromApiJsonDeserializer {
/** /**
* The parameters supported for this command. * The parameters supported for this command.
*/ */
final Set<String> supportedParameters = new HashSet<>(Arrays.asList(transactionDateParamName, localeParamName, final Set<String> supportedParameters = new HashSet<>(Arrays.asList(transactionDateParamName, localeParamName, dateFormatParamName,
dateFormatParamName, calendarIdParamName)); calendarIdParamName));
private final FromJsonHelper fromApiJsonHelper; private final FromJsonHelper fromApiJsonHelper;
@@ -74,4 +77,34 @@ public class CollectionSheetGenerateCommandFromApiJsonDeserializer {
"Validation errors exist.", dataValidationErrors); } "Validation errors exist.", dataValidationErrors); }
} }
public void validateForGenerateCollectionSheetOfIndividuals(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, INDIVIDUAL_COLLECTIONSHEET_SUPPORTED_PARAMS);
final JsonElement element = this.fromApiJsonHelper.parse(json);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("collectionsheet");
final String transactionDateStr = this.fromApiJsonHelper.extractStringNamed(transactionDateParamName, element);
baseDataValidator.reset().parameter(transactionDateParamName).value(transactionDateStr).notBlank();
if (!StringUtils.isBlank(transactionDateStr)) {
final LocalDate dueDate = this.fromApiJsonHelper.extractLocalDateNamed(transactionDateParamName, element);
baseDataValidator.reset().parameter(transactionDateParamName).value(dueDate).notNull();
}
final Long officeId = this.fromApiJsonHelper.extractLongNamed(officeIdParamName, element);
baseDataValidator.reset().parameter(officeIdParamName).value(officeId).longGreaterThanZero();
final Long staffId = this.fromApiJsonHelper.extractLongNamed(staffIdParamName, element);
baseDataValidator.reset().parameter(staffIdParamName).value(staffId).longGreaterThanZero();
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
} }
@@ -6,6 +6,7 @@
package org.mifosplatform.portfolio.collectionsheet.service; package org.mifosplatform.portfolio.collectionsheet.service;
import org.mifosplatform.infrastructure.core.api.JsonQuery; import org.mifosplatform.infrastructure.core.api.JsonQuery;
import org.mifosplatform.portfolio.collectionsheet.data.IndividualCollectionSheetData;
import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetData; import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetData;
public interface CollectionSheetReadPlatformService { public interface CollectionSheetReadPlatformService {
@@ -14,4 +15,6 @@ public interface CollectionSheetReadPlatformService {
JLGCollectionSheetData generateCenterCollectionSheet(final Long groupId, final JsonQuery query); JLGCollectionSheetData generateCenterCollectionSheet(final Long groupId, final JsonQuery query);
IndividualCollectionSheetData generateIndividualCollectionSheet(final JsonQuery query);
} }
@@ -7,6 +7,8 @@ package org.mifosplatform.portfolio.collectionsheet.service;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.calendarIdParamName; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.calendarIdParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.transactionDateParamName; import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.transactionDateParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.officeIdParamName;
import static org.mifosplatform.portfolio.collectionsheet.CollectionSheetConstants.staffIdParamName;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.ResultSet; import java.sql.ResultSet;
@@ -20,6 +22,8 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.infrastructure.codes.service.CodeValueReadPlatformService;
import org.mifosplatform.infrastructure.core.api.JsonQuery; import org.mifosplatform.infrastructure.core.api.JsonQuery;
import org.mifosplatform.infrastructure.core.data.EnumOptionData; import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport; import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
@@ -30,6 +34,9 @@ import org.mifosplatform.portfolio.calendar.domain.Calendar;
import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType; import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType;
import org.mifosplatform.portfolio.calendar.domain.CalendarRepositoryWrapper; import org.mifosplatform.portfolio.calendar.domain.CalendarRepositoryWrapper;
import org.mifosplatform.portfolio.calendar.exception.NotValidRecurringDateException; import org.mifosplatform.portfolio.calendar.exception.NotValidRecurringDateException;
import org.mifosplatform.portfolio.collectionsheet.data.IndividualClientData;
import org.mifosplatform.portfolio.collectionsheet.data.IndividualCollectionSheetData;
import org.mifosplatform.portfolio.collectionsheet.data.IndividualCollectionSheetLoanFlatData;
import org.mifosplatform.portfolio.collectionsheet.data.JLGClientData; import org.mifosplatform.portfolio.collectionsheet.data.JLGClientData;
import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetData; import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetData;
import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetFlatData; import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetFlatData;
@@ -44,6 +51,7 @@ import org.mifosplatform.portfolio.group.service.GroupReadPlatformService;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData; import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.mifosplatform.portfolio.meeting.attendance.service.AttendanceDropdownReadPlatformService; import org.mifosplatform.portfolio.meeting.attendance.service.AttendanceDropdownReadPlatformService;
import org.mifosplatform.portfolio.meeting.attendance.service.AttendanceEnumerations; import org.mifosplatform.portfolio.meeting.attendance.service.AttendanceEnumerations;
import org.mifosplatform.portfolio.paymentdetail.PaymentDetailConstants;
import org.mifosplatform.portfolio.savings.data.SavingsProductData; import org.mifosplatform.portfolio.savings.data.SavingsProductData;
import org.mifosplatform.useradministration.domain.AppUser; import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -65,14 +73,16 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
private final CollectionSheetGenerateCommandFromApiJsonDeserializer collectionSheetGenerateCommandFromApiJsonDeserializer; private final CollectionSheetGenerateCommandFromApiJsonDeserializer collectionSheetGenerateCommandFromApiJsonDeserializer;
private final CalendarRepositoryWrapper calendarRepositoryWrapper; private final CalendarRepositoryWrapper calendarRepositoryWrapper;
private final AttendanceDropdownReadPlatformService attendanceDropdownReadPlatformService; private final AttendanceDropdownReadPlatformService attendanceDropdownReadPlatformService;
final MandatorySavingsCollectionsheetExtractor mandatorySavingsExtractor = new MandatorySavingsCollectionsheetExtractor(); private final MandatorySavingsCollectionsheetExtractor mandatorySavingsExtractor = new MandatorySavingsCollectionsheetExtractor();
private final CodeValueReadPlatformService codeValueReadPlatformService;
@Autowired @Autowired
public CollectionSheetReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource, public CollectionSheetReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource,
final CenterReadPlatformService centerReadPlatformService, final GroupReadPlatformService groupReadPlatformService, final CenterReadPlatformService centerReadPlatformService, final GroupReadPlatformService groupReadPlatformService,
final CollectionSheetGenerateCommandFromApiJsonDeserializer collectionSheetGenerateCommandFromApiJsonDeserializer, final CollectionSheetGenerateCommandFromApiJsonDeserializer collectionSheetGenerateCommandFromApiJsonDeserializer,
final CalendarRepositoryWrapper calendarRepositoryWrapper, final CalendarRepositoryWrapper calendarRepositoryWrapper,
final AttendanceDropdownReadPlatformService attendanceDropdownReadPlatformService) { final AttendanceDropdownReadPlatformService attendanceDropdownReadPlatformService,
final CodeValueReadPlatformService codeValueReadPlatformService) {
this.context = context; this.context = context;
this.centerReadPlatformService = centerReadPlatformService; this.centerReadPlatformService = centerReadPlatformService;
this.namedParameterjdbcTemplate = new NamedParameterJdbcTemplate(dataSource); this.namedParameterjdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
@@ -80,6 +90,7 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
this.groupReadPlatformService = groupReadPlatformService; this.groupReadPlatformService = groupReadPlatformService;
this.calendarRepositoryWrapper = calendarRepositoryWrapper; this.calendarRepositoryWrapper = calendarRepositoryWrapper;
this.attendanceDropdownReadPlatformService = attendanceDropdownReadPlatformService; this.attendanceDropdownReadPlatformService = attendanceDropdownReadPlatformService;
this.codeValueReadPlatformService = codeValueReadPlatformService;
} }
/* /*
@@ -94,6 +105,8 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
boolean firstTime = true; boolean firstTime = true;
Long prevGroupId = null; Long prevGroupId = null;
Long prevClientId = null; Long prevClientId = null;
final Collection<CodeValueData> paymentOptions = this.codeValueReadPlatformService
.retrieveCodeValuesByCode(PaymentDetailConstants.paymentTypeCodeName);
final List<JLGGroupData> jlgGroupsData = new ArrayList<>(); final List<JLGGroupData> jlgGroupsData = new ArrayList<>();
List<JLGClientData> clientsData = new ArrayList<>(); List<JLGClientData> clientsData = new ArrayList<>();
@@ -168,7 +181,7 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
} }
jlgCollectionSheetData = JLGCollectionSheetData.instance(dueDate, loanProducts, jlgGroupsData, jlgCollectionSheetData = JLGCollectionSheetData.instance(dueDate, loanProducts, jlgGroupsData,
this.attendanceDropdownReadPlatformService.retrieveAttendanceTypeOptions()); this.attendanceDropdownReadPlatformService.retrieveAttendanceTypeOptions(), paymentOptions);
} }
return jlgCollectionSheetData; return jlgCollectionSheetData;
@@ -613,4 +626,219 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe
return SavingsDueData.instance(savingsId, accountId, accountStatusId, productName, productId, currency, dueAmount); return SavingsDueData.instance(savingsId, accountId, accountStatusId, productName, productId, currency, dueAmount);
} }
} }
@Override
public IndividualCollectionSheetData generateIndividualCollectionSheet(final JsonQuery query) {
this.collectionSheetGenerateCommandFromApiJsonDeserializer.validateForGenerateCollectionSheetOfIndividuals(query.json());
final LocalDate transactionDate = query.localDateValueOfParameterNamed(transactionDateParamName);
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
final String transactionDateStr = df.format(transactionDate.toDate());
final AppUser currentUser = this.context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
final String officeHierarchy = hierarchy + "%";
final Long officeId = query.longValueOfParameterNamed(officeIdParamName);
final Long staffId = query.longValueOfParameterNamed(staffIdParamName);
final boolean checkForOfficeId = officeId != null;
final boolean checkForStaffId = staffId != null;
final IndividualCollectionSheetFaltDataMapper mapper = new IndividualCollectionSheetFaltDataMapper(checkForOfficeId,
checkForStaffId);
final SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("dueDate", transactionDateStr).addValue(
"officeHierarchy", officeHierarchy);
if (checkForOfficeId) {
((MapSqlParameterSource) namedParameters).addValue("officeId", officeId);
}
if (checkForStaffId) {
((MapSqlParameterSource) namedParameters).addValue("staffId", staffId);
}
final Collection<IndividualCollectionSheetLoanFlatData> collectionSheetFlatDatas = this.namedParameterjdbcTemplate.query(
mapper.sqlSchema(), namedParameters, mapper);
IndividualMandatorySavingsCollectionsheetExtractor mandatorySavingsExtractor = new IndividualMandatorySavingsCollectionsheetExtractor(
checkForOfficeId, checkForStaffId);
// mandatory savings data for collection sheet
Collection<IndividualClientData> clientData = this.namedParameterjdbcTemplate.query(
mandatorySavingsExtractor.collectionSheetSchema(), namedParameters, mandatorySavingsExtractor);
// merge savings data into loan data
mergeLoanData(collectionSheetFlatDatas, (List<IndividualClientData>) clientData);
Collection<CodeValueData> paymentOptions = this.codeValueReadPlatformService
.retrieveCodeValuesByCode(PaymentDetailConstants.paymentTypeCodeName);
return IndividualCollectionSheetData.instance(transactionDate, clientData, paymentOptions);
}
private static final class IndividualCollectionSheetFaltDataMapper implements RowMapper<IndividualCollectionSheetLoanFlatData> {
private final String sql;
public IndividualCollectionSheetFaltDataMapper(final boolean checkForOfficeId, final boolean checkforStaffId) {
StringBuilder sb = new StringBuilder();
sb.append("SELECT loandata.*, sum(lc.amount_outstanding_derived) as chargesDue ");
sb.append("from (SELECT cl.display_name As clientName, ");
sb.append("cl.id As clientId, ln.id As loanId, ln.account_no As accountId, ln.loan_status_id As accountStatusId,");
sb.append(" pl.short_name As productShortName, ln.product_id As productId, ");
sb.append("ln.currency_code as currencyCode, ln.currency_digits as currencyDigits, ln.currency_multiplesof as inMultiplesOf, ");
sb.append("rc.`name` as currencyName, rc.display_symbol as currencyDisplaySymbol, rc.internationalized_name_code as currencyNameCode, ");
sb.append("if(ln.loan_status_id = 200 , ln.principal_amount , null) As disbursementAmount, ");
sb.append("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, ");
sb.append("ln.principal_repaid_derived As principalPaid, ");
sb.append("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, ");
sb.append("ln.interest_repaid_derived As interestPaid ");
sb.append("FROM m_loan ln ");
sb.append("JOIN m_client cl ON cl.id = ln.client_id ");
sb.append("LEFT JOIN m_office of ON of.id = cl.office_id AND of.hierarchy like :officeHierarchy ");
sb.append("LEFT JOIN m_product_loan pl ON pl.id = ln.product_id ");
sb.append("LEFT JOIN m_currency rc on rc.`code` = ln.currency_code ");
sb.append("JOIN m_loan_repayment_schedule ls ON ls.loan_id = ln.id AND ls.completed_derived = 0 AND ls.duedate <= :dueDate ");
sb.append("where ");
if (checkForOfficeId) {
sb.append("of.id = :officeId and ");
}
if (checkforStaffId) {
sb.append("ln.loan_officer_id = :staffId and ");
}
sb.append("(ln.loan_status_id = 200 or ln.loan_status_id = 300) ");
sb.append("and ln.group_id is null GROUP BY cl.id , ln.id ORDER BY cl.id , ln.id ) loandata ");
sb.append("LEFT JOIN m_loan_charge lc ON lc.loan_id = loandata.loanId AND lc.is_paid_derived = 0 AND lc.is_active = 1 AND ( lc.due_for_collection_as_of_date <= :dueDate OR lc.charge_time_enum = 1) ");
sb.append("GROUP BY loandata.clientId, loandata.loanId ORDER BY loandata.clientId, loandata.loanId ");
sql = sb.toString();
}
public String sqlSchema() {
return sql;
}
@Override
public IndividualCollectionSheetLoanFlatData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException {
final String clientName = rs.getString("clientName");
final Long clientId = JdbcSupport.getLong(rs, "clientId");
final Long loanId = JdbcSupport.getLong(rs, "loanId");
final String accountId = rs.getString("accountId");
final Integer accountStatusId = JdbcSupport.getInteger(rs, "accountStatusId");
final String productShortName = rs.getString("productShortName");
final Long productId = JdbcSupport.getLong(rs, "productId");
final String currencyCode = rs.getString("currencyCode");
final String currencyName = rs.getString("currencyName");
final String currencyNameCode = rs.getString("currencyNameCode");
final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
final Integer inMultiplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
CurrencyData currencyData = null;
if (currencyCode != null) {
currencyData = new CurrencyData(currencyCode, currencyName, currencyDigits, inMultiplesOf, currencyDisplaySymbol,
currencyNameCode);
}
final BigDecimal disbursementAmount = rs.getBigDecimal("disbursementAmount");
final BigDecimal principalDue = rs.getBigDecimal("principalDue");
final BigDecimal principalPaid = rs.getBigDecimal("principalPaid");
final BigDecimal interestDue = rs.getBigDecimal("interestDue");
final BigDecimal interestPaid = rs.getBigDecimal("interestPaid");
final BigDecimal chargesDue = rs.getBigDecimal("chargesDue");
return new IndividualCollectionSheetLoanFlatData(clientName, clientId, loanId, accountId, accountStatusId, productShortName,
productId, currencyData, disbursementAmount, principalDue, principalPaid, interestDue, interestPaid, chargesDue);
}
}
private static final class IndividualMandatorySavingsCollectionsheetExtractor implements
ResultSetExtractor<Collection<IndividualClientData>> {
private final SavingsDueDataMapper savingsDueDataMapper = new SavingsDueDataMapper();
private final String sql;
public IndividualMandatorySavingsCollectionsheetExtractor(final boolean checkForOfficeId, final boolean checkforStaffId) {
final StringBuffer sb = new StringBuffer(400);
sb.append("SELECT cl.display_name As clientName, cl.id As clientId, ");
sb.append("sa.id As savingsId, sa.account_no As accountId, sa.status_enum As accountStatusId, ");
sb.append("sp.short_name As productShortName, sp.id As productId, ");
sb.append("sa.currency_code as currencyCode, sa.currency_digits as currencyDigits, sa.currency_multiplesof as inMultiplesOf, ");
sb.append("rc.`name` as currencyName, rc.display_symbol as currencyDisplaySymbol, rc.internationalized_name_code as currencyNameCode, ");
sb.append("sum(ifnull(mss.deposit_amount,0) - ifnull(mss.deposit_amount_completed_derived,0)) as dueAmount ");
sb.append("FROM m_savings_account sa ");
sb.append("JOIN m_client cl ON cl.id = sa.client_id ");
sb.append("JOIN m_savings_product sp ON sa.product_id=sp.id ");
sb.append("JOIN m_deposit_account_recurring_detail dard ON sa.id = dard.savings_account_id AND dard.is_mandatory = true AND dard.is_calendar_inherited = false ");
sb.append("JOIN m_mandatory_savings_schedule mss ON mss.savings_account_id=sa.id AND mss.completed_derived = 0 AND mss.duedate <= :dueDate ");
sb.append("LEFT JOIN m_office of ON of.id = cl.office_id AND of.hierarchy like :officeHierarchy ");
sb.append("LEFT JOIN m_currency rc on rc.`code` = sa.currency_code ");
sb.append("WHERE sa.status_enum=300 and sa.group_id is null ");
sb.append("and (cl.status_enum = 300 or (cl.status_enum = 600 and cl.closedon_date >= :dueDate)) ");
if (checkForOfficeId) {
sb.append("and of.id = :officeId ");
}
if (checkforStaffId) {
sb.append("and sa.field_officer_id = :staffId ");
}
sb.append("GROUP BY cl.id , sa.id ORDER BY cl.id , sa.id ");
this.sql = sb.toString();
}
public String collectionSheetSchema() {
return this.sql;
}
@SuppressWarnings("null")
@Override
public Collection<IndividualClientData> extractData(ResultSet rs) throws SQLException, DataAccessException {
List<IndividualClientData> clientData = new ArrayList<>();
int rowNum = 0;
IndividualClientData client = null;
Long previousClientId = null;
while (rs.next()) {
final Long clientId = JdbcSupport.getLong(rs, "clientId");
if (previousClientId == null || clientId.compareTo(previousClientId) != 0) {
final String clientName = rs.getString("clientName");
client = IndividualClientData.instance(clientId, clientName);
client = IndividualClientData.withSavings(client, new ArrayList<SavingsDueData>());
clientData.add(client);
previousClientId = clientId;
}
SavingsDueData saving = savingsDueDataMapper.mapRow(rs, rowNum);
client.addSavings(saving);
rowNum++;
}
return clientData;
}
}
private void mergeLoanData(final Collection<IndividualCollectionSheetLoanFlatData> loanFlatDatas, List<IndividualClientData> clientDatas) {
IndividualClientData clientSavingsData = null;
for (IndividualCollectionSheetLoanFlatData loanFlatData : loanFlatDatas) {
IndividualClientData clientData = loanFlatData.getClientData();
if (clientSavingsData == null || !clientSavingsData.equals(clientData)) {
if (clientDatas.contains(clientData)) {
final int index = clientDatas.indexOf(clientData);
if (index < 0) return;
clientSavingsData = clientDatas.get(index);
clientSavingsData.setLoans(new ArrayList<LoanDueData>());
} else {
clientSavingsData = clientData;
clientSavingsData.setLoans(new ArrayList<LoanDueData>());
clientDatas.add(clientSavingsData);
}
}
clientSavingsData.addLoans(loanFlatData.getLoanDueData());
}
}
} }
@@ -11,4 +11,6 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
public interface CollectionSheetWritePlatformService { public interface CollectionSheetWritePlatformService {
CommandProcessingResult updateCollectionSheet(JsonCommand command); CommandProcessingResult updateCollectionSheet(JsonCommand command);
CommandProcessingResult saveIndividualCollectionSheet(JsonCommand command);
} }
@@ -5,8 +5,10 @@
*/ */
package org.mifosplatform.portfolio.collectionsheet.service; package org.mifosplatform.portfolio.collectionsheet.service;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
@@ -20,8 +22,11 @@ import org.mifosplatform.portfolio.collectionsheet.serialization.CollectionSheet
import org.mifosplatform.portfolio.collectionsheet.serialization.CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer; import org.mifosplatform.portfolio.collectionsheet.serialization.CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.loanaccount.service.LoanWritePlatformService; import org.mifosplatform.portfolio.loanaccount.service.LoanWritePlatformService;
import org.mifosplatform.portfolio.meeting.service.MeetingWritePlatformService; import org.mifosplatform.portfolio.meeting.service.MeetingWritePlatformService;
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetailAssembler;
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionDTO; import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionDTO;
import org.mifosplatform.portfolio.savings.domain.DepositAccountAssembler; import org.mifosplatform.portfolio.savings.domain.DepositAccountAssembler;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransaction;
import org.mifosplatform.portfolio.savings.service.DepositAccountWritePlatformService; import org.mifosplatform.portfolio.savings.service.DepositAccountWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -36,6 +41,7 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
private final MeetingWritePlatformService meetingWritePlatformService; private final MeetingWritePlatformService meetingWritePlatformService;
private final DepositAccountAssembler accountAssembler; private final DepositAccountAssembler accountAssembler;
private final DepositAccountWritePlatformService accountWritePlatformService; private final DepositAccountWritePlatformService accountWritePlatformService;
private final PaymentDetailAssembler paymentDetailAssembler;
@Autowired @Autowired
public CollectionSheetWritePlatformServiceJpaRepositoryImpl(final LoanWritePlatformService loanWritePlatformService, public CollectionSheetWritePlatformServiceJpaRepositoryImpl(final LoanWritePlatformService loanWritePlatformService,
@@ -43,7 +49,7 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
final CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer bulkDisbursalCommandFromApiJsonDeserializer, final CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer bulkDisbursalCommandFromApiJsonDeserializer,
final CollectionSheetTransactionDataValidator transactionDataValidator, final CollectionSheetTransactionDataValidator transactionDataValidator,
final MeetingWritePlatformService meetingWritePlatformService, final DepositAccountAssembler accountAssembler, final MeetingWritePlatformService meetingWritePlatformService, final DepositAccountAssembler accountAssembler,
final DepositAccountWritePlatformService accountWritePlatformService) { final DepositAccountWritePlatformService accountWritePlatformService, final PaymentDetailAssembler paymentDetailAssembler) {
this.loanWritePlatformService = loanWritePlatformService; this.loanWritePlatformService = loanWritePlatformService;
this.bulkRepaymentCommandFromApiJsonDeserializer = bulkRepaymentCommandFromApiJsonDeserializer; this.bulkRepaymentCommandFromApiJsonDeserializer = bulkRepaymentCommandFromApiJsonDeserializer;
this.bulkDisbursalCommandFromApiJsonDeserializer = bulkDisbursalCommandFromApiJsonDeserializer; this.bulkDisbursalCommandFromApiJsonDeserializer = bulkDisbursalCommandFromApiJsonDeserializer;
@@ -51,6 +57,7 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
this.meetingWritePlatformService = meetingWritePlatformService; this.meetingWritePlatformService = meetingWritePlatformService;
this.accountAssembler = accountAssembler; this.accountAssembler = accountAssembler;
this.accountWritePlatformService = accountWritePlatformService; this.accountWritePlatformService = accountWritePlatformService;
this.paymentDetailAssembler = paymentDetailAssembler;
} }
@Override @Override
@@ -67,11 +74,12 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
changes.put("note", noteText); changes.put("note", noteText);
} }
changes.putAll(updateBulkReapayments(command)); final PaymentDetail paymentDetail = this.paymentDetailAssembler.fetchPaymentDetail(command.parsedJson().getAsJsonObject());
changes.putAll(updateBulkReapayments(command, paymentDetail));
changes.putAll(updateBulkDisbursals(command)); changes.putAll(updateBulkDisbursals(command));
changes.putAll(updateBulkMandatorySavingsDuePayments(command)); changes.putAll(updateBulkMandatorySavingsDuePayments(command, paymentDetail));
this.meetingWritePlatformService.updateCollectionSheetAttendance(command); this.meetingWritePlatformService.updateCollectionSheetAttendance(command);
@@ -82,10 +90,39 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
.with(changes).with(changes).build(); .with(changes).with(changes).build();
} }
private Map<String, Object> updateBulkReapayments(final JsonCommand command) { @Override
public CommandProcessingResult saveIndividualCollectionSheet(final JsonCommand command) {
this.transactionDataValidator.validateIndividualCollectionSheet(command);
final Map<String, Object> changes = new HashMap<>();
changes.put("locale", command.locale());
changes.put("dateFormat", command.dateFormat());
final String noteText = command.stringValueOfParameterNamed("note");
if (StringUtils.isNotBlank(noteText)) {
changes.put("note", noteText);
}
final PaymentDetail paymentDetail = null;
changes.putAll(updateBulkReapayments(command, paymentDetail));
changes.putAll(updateBulkDisbursals(command));
changes.putAll(updateBulkMandatorySavingsDuePayments(command, paymentDetail));
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(command.entityId()) //
.withGroupId(command.entityId()) //
.with(changes).with(changes).build();
}
private Map<String, Object> updateBulkReapayments(final JsonCommand command, final PaymentDetail paymentDetail) {
final Map<String, Object> changes = new HashMap<>(); final Map<String, Object> changes = new HashMap<>();
final CollectionSheetBulkRepaymentCommand bulkRepaymentCommand = this.bulkRepaymentCommandFromApiJsonDeserializer final CollectionSheetBulkRepaymentCommand bulkRepaymentCommand = this.bulkRepaymentCommandFromApiJsonDeserializer
.commandFromApiJson(command.json()); .commandFromApiJson(command.json(), paymentDetail);
changes.putAll(this.loanWritePlatformService.makeLoanBulkRepayment(bulkRepaymentCommand)); changes.putAll(this.loanWritePlatformService.makeLoanBulkRepayment(bulkRepaymentCommand));
return changes; return changes;
} }
@@ -98,20 +135,21 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
return changes; return changes;
} }
private Map<String, Object> updateBulkMandatorySavingsDuePayments(final JsonCommand command) { private Map<String, Object> updateBulkMandatorySavingsDuePayments(final JsonCommand command, final PaymentDetail paymentDetail) {
final Map<String, Object> changes = new HashMap<>(); final Map<String, Object> changes = new HashMap<>();
final Collection<SavingsAccountTransactionDTO> savingsTransactions = this.accountAssembler.assembleBulkMandatorySavingsAccountTransactionDTOs(command); final Collection<SavingsAccountTransactionDTO> savingsTransactions = this.accountAssembler
.assembleBulkMandatorySavingsAccountTransactionDTOs(command, paymentDetail);
List<Long> depositTransactionIds = new ArrayList<>();
for (SavingsAccountTransactionDTO savingsAccountTransactionDTO : savingsTransactions) { for (SavingsAccountTransactionDTO savingsAccountTransactionDTO : savingsTransactions) {
try { try {
this.accountWritePlatformService.mandatorySavingsAccountDeposit(savingsAccountTransactionDTO); SavingsAccountTransaction savingsAccountTransaction = this.accountWritePlatformService.mandatorySavingsAccountDeposit(savingsAccountTransactionDTO);
changes.put("savingsAccountId", savingsAccountTransactionDTO.getSavingsAccountId()); depositTransactionIds.add(savingsAccountTransaction.getId());
changes.put("transationAmount", savingsAccountTransactionDTO.getTransactionAmount());
} catch (Exception e) { } catch (Exception e) {
// TODO: handle exception // TODO: handle exception
} }
} }
changes.put("SavingsTransactions", depositTransactionIds);
return changes; return changes;
} }
} }
@@ -9,7 +9,6 @@ import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@@ -124,7 +123,6 @@ import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionRepository; import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionRepository;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionType; import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionType;
import org.mifosplatform.portfolio.loanaccount.exception.InvalidPaidInAdvanceAmountException; import org.mifosplatform.portfolio.loanaccount.exception.InvalidPaidInAdvanceAmountException;
import org.mifosplatform.portfolio.loanaccount.exception.InvalidRefundDateException;
import org.mifosplatform.portfolio.loanaccount.exception.LoanDisbursalException; import org.mifosplatform.portfolio.loanaccount.exception.LoanDisbursalException;
import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerAssignmentException; import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerAssignmentException;
import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerUnassignmentException; import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerUnassignmentException;
@@ -761,21 +759,22 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final boolean isRecoveryRepayment = false; final boolean isRecoveryRepayment = false;
if (repaymentCommand == null) { return changes; } if (repaymentCommand == null) { return changes; }
List<Long> transactionIds = new ArrayList<>();
boolean isAccountTransfer = false; boolean isAccountTransfer = false;
for (final SingleRepaymentCommand singleLoanRepaymentCommand : repaymentCommand) { for (final SingleRepaymentCommand singleLoanRepaymentCommand : repaymentCommand) {
/****
* TODO Vishwas, have a re-look at this implementation, defaulting
* it to null for now
***/
final Loan loan = this.loanAssembler.assembleFrom(singleLoanRepaymentCommand.getLoanId()); final Loan loan = this.loanAssembler.assembleFrom(singleLoanRepaymentCommand.getLoanId());
final PaymentDetail paymentDetail = null; final PaymentDetail paymentDetail = singleLoanRepaymentCommand.getPaymentDetail();
if (paymentDetail != null && paymentDetail.getId() == null) {
this.paymentDetailWritePlatformService.persistPaymentDetail(paymentDetail);
}
final CommandProcessingResultBuilder commandProcessingResultBuilder = new CommandProcessingResultBuilder(); final CommandProcessingResultBuilder commandProcessingResultBuilder = new CommandProcessingResultBuilder();
this.loanAccountDomainService.makeRepayment(loan, commandProcessingResultBuilder, bulkRepaymentCommand.getTransactionDate(), LoanTransaction loanTransaction = this.loanAccountDomainService.makeRepayment(loan, commandProcessingResultBuilder, bulkRepaymentCommand.getTransactionDate(),
singleLoanRepaymentCommand.getTransactionAmount(), paymentDetail, bulkRepaymentCommand.getNote(), null, singleLoanRepaymentCommand.getTransactionAmount(), paymentDetail, bulkRepaymentCommand.getNote(), null,
isRecoveryRepayment, isAccountTransfer); isRecoveryRepayment, isAccountTransfer);
transactionIds.add(loanTransaction.getId());
changes.put("bulkTransactions", singleLoanRepaymentCommand);
} }
changes.put("loanTransactions", transactionIds);
return changes; return changes;
} }
@@ -1971,19 +1970,18 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
existingTransactionIds, existingReversedTransactionIds, isAccountTransfer); existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData); this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
} }
@Transactional @Transactional
@Override @Override
public void applyMeetingDateChanges(final Calendar calendar, final Collection<CalendarInstance> loanCalendarInstances) { public void applyMeetingDateChanges(final Calendar calendar, final Collection<CalendarInstance> loanCalendarInstances) {
final Boolean reschedulebasedOnMeetingDates = null; final Boolean reschedulebasedOnMeetingDates = null;
final LocalDate presentMeetingDate = null; final LocalDate presentMeetingDate = null;
final LocalDate newMeetingDate = null; final LocalDate newMeetingDate = null;
applyMeetingDateChanges(calendar, loanCalendarInstances, reschedulebasedOnMeetingDates, presentMeetingDate, newMeetingDate); applyMeetingDateChanges(calendar, loanCalendarInstances, reschedulebasedOnMeetingDates, presentMeetingDate, newMeetingDate);
} }
@Transactional @Transactional
@Override @Override
@@ -2011,16 +2009,15 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
throw new CalendarParameterUpdateNotSupportedException("jlg.loan.recalculation", defaultUserMessage); throw new CalendarParameterUpdateNotSupportedException("jlg.loan.recalculation", defaultUserMessage);
} }
holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan.getDisbursementDate().toDate()); holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan.getDisbursementDate().toDate());
if(reschedulebasedOnMeetingDates != null && reschedulebasedOnMeetingDates ){ if (reschedulebasedOnMeetingDates != null && reschedulebasedOnMeetingDates) {
loan.updateLoanRepaymentScheduleDates(calendar.getStartDateLocalDate(), calendar.getRecurrence(), isHolidayEnabled, loan.updateLoanRepaymentScheduleDates(calendar.getStartDateLocalDate(), calendar.getRecurrence(), isHolidayEnabled,
holidays, workingDays, reschedulebasedOnMeetingDates, presentMeetingDate, newMeetingDate); holidays, workingDays, reschedulebasedOnMeetingDates, presentMeetingDate, newMeetingDate);
}else{ } else {
loan.updateLoanRepaymentScheduleDates(calendar.getStartDateLocalDate(), calendar.getRecurrence(), isHolidayEnabled, loan.updateLoanRepaymentScheduleDates(calendar.getStartDateLocalDate(), calendar.getRecurrence(), isHolidayEnabled,
holidays, workingDays); holidays, workingDays);
} }
saveLoanWithDataIntegrityViolationChecks(loan); saveLoanWithDataIntegrityViolationChecks(loan);
} }
} }
@@ -2708,7 +2705,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
} }
return installments; return installments;
} }
@Override @Override
@Transactional @Transactional
public CommandProcessingResult makeLoanRefund(Long loanId, JsonCommand command) { public CommandProcessingResult makeLoanRefund(Long loanId, JsonCommand command) {
@@ -2718,11 +2715,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate"); final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate");
//checkRefundDateIsAfterAtLeastOneRepayment(loanId, transactionDate); // checkRefundDateIsAfterAtLeastOneRepayment(loanId, transactionDate);
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount"); final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount");
checkIfLoanIsPaidInAdvance(loanId, transactionAmount); checkIfLoanIsPaidInAdvance(loanId, transactionAmount);
final Map<String, Object> changes = new LinkedHashMap<String, Object>(); final Map<String, Object> changes = new LinkedHashMap<String, Object>();
changes.put("transactionDate", command.stringValueOfParameterNamed("transactionDate")); changes.put("transactionDate", command.stringValueOfParameterNamed("transactionDate"));
changes.put("transactionAmount", command.stringValueOfParameterNamed("transactionAmount")); changes.put("transactionAmount", command.stringValueOfParameterNamed("transactionAmount"));
@@ -2748,15 +2745,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
} }
private void checkIfLoanIsPaidInAdvance(final Long loanId,final BigDecimal transactionAmount) { private void checkIfLoanIsPaidInAdvance(final Long loanId, final BigDecimal transactionAmount) {
BigDecimal overpaid = this.loanReadPlatformService.retrieveTotalPaidInAdvance(loanId).getPaidInAdvance(); BigDecimal overpaid = this.loanReadPlatformService.retrieveTotalPaidInAdvance(loanId).getPaidInAdvance();
if(overpaid == null || overpaid.equals(new BigDecimal(0)) || transactionAmount.floatValue() > overpaid.floatValue()) { if (overpaid == null || overpaid.equals(new BigDecimal(0)) || transactionAmount.floatValue() > overpaid.floatValue()) {
if(overpaid == null) if (overpaid == null) overpaid = BigDecimal.ZERO;
overpaid = BigDecimal.ZERO;
throw new InvalidPaidInAdvanceAmountException(overpaid.toPlainString()); throw new InvalidPaidInAdvanceAmountException(overpaid.toPlainString());
} }
} }
private AppUser getAppUserIfPresent() { private AppUser getAppUserIfPresent() {
AppUser user = null; AppUser user = null;
@@ -76,6 +76,11 @@ public final class PaymentDetail extends AbstractPersistable<Long> {
return paymentDetail; return paymentDetail;
} }
public static PaymentDetail instance(final CodeValue paymentType, final String accountNumber, final String checkNumber,
final String routingCode, final String receiptNumber, final String bankNumber) {
return new PaymentDetail(paymentType, accountNumber, checkNumber, routingCode, receiptNumber, bankNumber);
}
private PaymentDetail(final CodeValue paymentType, final String accountNumber, final String checkNumber, final String routingCode, private PaymentDetail(final CodeValue paymentType, final String accountNumber, final String checkNumber, final String routingCode,
final String receiptNumber, final String bankNumber) { final String receiptNumber, final String bankNumber) {
this.paymentType = paymentType; this.paymentType = paymentType;
@@ -0,0 +1,43 @@
/**
* 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.paymentdetail.domain;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.codes.domain.CodeValueRepositoryWrapper;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.portfolio.paymentdetail.PaymentDetailConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.google.gson.JsonObject;
@Service
public class PaymentDetailAssembler {
private final FromJsonHelper fromApiJsonHelper;
private final CodeValueRepositoryWrapper codeValueRepositoryWrapper;
@Autowired
public PaymentDetailAssembler(final FromJsonHelper fromApiJsonHelper, final CodeValueRepositoryWrapper codeValueRepositoryWrapper) {
this.fromApiJsonHelper = fromApiJsonHelper;
this.codeValueRepositoryWrapper = codeValueRepositoryWrapper;
}
public PaymentDetail fetchPaymentDetail(final JsonObject json) {
final Long paymentTypeId = this.fromApiJsonHelper.extractLongNamed(PaymentDetailConstants.paymentTypeParamName, json);
if (paymentTypeId == null) { return null; }
final CodeValue paymentType = this.codeValueRepositoryWrapper.findOneByCodeNameAndIdWithNotFoundDetection(
PaymentDetailConstants.paymentTypeCodeName, paymentTypeId);
final String accountNumber = this.fromApiJsonHelper.extractStringNamed(PaymentDetailConstants.accountNumberParamName, json);
final String checkNumber = this.fromApiJsonHelper.extractStringNamed(PaymentDetailConstants.checkNumberParamName, json);
final String routingCode = this.fromApiJsonHelper.extractStringNamed(PaymentDetailConstants.routingCodeParamName, json);
final String receiptNumber = this.fromApiJsonHelper.extractStringNamed(PaymentDetailConstants.receiptNumberParamName, json);
final String bankNumber = this.fromApiJsonHelper.extractStringNamed(PaymentDetailConstants.bankNumberParamName, json);
return PaymentDetail.instance(paymentType, accountNumber, checkNumber, routingCode, receiptNumber, bankNumber);
}
}
@@ -31,7 +31,6 @@ public class PaymentDetailWritePlatformServiceJpaRepositoryImpl implements Payme
} }
@Override @Override
@Transactional
public PaymentDetail createPaymentDetail(final JsonCommand command, final Map<String, Object> changes) { public PaymentDetail createPaymentDetail(final JsonCommand command, final Map<String, Object> changes) {
final Long paymentTypeId = command.longValueOfParameterNamed(PaymentDetailConstants.paymentTypeParamName); final Long paymentTypeId = command.longValueOfParameterNamed(PaymentDetailConstants.paymentTypeParamName);
if (paymentTypeId == null) { return null; } if (paymentTypeId == null) { return null; }
@@ -24,8 +24,7 @@ public class SavingsAccountTransactionDTO {
private final AppUser appUser; private final AppUser appUser;
public SavingsAccountTransactionDTO(final DateTimeFormatter formatter, final LocalDate transactionDate, public SavingsAccountTransactionDTO(final DateTimeFormatter formatter, final LocalDate transactionDate,
final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final Date createdDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final Date createdDate, final AppUser appUser) {
final AppUser appUser) {
this.formatter = formatter; this.formatter = formatter;
this.transactionDate = transactionDate; this.transactionDate = transactionDate;
this.transactionAmount = transactionAmount; this.transactionAmount = transactionAmount;
@@ -79,9 +78,8 @@ public class SavingsAccountTransactionDTO {
public Long getSavingsAccountId() { public Long getSavingsAccountId() {
return this.savingsAccountId; return this.savingsAccountId;
} }
public AppUser getAppUser() {
return this.appUser;
}
public AppUser getAppUser() {
return this.appUser;
}
} }
@@ -48,6 +48,8 @@ import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.DateTimeFormatter;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.codes.domain.CodeValueRepositoryWrapper;
import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
@@ -66,7 +68,9 @@ import org.mifosplatform.portfolio.group.exception.CenterNotActiveException;
import org.mifosplatform.portfolio.group.exception.ClientNotInGroupException; import org.mifosplatform.portfolio.group.exception.ClientNotInGroupException;
import org.mifosplatform.portfolio.group.exception.GroupNotActiveException; import org.mifosplatform.portfolio.group.exception.GroupNotActiveException;
import org.mifosplatform.portfolio.interestratechart.domain.InterestRateChart; import org.mifosplatform.portfolio.interestratechart.domain.InterestRateChart;
import org.mifosplatform.portfolio.paymentdetail.PaymentDetailConstants;
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail; import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetailAssembler;
import org.mifosplatform.portfolio.savings.DepositAccountOnClosureType; import org.mifosplatform.portfolio.savings.DepositAccountOnClosureType;
import org.mifosplatform.portfolio.savings.DepositAccountType; import org.mifosplatform.portfolio.savings.DepositAccountType;
import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType; import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
@@ -101,6 +105,7 @@ public class DepositAccountAssembler {
private final SavingsAccountChargeAssembler savingsAccountChargeAssembler; private final SavingsAccountChargeAssembler savingsAccountChargeAssembler;
private final FromJsonHelper fromApiJsonHelper; private final FromJsonHelper fromApiJsonHelper;
private final DepositProductAssembler depositProductAssembler; private final DepositProductAssembler depositProductAssembler;
private final PaymentDetailAssembler paymentDetailAssembler;
@Autowired @Autowired
public DepositAccountAssembler(final SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper, public DepositAccountAssembler(final SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper,
@@ -110,7 +115,8 @@ public class DepositAccountAssembler {
final SavingsAccountChargeAssembler savingsAccountChargeAssembler, final FromJsonHelper fromApiJsonHelper, final SavingsAccountChargeAssembler savingsAccountChargeAssembler, final FromJsonHelper fromApiJsonHelper,
final DepositProductAssembler depositProductAssembler, final DepositProductAssembler depositProductAssembler,
final RecurringDepositProductRepository recurringDepositProductRepository, final RecurringDepositProductRepository recurringDepositProductRepository,
final AccountTransfersReadPlatformService accountTransfersReadPlatformService, final PlatformSecurityContext context) { final AccountTransfersReadPlatformService accountTransfersReadPlatformService, final PlatformSecurityContext context,
final PaymentDetailAssembler paymentDetailAssembler) {
this.savingsAccountTransactionSummaryWrapper = savingsAccountTransactionSummaryWrapper; this.savingsAccountTransactionSummaryWrapper = savingsAccountTransactionSummaryWrapper;
this.clientRepository = clientRepository; this.clientRepository = clientRepository;
@@ -124,6 +130,7 @@ public class DepositAccountAssembler {
this.recurringDepositProductRepository = recurringDepositProductRepository; this.recurringDepositProductRepository = recurringDepositProductRepository;
this.savingsHelper = new SavingsHelper(accountTransfersReadPlatformService); this.savingsHelper = new SavingsHelper(accountTransfersReadPlatformService);
this.context = context; this.context = context;
this.paymentDetailAssembler = paymentDetailAssembler;
} }
/** /**
@@ -392,13 +399,12 @@ public class DepositAccountAssembler {
return depositAccountRecurringDetail; return depositAccountRecurringDetail;
} }
public Collection<SavingsAccountTransactionDTO> assembleBulkMandatorySavingsAccountTransactionDTOs(final JsonCommand command) { public Collection<SavingsAccountTransactionDTO> assembleBulkMandatorySavingsAccountTransactionDTOs(final JsonCommand command,final PaymentDetail paymentDetail) {
AppUser user = getAppUserIfPresent(); AppUser user = getAppUserIfPresent();
final String json = command.json(); final String json = command.json();
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final JsonElement element = this.fromApiJsonHelper.parse(json); final JsonElement element = this.fromApiJsonHelper.parse(json);
final Collection<SavingsAccountTransactionDTO> savingsAccountTransactions = new ArrayList<>(); final Collection<SavingsAccountTransactionDTO> savingsAccountTransactions = new ArrayList<>();
final PaymentDetail paymentDetail = null;
final LocalDate transactionDate = this.fromApiJsonHelper.extractLocalDateNamed(transactionDateParamName, element); final LocalDate transactionDate = this.fromApiJsonHelper.extractLocalDateNamed(transactionDateParamName, element);
final String dateFormat = this.fromApiJsonHelper.extractDateFormatParameter(element.getAsJsonObject()); final String dateFormat = this.fromApiJsonHelper.extractDateFormatParameter(element.getAsJsonObject());
final JsonObject topLevelJsonElement = element.getAsJsonObject(); final JsonObject topLevelJsonElement = element.getAsJsonObject();
@@ -415,8 +421,12 @@ public class DepositAccountAssembler {
final Long savingsId = this.fromApiJsonHelper.extractLongNamed(savingsIdParamName, savingsTransactionElement); final Long savingsId = this.fromApiJsonHelper.extractLongNamed(savingsIdParamName, savingsTransactionElement);
final BigDecimal dueAmount = this.fromApiJsonHelper.extractBigDecimalNamed(transactionAmountParamName, final BigDecimal dueAmount = this.fromApiJsonHelper.extractBigDecimalNamed(transactionAmountParamName,
savingsTransactionElement, locale); savingsTransactionElement, locale);
PaymentDetail detail = paymentDetail;
if (paymentDetail == null) {
detail = this.paymentDetailAssembler.fetchPaymentDetail(savingsTransactionElement);
}
final SavingsAccountTransactionDTO savingsAccountTransactionDTO = new SavingsAccountTransactionDTO(formatter, final SavingsAccountTransactionDTO savingsAccountTransactionDTO = new SavingsAccountTransactionDTO(formatter,
transactionDate, dueAmount, paymentDetail, new Date(), savingsId, user); transactionDate, dueAmount, detail, new Date(), savingsId, user);
savingsAccountTransactions.add(savingsAccountTransactionDTO); savingsAccountTransactions.add(savingsAccountTransactionDTO);
} }
} }
@@ -1286,9 +1286,13 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
boolean isRegularTransaction = false; boolean isRegularTransaction = false;
final RecurringDepositAccount account = (RecurringDepositAccount) this.depositAccountAssembler.assembleFrom( final RecurringDepositAccount account = (RecurringDepositAccount) this.depositAccountAssembler.assembleFrom(
accountTransactionDTO.getSavingsAccountId(), DepositAccountType.RECURRING_DEPOSIT); accountTransactionDTO.getSavingsAccountId(), DepositAccountType.RECURRING_DEPOSIT);
final PaymentDetail paymentDetail = accountTransactionDTO.getPaymentDetail();
if (paymentDetail != null && paymentDetail.getId() == null) {
this.paymentDetailWritePlatformService.persistPaymentDetail(paymentDetail);
}
return this.depositAccountDomainService.handleRDDeposit(account, accountTransactionDTO.getFormatter(), return this.depositAccountDomainService.handleRDDeposit(account, accountTransactionDTO.getFormatter(),
accountTransactionDTO.getTransactionDate(), accountTransactionDTO.getTransactionAmount(), accountTransactionDTO.getTransactionDate(), accountTransactionDTO.getTransactionAmount(), paymentDetail,
accountTransactionDTO.getPaymentDetail(), isRegularTransaction); isRegularTransaction);
} }
private AppUser getAppUserIfPresent() { private AppUser getAppUserIfPresent() {
@@ -0,0 +1,2 @@
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('collection_sheet', 'READ_COLLECTIONSHEET', 'COLLECTIONSHEET', 'READ', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('collection_sheet', 'SAVE_COLLECTIONSHEET', 'COLLECTIONSHEET', 'SAVE', 0);