From c77f3e15f1a856559cf140729f9a04702d371eb4 Mon Sep 17 00:00:00 2001 From: ashok-conflux Date: Wed, 27 Mar 2013 16:22:55 +0530 Subject: [PATCH] Collection sheet UI and bulk update --- .../commands/domain/CommandWrapper.java | 5 + .../service/CommandWrapperBuilder.java | 8 ++ .../SynchronousCommandProcessingService.java | 8 ++ .../api/CollectionSheetApiResource.java | 26 +++- .../CollectionSheetBulkDisbursalCommand.java | 38 ++++++ .../CollectionSheetBulkRepaymentCommand.java | 39 ++++++ .../command/SingleDisbursalCommand.java | 39 ++++++ .../command/SingleRepaymentCommand.java | 39 ++++++ .../data/JLGCollectionSheetData.java | 8 +- .../data/JLGCollectionSheetFlatData.java | 25 ++-- .../collectionsheet/data/LoanDueData.java | 22 ++-- .../UpdateCollectionSheetCommandHandler.java | 28 +++++ ...sbursalCommandFromApiJsonDeserializer.java | 118 ++++++++++++++++++ ...paymentCommandFromApiJsonDeserializer.java | 116 +++++++++++++++++ ...ollectionSheetReadPlatformServiceImpl.java | 28 +++-- .../CollectionSheetWritePlatformService.java | 9 ++ ...WritePlatformServiceJpaRepositoryImpl.java | 79 ++++++++++++ .../service/LoanWritePlatformService.java | 8 ++ ...WritePlatformServiceJpaRepositoryImpl.java | 90 +++++++++++-- .../loanproduct/data/LoanProductData.java | 36 ++++++ 20 files changed, 719 insertions(+), 50 deletions(-) create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/command/CollectionSheetBulkDisbursalCommand.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/command/CollectionSheetBulkRepaymentCommand.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/command/SingleDisbursalCommand.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/command/SingleRepaymentCommand.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/handler/UpdateCollectionSheetCommandHandler.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/serialization/CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/serialization/CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/service/CollectionSheetWritePlatformService.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/service/CollectionSheetWritePlatformServiceJpaRepositoryImpl.java diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java index c7d9a1023..ab83e5f46 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java @@ -463,4 +463,9 @@ public class CommandWrapper { public boolean isGroupResource() { return this.entityName.equalsIgnoreCase("GROUP"); } + + public boolean isCollectionSheetResource(){ + return this.entityName.equals("COLLECTIONSHEET"); + } + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java index 2fced93b2..0dd569546 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java @@ -826,5 +826,13 @@ public class CommandWrapperBuilder { this.loanId = loanId; this.href = "/loans/" + loanId + "/collaterals/" + collateralId; return this; + } + + public CommandWrapperBuilder updateCollectionSheet(final Long groupId) { + this.actionName = "UPDATE"; + this.entityName = "COLLECTIONSHEET"; + this.entityId = groupId; + this.href = "/groups/" + groupId + "/collectionsheet"; + return this; } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java index 66725d859..4a18e74cc 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java @@ -393,6 +393,14 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer } else { throw new UnsupportedCommandException(wrapper.commandName()); } + + } else if (wrapper.isCollectionSheetResource()) { + + if (wrapper.isUpdate()) { + handler = applicationContext.getBean("updateCollectionSheetCommandHandler", NewCommandSourceHandler.class); + } else { + throw new UnsupportedCommandException(wrapper.commandName()); + } } else { throw new UnsupportedCommandException(wrapper.commandName()); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/api/CollectionSheetApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/api/CollectionSheetApiResource.java index c21190920..c82206ea4 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/api/CollectionSheetApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/api/CollectionSheetApiResource.java @@ -6,6 +6,7 @@ import java.util.Set; import javax.ws.rs.Consumes; import javax.ws.rs.GET; +import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @@ -15,7 +16,11 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.UriInfo; import org.joda.time.LocalDate; +import org.mifosplatform.commands.domain.CommandWrapper; +import org.mifosplatform.commands.service.CommandWrapperBuilder; +import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService; import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings; import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer; import org.mifosplatform.infrastructure.core.service.DateUtils; @@ -37,7 +42,7 @@ import org.springframework.stereotype.Component; @Scope("singleton") public class CollectionSheetApiResource { - private final Set COLLECTIONSHEET_DATA_PARAMETERS = new HashSet(Arrays.asList("dueDate", "groups")); + private final Set COLLECTIONSHEET_DATA_PARAMETERS = new HashSet(Arrays.asList("dueDate", "loanProducts", "groups")); /* * dueDate format is ISO 8601 Calendar Date (YYYYMMDD) */ @@ -46,17 +51,18 @@ public class CollectionSheetApiResource { private final CollectionSheetReadPlatformService collectionSheetReadPlatformService; private final ToApiJsonSerializer toApiJsonSerializer; private final ApiRequestParameterHelper apiRequestParameterHelper; - + private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; + @Autowired public CollectionSheetApiResource(final PlatformSecurityContext context, final CollectionSheetReadPlatformService collectionSheetReadPlatformService, - final ToApiJsonSerializer toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper) { + final ToApiJsonSerializer toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper, final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) { this.context = context; this.collectionSheetReadPlatformService = collectionSheetReadPlatformService; this.toApiJsonSerializer = toApiJsonSerializer; this.apiRequestParameterHelper = apiRequestParameterHelper; - + this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; } @GET @@ -72,4 +78,16 @@ public class CollectionSheetApiResource { return this.toApiJsonSerializer.serialize(settings, collectionSheet, this.COLLECTIONSHEET_DATA_PARAMETERS); } + + @POST + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String updateCalendar(@PathParam("groupId") final Long groupId, final String jsonRequestBody) { + + final CommandWrapper commandRequest = new CommandWrapperBuilder().updateCollectionSheet(groupId).withJson(jsonRequestBody).build(); + + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + + return this.toApiJsonSerializer.serialize(result); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/command/CollectionSheetBulkDisbursalCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/command/CollectionSheetBulkDisbursalCommand.java new file mode 100644 index 000000000..ef47670bd --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/command/CollectionSheetBulkDisbursalCommand.java @@ -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.command; + +import org.joda.time.LocalDate; + + +/** + * Immutable command for loan bulk disburse. + */ +public class CollectionSheetBulkDisbursalCommand { + + private final String note; + private final LocalDate transactionDate; + private final SingleDisbursalCommand[] disburseTransactions; + + public CollectionSheetBulkDisbursalCommand(String note, final LocalDate transactionDate, SingleDisbursalCommand[] disburseTransactions) { + this.note = note; + this.transactionDate = transactionDate; + this.disburseTransactions = disburseTransactions; + } + + public String getNote() { + return this.note; + } + + public SingleDisbursalCommand[] getDisburseTransactions() { + return this.disburseTransactions; + } + + public LocalDate getTransactionDate() { + return this.transactionDate; + } + +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/command/CollectionSheetBulkRepaymentCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/command/CollectionSheetBulkRepaymentCommand.java new file mode 100644 index 000000000..747bbc766 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/command/CollectionSheetBulkRepaymentCommand.java @@ -0,0 +1,39 @@ +/** + * 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.command; + +import org.joda.time.LocalDate; + + +/** + * Immutable command for loan bulk repayment. + */ +public class CollectionSheetBulkRepaymentCommand { + + private final String note; + private final LocalDate transactionDate; + private final SingleRepaymentCommand[] repaymentTransactions; + + public CollectionSheetBulkRepaymentCommand(String note, final LocalDate transactionDate, SingleRepaymentCommand[] repaymentTransactions) { + this.note = note; + this.transactionDate = transactionDate; + this.repaymentTransactions = repaymentTransactions; + } + + public String getNote() { + return this.note; + } + + public SingleRepaymentCommand[] getLoanTransactions() { + return this.repaymentTransactions; + } + + + public LocalDate getTransactionDate() { + return this.transactionDate; + } + +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/command/SingleDisbursalCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/command/SingleDisbursalCommand.java new file mode 100644 index 000000000..9a4f8a45f --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/command/SingleDisbursalCommand.java @@ -0,0 +1,39 @@ +/** + * 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.command; + +import java.math.BigDecimal; + +import org.joda.time.LocalDate; + + +/** + * Immutable command for Single loan repayment. + */ +public class SingleDisbursalCommand { + + private final Long loanId; + private final BigDecimal transactionAmount; + private final LocalDate transactionDate; + public SingleDisbursalCommand(Long loanId, BigDecimal transactionAmount, LocalDate transactionDate) { + this.loanId = loanId; + this.transactionAmount = transactionAmount; + this.transactionDate = transactionDate; + } + + public Long getLoanId() { + return this.loanId; + } + + public BigDecimal getTransactionAmount() { + return this.transactionAmount; + } + + public LocalDate getTransactionDate() { + return this.transactionDate; + } + +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/command/SingleRepaymentCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/command/SingleRepaymentCommand.java new file mode 100644 index 000000000..e118c203f --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/command/SingleRepaymentCommand.java @@ -0,0 +1,39 @@ +/** + * 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.command; + +import java.math.BigDecimal; + +import org.joda.time.LocalDate; + + +/** + * Immutable command for Single loan repayment. + */ +public class SingleRepaymentCommand { + + private final Long loanId; + private final BigDecimal transactionAmount; + private final LocalDate transactionDate; + public SingleRepaymentCommand(Long loanId, BigDecimal transactionAmount, LocalDate transactionDate) { + this.loanId = loanId; + this.transactionAmount = transactionAmount; + this.transactionDate = transactionDate; + } + + public Long getLoanId() { + return this.loanId; + } + + public BigDecimal getTransactionAmount() { + return this.transactionAmount; + } + + public LocalDate getTransactionDate() { + return this.transactionDate; + } + +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/data/JLGCollectionSheetData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/data/JLGCollectionSheetData.java index e37c24d62..f7e96af96 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/data/JLGCollectionSheetData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/data/JLGCollectionSheetData.java @@ -8,6 +8,7 @@ package org.mifosplatform.portfolio.collectionsheet.data; import java.util.Collection; import org.joda.time.LocalDate; +import org.mifosplatform.portfolio.loanproduct.data.LoanProductData; /** * Immutable data object for join liability group's collection sheet. @@ -15,10 +16,12 @@ import org.joda.time.LocalDate; public class JLGCollectionSheetData { private final LocalDate dueDate; + private final Collection loanProducts; private final Collection groups; - public JLGCollectionSheetData(final LocalDate date, final Collection groups) { + public JLGCollectionSheetData(final LocalDate date, final Collection loanProducts, final Collection groups) { this.dueDate = date; + this.loanProducts = loanProducts; this.groups = groups; } @@ -30,4 +33,7 @@ public class JLGCollectionSheetData { return this.groups; } + public Collection getLoanProducts() { + return this.loanProducts; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/data/JLGCollectionSheetFlatData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/data/JLGCollectionSheetFlatData.java index 69859f46c..399fb00a3 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/data/JLGCollectionSheetFlatData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/data/JLGCollectionSheetFlatData.java @@ -7,6 +7,8 @@ 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. */ @@ -25,8 +27,7 @@ public class JLGCollectionSheetFlatData { private final Integer accountStatusId; private final String productShortName; private final Long productId; - private final String currencyCode; - private final Integer currencyDigits; + private final CurrencyData currency; private BigDecimal disbursementAmount = BigDecimal.ZERO; private BigDecimal principalDue = BigDecimal.ZERO; private BigDecimal principalPaid = BigDecimal.ZERO; @@ -37,7 +38,7 @@ public class JLGCollectionSheetFlatData { public JLGCollectionSheetFlatData(final String groupName, final Long groupId, final Long staffId, final String staffName, final Long levelId, final String levelName, final String clientName, final Long clientId, final Long loanId, final String accountId, final Integer accountStatusId, final String productShortName, final Long productId, - final String currencyCode, final Integer currencyDigits, final BigDecimal disbursementAmount, final BigDecimal principalDue, + final CurrencyData currency, final BigDecimal disbursementAmount, final BigDecimal principalDue, final BigDecimal principalPaid, final BigDecimal interestDue, final BigDecimal interestPaid, final BigDecimal chargesDue) { this.groupName = groupName; this.groupId = groupId; @@ -52,8 +53,7 @@ public class JLGCollectionSheetFlatData { this.accountStatusId = accountStatusId; this.productShortName = productShortName; this.productId = productId; - this.currencyCode = currencyCode; - this.currencyDigits = currencyDigits; + this.currency = currency; this.disbursementAmount = disbursementAmount; this.principalDue = principalDue; this.principalPaid = principalPaid; @@ -113,13 +113,9 @@ public class JLGCollectionSheetFlatData { public Long getProductId() { return this.productId; } - - public String getCurrencyCode() { - return this.currencyCode; - } - - public Integer getCurrencyDigits() { - return this.currencyDigits; + + public CurrencyData getCurrency() { + return this.currency; } public BigDecimal getDisbursementAmount() { @@ -147,9 +143,8 @@ public class JLGCollectionSheetFlatData { } public LoanDueData getLoanDueData() { - return new LoanDueData(this.loanId, this.accountId, this.accountStatusId, this.productShortName, this.productId, this.currencyCode, - this.currencyDigits, this.disbursementAmount, this.principalDue, this.principalPaid, this.interestDue, this.interestPaid, - this.chargesDue); + 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 ClientLoansData getClientLoansData() { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/data/LoanDueData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/data/LoanDueData.java index 5d598e014..ee76bb8a8 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/data/LoanDueData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/data/LoanDueData.java @@ -7,6 +7,8 @@ package org.mifosplatform.portfolio.collectionsheet.data; import java.math.BigDecimal; +import org.mifosplatform.organisation.monetary.data.CurrencyData; + /** * Immutable data object for representing loan with dues (example: loan is due for disbursement, repayments). */ @@ -17,17 +19,17 @@ public class LoanDueData { private final Integer accountStatusId; private final String productShortName; private final Long productId; - private final String currencyCode; - private final Integer currencyDigits; + 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; + private BigDecimal totalDue = BigDecimal.ZERO; public LoanDueData(final Long loanId, final String accountId, final Integer accountStatusId, final String productShortName, - final Long productId, final String currencyCode, final Integer currencyDigits, final BigDecimal disbursementAmount, + 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.loanId = loanId; @@ -35,14 +37,14 @@ public class LoanDueData { this.accountStatusId = accountStatusId; this.productShortName = productShortName; this.productId = productId; - this.currencyCode = currencyCode; - this.currencyDigits = currencyDigits; + this.currency = currency; this.disbursementAmount = disbursementAmount; this.principalDue = principalDue; this.principalPaid = principalPaid; this.interestDue = interestDue; this.interestPaid = interestPaid; this.chargesDue = chargesDue; + this.totalDue = this.totalDue.add(principalDue).add(interestDue); } public Long getLoanId() { @@ -64,13 +66,9 @@ public class LoanDueData { public Long getProductId() { return this.productId; } - - public String getCurrencyCode() { - return this.currencyCode; - } - - public Integer getCurrencyDigits() { - return this.currencyDigits; + + public CurrencyData getCurrency() { + return this.currency; } public BigDecimal getDisbursementAmount() { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/handler/UpdateCollectionSheetCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/handler/UpdateCollectionSheetCommandHandler.java new file mode 100644 index 000000000..39c2c5d00 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/handler/UpdateCollectionSheetCommandHandler.java @@ -0,0 +1,28 @@ +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 UpdateCollectionSheetCommandHandler implements NewCommandSourceHandler { + + private final CollectionSheetWritePlatformService collectionSheetWritePlatformService; + + @Autowired + public UpdateCollectionSheetCommandHandler(final CollectionSheetWritePlatformService collectionSheetWritePlatformService) { + this.collectionSheetWritePlatformService = collectionSheetWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + + return this.collectionSheetWritePlatformService.updateCollectionSheet(command); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/serialization/CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/serialization/CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer.java new file mode 100644 index 000000000..af5af12e0 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/serialization/CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer.java @@ -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.serialization; + +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.joda.time.LocalDate; +import org.mifosplatform.infrastructure.core.data.ApiParameterError; +import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder; +import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; +import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; +import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer; +import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer; +import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; +import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkDisbursalCommand; +import org.mifosplatform.portfolio.collectionsheet.command.SingleDisbursalCommand; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; + +/** + * Implementation of {@link FromApiJsonDeserializer} for + * {@link CollectionSheetBulkDisbursalCommand}'s. + */ +@Component +public final class CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer { + + private final FromJsonHelper fromApiJsonHelper; + + @Autowired + public CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer(FromJsonHelper fromApiJsonHelper) { + this.fromApiJsonHelper = fromApiJsonHelper; + } + + @Override + public CollectionSheetBulkDisbursalCommand commandFromApiJson(final String json) { + if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } + + final Type typeOfMap = new TypeToken>() {}.getType(); + //TODO: AA need to refactor transactionDate and actualDisbursementDate + //actualDisbursementDate used in Loan.disburse() + final Set supportedParameters = new HashSet(Arrays.asList("transactionDate", "actualDisbursementDate", "bulkRepaymentTransactions", "bulkDisbursementTransactions", "note", + "locale", "dateFormat")); + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters); + + final JsonElement element = this.fromApiJsonHelper.parse(json); + + final LocalDate transactionDate = fromApiJsonHelper.extractLocalDateNamed("transactionDate", element); + + final String note = fromApiJsonHelper.extractStringNamed("note", element); + + final JsonObject topLevelJsonElement = element.getAsJsonObject(); + final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement); + + SingleDisbursalCommand[] loanDisbursementTransactions = null; + + if (element.isJsonObject()) { + if (topLevelJsonElement.has("bulkDisbursementTransactions") + && topLevelJsonElement.get("bulkDisbursementTransactions").isJsonArray()) { + final JsonArray array = topLevelJsonElement.get("bulkDisbursementTransactions").getAsJsonArray(); + loanDisbursementTransactions = new SingleDisbursalCommand[array.size()]; + for (int i = 0; i < array.size(); i++) { + final JsonObject loanTransactionElement = array.get(i).getAsJsonObject(); + + final Long loanId = this.fromApiJsonHelper.extractLongNamed("loanId", loanTransactionElement); + final BigDecimal disbursementAmount = this.fromApiJsonHelper.extractBigDecimalNamed("transactionAmount", loanTransactionElement, locale); + loanDisbursementTransactions[i] = new SingleDisbursalCommand(loanId, disbursementAmount, transactionDate); + } + } + } + return new CollectionSheetBulkDisbursalCommand(note, transactionDate, loanDisbursementTransactions); + } + + public void validateBulkDisbursalTransaction(final CollectionSheetBulkDisbursalCommand bulkDisburseCommand) { + + final List dataValidationErrors = new ArrayList(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.bulk.disbursement.transaction"); + + baseDataValidator.reset().parameter("transactionDate").value(bulkDisburseCommand.getTransactionDate()).notNull(); + + if (StringUtils.isNotBlank(bulkDisburseCommand.getNote())) { + baseDataValidator.reset().parameter("note").value(bulkDisburseCommand.getNote()).notExceedingLengthOf(1000); + } + final SingleDisbursalCommand[] loanDisbursements = bulkDisburseCommand.getDisburseTransactions(); + if (loanDisbursements != null) { + for (int i = 0; i < loanDisbursements.length; i++) { + SingleDisbursalCommand singleLoanDisburseCommand = loanDisbursements[i]; + + baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].loan.id").value(singleLoanDisburseCommand.getLoanId()) + .notNull().integerGreaterThanZero(); + baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].disbursement.amount") + .value(singleLoanDisburseCommand.getTransactionAmount()).notNull().zeroOrPositiveAmount(); + } + } + throwExceptionIfValidationWarningsExist(dataValidationErrors); + } + + private void throwExceptionIfValidationWarningsExist(final List dataValidationErrors) { + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); } + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/serialization/CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/serialization/CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer.java new file mode 100644 index 000000000..ae26e034a --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/serialization/CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer.java @@ -0,0 +1,116 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.collectionsheet.serialization; + +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.joda.time.LocalDate; +import org.mifosplatform.infrastructure.core.data.ApiParameterError; +import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder; +import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; +import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; +import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer; +import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer; +import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; +import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkRepaymentCommand; +import org.mifosplatform.portfolio.collectionsheet.command.SingleRepaymentCommand; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; + +/** + * Implementation of {@link FromApiJsonDeserializer} for + * {@link CollectionSheetBulkRepaymentCommand}'s. + */ +@Component +public final class CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer { + + private final FromJsonHelper fromApiJsonHelper; + + @Autowired + public CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer(FromJsonHelper fromApiJsonHelper) { + this.fromApiJsonHelper = fromApiJsonHelper; + } + + @Override + public CollectionSheetBulkRepaymentCommand commandFromApiJson(final String json) { + if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } + + final Type typeOfMap = new TypeToken>() {}.getType(); + final Set supportedParameters = new HashSet(Arrays.asList("transactionDate", "actualDisbursementDate", "bulkRepaymentTransactions", "bulkDisbursementTransactions", "note", + "locale", "dateFormat")); + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters); + + final JsonElement element = this.fromApiJsonHelper.parse(json); + + final LocalDate transactionDate = fromApiJsonHelper.extractLocalDateNamed("transactionDate", element); + + final String note = fromApiJsonHelper.extractStringNamed("note", element); + + final JsonObject topLevelJsonElement = element.getAsJsonObject(); + final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement); + + SingleRepaymentCommand[] loanRepaymentTransactions = null; + + if (element.isJsonObject()) { + if (topLevelJsonElement.has("bulkRepaymentTransactions") + && topLevelJsonElement.get("bulkRepaymentTransactions").isJsonArray()) { + final JsonArray array = topLevelJsonElement.get("bulkRepaymentTransactions").getAsJsonArray(); + loanRepaymentTransactions = new SingleRepaymentCommand[array.size()]; + for (int i = 0; i < array.size(); i++) { + final JsonObject loanTransactionElement = array.get(i).getAsJsonObject(); + + final Long loanId = this.fromApiJsonHelper.extractLongNamed("loanId", loanTransactionElement); + final BigDecimal transactionAmount = this.fromApiJsonHelper.extractBigDecimalNamed("transactionAmount", loanTransactionElement, locale); + loanRepaymentTransactions[i] = new SingleRepaymentCommand(loanId, transactionAmount, transactionDate); + } + } + } + return new CollectionSheetBulkRepaymentCommand(note, transactionDate, loanRepaymentTransactions); + } + + public void validateBulkRepaymentTransaction(final CollectionSheetBulkRepaymentCommand bulkRepaymentCommand) { + + final List dataValidationErrors = new ArrayList(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.bulk.repayment.transaction"); + + baseDataValidator.reset().parameter("transactionDate").value(bulkRepaymentCommand.getTransactionDate()).notNull(); + + if (StringUtils.isNotBlank(bulkRepaymentCommand.getNote())) { + baseDataValidator.reset().parameter("note").value(bulkRepaymentCommand.getNote()).notExceedingLengthOf(1000); + } + + final SingleRepaymentCommand[] loanRepayments = bulkRepaymentCommand.getLoanTransactions(); + if (loanRepayments != null) { + for (int i = 0; i < loanRepayments.length; i++) { + SingleRepaymentCommand singleLoanRepaymentCommand = loanRepayments[i]; + baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].loan.id") + .value(singleLoanRepaymentCommand.getLoanId()).notNull().integerGreaterThanZero(); + baseDataValidator.reset().parameter("bulktransaction" + "[" + i + "].transaction.amount") + .value(singleLoanRepaymentCommand.getTransactionAmount()).notNull().zeroOrPositiveAmount(); + } + } + throwExceptionIfValidationWarningsExist(dataValidationErrors); + } + + private void throwExceptionIfValidationWarningsExist(final List dataValidationErrors) { + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); } + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/service/CollectionSheetReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/service/CollectionSheetReadPlatformServiceImpl.java index 9477c6da0..4341e301d 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/service/CollectionSheetReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/service/CollectionSheetReadPlatformServiceImpl.java @@ -5,12 +5,15 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.joda.time.LocalDate; import org.mifosplatform.infrastructure.core.domain.JdbcSupport; import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; +import org.mifosplatform.organisation.monetary.data.CurrencyData; import org.mifosplatform.portfolio.collectionsheet.data.ClientLoansData; import org.mifosplatform.portfolio.collectionsheet.data.JLGClientsData; import org.mifosplatform.portfolio.collectionsheet.data.JLGCollectionSheetData; @@ -19,6 +22,7 @@ import org.mifosplatform.portfolio.collectionsheet.data.LoanDueData; import org.mifosplatform.portfolio.group.data.GroupData; import org.mifosplatform.portfolio.group.exception.GroupNotFoundException; import org.mifosplatform.portfolio.group.service.GroupReadPlatformServiceImpl; +import org.mifosplatform.portfolio.loanproduct.data.LoanProductData; import org.mifosplatform.useradministration.domain.AppUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.RowMapper; @@ -88,11 +92,12 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe JLGCollectionSheetData jlgCollectionSheetData = null; JLGCollectionSheetFlatData prevCollectioSheetFlatData = null; JLGCollectionSheetFlatData corrCollectioSheetFlatData = null; - + Set loanProducts = new HashSet(); if (jlgCollectionSheetFlatData != null) { for (final JLGCollectionSheetFlatData collectionSheetFlatData : jlgCollectionSheetFlatData) { - + + loanProducts.add(LoanProductData.lookupWithCurrency(collectionSheetFlatData.getProductId(), collectionSheetFlatData.getProductShortName(), collectionSheetFlatData.getCurrency())); corrCollectioSheetFlatData = collectionSheetFlatData; if (firstTime || collectionSheetFlatData.getGroupId().equals(prevGroupId)) { @@ -149,7 +154,7 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe jlgClientsDatas.add(jlgClientsData); - jlgCollectionSheetData = new JLGCollectionSheetData(dueDate, jlgClientsDatas); + jlgCollectionSheetData = new JLGCollectionSheetData(dueDate, loanProducts, jlgClientsDatas); } return jlgCollectionSheetData; @@ -184,12 +189,11 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe + "ln.loan_status_id As accountStatusId, " + "pl.name As productShortName, " + "ln.product_id As productId, " - + "ln.currency_code As currencyCode, " - + "ln.currency_digits As currencyDigits, " + + "ln.currency_code as currencyCode, ln.currency_digits as currencyDigits, rc.`name` as currencyName, rc.display_symbol as currencyDisplaySymbol, rc.internationalized_name_code as currencyNameCode, " + "if(ln.loan_status_id = 200 , ln.principal_amount , null) As disbursementAmount, " - + "sum(ls.principal_amount - ls.principal_completed_derived) As principalDue, " + + "sum(ifnull(ls.principal_amount, 0.0) - ifnull(ls.principal_completed_derived, 0.0)) As principalDue, " + "ln.principal_repaid_derived As principalPaid, " - + "sum(ls.interest_amount - ls.interest_completed_derived) As interestDue, " + + "sum(ifnull(ls.interest_amount, 0.0) - ifnull(ls.interest_completed_derived, 0.0)) As interestDue, " + "ln.interest_repaid_derived As interestPaid, " + "sum(lc.amount_outstanding_derived) as chargesDue " + "FROM m_group gp " @@ -200,6 +204,7 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe + "JOIN m_client cl ON cl.id = gc.client_id " + "LEFT JOIN m_loan ln ON cl.id = ln.client_id AND ln.group_id is not null AND ( ln.loan_status_id = 300 OR ( ln.loan_status_id =200 AND ln.expected_disbursedon_date <= :dueDate )) " + "LEFT JOIN m_product_loan pl ON pl.id = ln.product_id " + + "JOIN m_currency rc on rc.`code` = ln.currency_code " + "LEFT JOIN m_loan_repayment_schedule ls ON ls.loan_id = ln.id AND ls.completed_derived = 0 AND ls.duedate <= :dueDate " + "LEFT JOIN m_loan_charge lc ON lc.loan_id = ln.id AND lc.is_paid_derived = 0 AND ( lc.due_for_collection_as_of_date <= :dueDate OR lc.charge_time_enum = 1) " + "WHERE gp.hierarchy like :hierarchy " + "GROUP BY gp.id ,cl.id , ln.id " + "ORDER BY gp.id , cl.id , ln.id "; @@ -221,8 +226,15 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe 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 CurrencyData currencyData = new CurrencyData(currencyCode, currencyName, currencyDigits, currencyDisplaySymbol, + currencyNameCode); + final BigDecimal disbursementAmount = rs.getBigDecimal("disbursementAmount"); final BigDecimal principalDue = rs.getBigDecimal("principalDue"); final BigDecimal principalPaid = rs.getBigDecimal("principalPaid"); @@ -231,7 +243,7 @@ public class CollectionSheetReadPlatformServiceImpl implements CollectionSheetRe final BigDecimal chargesDue = rs.getBigDecimal("chargesDue"); return new JLGCollectionSheetFlatData(groupName, groupId, staffId, staffName, levelId, levelName, clientName, clientId, loanId, - accountId, accountStatusId, productShortName, productId, currencyCode, currencyDigits, disbursementAmount, + accountId, accountStatusId, productShortName, productId, currencyData, disbursementAmount, principalDue, principalPaid, interestDue, interestPaid, chargesDue); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/service/CollectionSheetWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/service/CollectionSheetWritePlatformService.java new file mode 100644 index 000000000..d5ec4212b --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/service/CollectionSheetWritePlatformService.java @@ -0,0 +1,9 @@ +package org.mifosplatform.portfolio.collectionsheet.service; + +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; + +public interface CollectionSheetWritePlatformService { + + CommandProcessingResult updateCollectionSheet(JsonCommand command); +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/service/CollectionSheetWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/service/CollectionSheetWritePlatformServiceJpaRepositoryImpl.java new file mode 100644 index 000000000..e37c099c3 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/collectionsheet/service/CollectionSheetWritePlatformServiceJpaRepositoryImpl.java @@ -0,0 +1,79 @@ +/** + * 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.service; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; +import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkDisbursalCommand; +import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkRepaymentCommand; +import org.mifosplatform.portfolio.collectionsheet.serialization.CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer; +import org.mifosplatform.portfolio.collectionsheet.serialization.CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer; +import org.mifosplatform.portfolio.loanaccount.service.LoanWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements CollectionSheetWritePlatformService { + + private final LoanWritePlatformService loanWritePlatformService; + private final CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer bulkRepaymentCommandFromApiJsonDeserializer; + private final CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer bulkDisbursalCommandFromApiJsonDeserializer; + + @Autowired + public CollectionSheetWritePlatformServiceJpaRepositoryImpl(LoanWritePlatformService loanWritePlatformService, + CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer bulkRepaymentCommandFromApiJsonDeserializer, + CollectionSheetBulkDisbursalCommandFromApiJsonDeserializer bulkDisbursalCommandFromApiJsonDeserializer) { + this.loanWritePlatformService = loanWritePlatformService; + this.bulkRepaymentCommandFromApiJsonDeserializer = bulkRepaymentCommandFromApiJsonDeserializer; + this.bulkDisbursalCommandFromApiJsonDeserializer = bulkDisbursalCommandFromApiJsonDeserializer; + } + + + @Override + public CommandProcessingResult updateCollectionSheet(JsonCommand command) { + + Map 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); + } + + changes.putAll(updateBulkReapayments(command)); + + changes.putAll(updateBulkDisbursals(command)); + + return new CommandProcessingResultBuilder() // + .withCommandId(command.commandId()) // + .withEntityId(command.entityId()) // + .withGroupId(command.entityId()) // + .with(changes) + .with(changes).build(); + } + + private Map updateBulkReapayments(JsonCommand command) { + Map changes = new HashMap(); + final CollectionSheetBulkRepaymentCommand bulkRepaymentCommand = this.bulkRepaymentCommandFromApiJsonDeserializer.commandFromApiJson(command.json()); + this.bulkRepaymentCommandFromApiJsonDeserializer.validateBulkRepaymentTransaction(bulkRepaymentCommand); + changes.putAll(this.loanWritePlatformService.makeLoanBulkRepayment(bulkRepaymentCommand)); + return changes; + } + + private Map updateBulkDisbursals(JsonCommand command) { + Map changes = new HashMap(); + final CollectionSheetBulkDisbursalCommand bulkDisbursalCommand = this.bulkDisbursalCommandFromApiJsonDeserializer.commandFromApiJson(command.json()); + this.bulkDisbursalCommandFromApiJsonDeserializer.validateBulkDisbursalTransaction(bulkDisbursalCommand); + changes.putAll(this.loanWritePlatformService.bulkLoanDisbursal(command, bulkDisbursalCommand)); + return changes; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformService.java index edc82fcf3..9c18b7ef8 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformService.java @@ -5,16 +5,24 @@ */ package org.mifosplatform.portfolio.loanaccount.service; +import java.util.Map; + import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkDisbursalCommand; +import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkRepaymentCommand; public interface LoanWritePlatformService { CommandProcessingResult disburseLoan(Long loanId, JsonCommand command); + + Map bulkLoanDisbursal(JsonCommand command, CollectionSheetBulkDisbursalCommand bulkDisbursalCommand); CommandProcessingResult undoLoanDisbursal(Long loanId, JsonCommand command); CommandProcessingResult makeLoanRepayment(Long loanId, JsonCommand command); + + Map makeLoanBulkRepayment(CollectionSheetBulkRepaymentCommand bulkRepaymentCommand); CommandProcessingResult adjustLoanTransaction(Long loanId, Long transactionId, JsonCommand command); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 89d614e97..e86708605 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -32,6 +32,10 @@ import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeUpdatedExc import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeWaivedException; import org.mifosplatform.portfolio.charge.exception.LoanChargeCannotBeWaivedException.LOAN_CHARGE_CANNOT_BE_WAIVED_REASON; import org.mifosplatform.portfolio.charge.exception.LoanChargeNotFoundException; +import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkDisbursalCommand; +import org.mifosplatform.portfolio.collectionsheet.command.CollectionSheetBulkRepaymentCommand; +import org.mifosplatform.portfolio.collectionsheet.command.SingleDisbursalCommand; +import org.mifosplatform.portfolio.collectionsheet.command.SingleRepaymentCommand; import org.mifosplatform.portfolio.loanaccount.command.LoanUpdateCommand; import org.mifosplatform.portfolio.loanaccount.domain.ChangedTransactionDetail; import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine; @@ -143,6 +147,44 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf .with(changes) // .build(); } + + @Transactional + @Override + public Map bulkLoanDisbursal(JsonCommand command, CollectionSheetBulkDisbursalCommand bulkDisbursalCommand) { + final AppUser currentUser = context.authenticatedUser(); + + SingleDisbursalCommand[] disbursalCommand = bulkDisbursalCommand.getDisburseTransactions(); + Map changes = new LinkedHashMap(); + if(disbursalCommand == null){ + return changes; + } + + for (int i = 0; i < disbursalCommand.length; i++) { + SingleDisbursalCommand singleLoanDisbursalCommand = disbursalCommand[i]; + + final Loan loan = retrieveLoanBy(singleLoanDisbursalCommand.getLoanId()); + + final ApplicationCurrency currency = this.applicationCurrencyRepository.findOneByCode(loan.getCurrencyCode()); + + final List existingTransactionIds = new ArrayList(); + final List existingReversedTransactionIds = new ArrayList(); + + changes.putAll(loan.disburse(currentUser, command, currency, existingTransactionIds, + existingReversedTransactionIds)); + if (!changes.isEmpty()) { + this.loanRepository.save(loan); + + final String noteText = command.stringValueOfParameterNamed("note"); + if (StringUtils.isNotBlank(noteText)) { + Note note = Note.loanNote(loan, noteText); + this.noteRepository.save(note); + } + + postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); + } + } + return changes; + } @Transactional @Override @@ -204,6 +246,22 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf changes.put("locale", command.locale()); changes.put("dateFormat", command.dateFormat()); + final String noteText = command.stringValueOfParameterNamed("note"); + if (StringUtils.isNotBlank(noteText)) { + changes.put("note", noteText); + } + + CommandProcessingResultBuilder commandProcessingResultBuilder = saveLoanRepayment(loanId, transactionAmount, transactionDate, noteText); + + return commandProcessingResultBuilder + .withCommandId(command.commandId()) // + .withLoanId(loanId) // + .with(changes) // + .build(); + } + + private CommandProcessingResultBuilder saveLoanRepayment(final Long loanId, final BigDecimal transactionAmount, + final LocalDate transactionDate, final String noteText) { final Loan loan = retrieveLoanBy(loanId); final List existingTransactionIds = new ArrayList(); @@ -230,9 +288,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf } this.loanRepository.save(loan); - final String noteText = command.stringValueOfParameterNamed("note"); + if (StringUtils.isNotBlank(noteText)) { - changes.put("note", noteText); Note note = Note.loanTransactionNote(loan, newRepaymentTransaction, noteText); this.noteRepository.save(note); } @@ -240,16 +297,29 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); return new CommandProcessingResultBuilder() // - .withCommandId(command.commandId()) // - .withEntityId(newRepaymentTransaction.getId()) // - .withOfficeId(loan.getOfficeId()) // - .withClientId(loan.getClientId()) // - .withGroupId(loan.getGroupId()) // - .withLoanId(loanId) // - .with(changes) // - .build(); + .withEntityId(newRepaymentTransaction.getId()) // + .withOfficeId(loan.getOfficeId()) // + .withClientId(loan.getClientId()) // + .withGroupId(loan.getGroupId()); // } + @Transactional + @Override + public Map makeLoanBulkRepayment(final CollectionSheetBulkRepaymentCommand bulkRepaymentCommand) { + + context.authenticatedUser(); + final SingleRepaymentCommand[] repaymentCommand = bulkRepaymentCommand.getLoanTransactions(); + final Map changes = new LinkedHashMap(); + + if(repaymentCommand == null) return changes; + + for (SingleRepaymentCommand singleLoanRepaymentCommand : repaymentCommand) { + saveLoanRepayment(singleLoanRepaymentCommand.getLoanId(), singleLoanRepaymentCommand.getTransactionAmount(), bulkRepaymentCommand.getTransactionDate(), bulkRepaymentCommand.getNote()); + changes.put("bulkTransations", singleLoanRepaymentCommand); + } + return changes; + } + @Transactional @Override public CommandProcessingResult adjustLoanTransaction(final Long loanId, final Long transactionId, final JsonCommand command) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanProductData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanProductData.java index a0f29b90a..c61976aa9 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanProductData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanProductData.java @@ -102,6 +102,32 @@ public class LoanProductData { interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId, transactionProcessingStrategyName, charges, accountingType); } + + public static LoanProductData lookupWithCurrency(final Long id, final String name, final CurrencyData currency) { + final String description = null; + final BigDecimal principal = null; + final BigDecimal tolerance = null; + final Integer numberOfRepayments = null; + final Integer repaymentEvery = null; + final BigDecimal interestRatePerPeriod = null; + final BigDecimal annualInterestRate = null; + final EnumOptionData repaymentFrequencyType = null; + final EnumOptionData interestRateFrequencyType = null; + final EnumOptionData amortizationType = null; + final EnumOptionData interestType = null; + final EnumOptionData interestCalculationPeriodType = null; + final Long fundId = null; + final String fundName = null; + final Long transactionProcessingStrategyId = null; + final String transactionProcessingStrategyName = null; + final Collection charges = null; + final EnumOptionData accountingType = null; + + return new LoanProductData(id, name, description, currency, principal, tolerance, numberOfRepayments, repaymentEvery, + interestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType, + interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId, + transactionProcessingStrategyName, charges, accountingType); + } public static LoanProductData sensibleDefaultsForNewLoanProductCreation() { final Long id = null; @@ -378,4 +404,14 @@ public class LoanProductData { public Collection getChargeOptions() { return chargeOptions; } + @Override + public boolean equals(Object obj) { + LoanProductData loanProductData = (LoanProductData) obj; + return loanProductData.id.equals(this.id); + } + + @Override + public int hashCode() { + return this.id.hashCode(); + } } \ No newline at end of file