From 015400b08e8ff07fa71367c5a956c2cd83c4deb7 Mon Sep 17 00:00:00 2001 From: Michal Dudzinski Date: Sat, 17 Nov 2012 14:18:54 +0100 Subject: [PATCH] MIFOSX-73: new API for loan officer reassignment. --- .../platform/api/LoansApiResource.java | 46 +++++++++++++++- .../platform/api/StaffApiResource.java | 6 +- .../commands/BulkLoanReassignmentCommand.java | 40 -------------- .../api/commands/LoanReassignmentCommand.java | 55 +++++++++++++++++++ .../api/data/LoanBasicDetailsData.java | 11 ++++ .../api/data/LoanReassignmentData.java | 17 +++++- .../PortfolioApiDataConversionService.java | 6 +- ...PortfolioApiDataConversionServiceImpl.java | 31 ++++++++++- .../mifosng/platform/loan/domain/Loan.java | 20 +++---- .../LoanReassignmentCommandValidator.java | 54 ++++++++++++++++++ .../service/LoanWritePlatformService.java | 7 ++- ...WritePlatformServiceJpaRepositoryImpl.java | 39 ++++++++++--- .../BulkLoanReassignmentCommandValidator.java | 37 ------------- 13 files changed, 259 insertions(+), 110 deletions(-) delete mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/api/commands/BulkLoanReassignmentCommand.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanReassignmentCommand.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReassignmentCommandValidator.java delete mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/staff/service/BulkLoanReassignmentCommandValidator.java diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java index c86d0c454..19d464393 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java @@ -19,10 +19,12 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import org.apache.commons.lang.StringUtils; +import org.joda.time.LocalDate; import org.mifosng.platform.api.commands.AdjustLoanTransactionCommand; import org.mifosng.platform.api.commands.CalculateLoanScheduleCommand; import org.mifosng.platform.api.commands.LoanApplicationCommand; import org.mifosng.platform.api.commands.LoanChargeCommand; +import org.mifosng.platform.api.commands.LoanReassignmentCommand; import org.mifosng.platform.api.commands.LoanStateTransitionCommand; import org.mifosng.platform.api.commands.LoanTransactionCommand; import org.mifosng.platform.api.commands.UndoStateTransitionCommand; @@ -36,6 +38,7 @@ import org.mifosng.platform.api.data.LoanBasicDetailsData; import org.mifosng.platform.api.data.LoanChargeData; import org.mifosng.platform.api.data.LoanPermissionData; import org.mifosng.platform.api.data.LoanProductData; +import org.mifosng.platform.api.data.LoanReassignmentData; import org.mifosng.platform.api.data.LoanTransactionData; import org.mifosng.platform.api.data.StaffData; import org.mifosng.platform.api.data.TransactionProcessingStrategyData; @@ -226,7 +229,6 @@ public class LoansApiResource { Collection interestTypeOptions = null; Collection interestCalculationPeriodTypeOptions = null; Collection fundOptions = null; - Collection allowedLoanOfficers = null; Collection chargeOptions = null; ChargeData chargeTemplate = null; @@ -245,7 +247,6 @@ public class LoansApiResource { repaymentStrategyOptions = this.dropdownReadPlatformService.retreiveTransactionProcessingStrategies(); final boolean feeChargesOnly = false; chargeOptions = this.chargeReadPlatformService.retrieveLoanApplicableCharges(feeChargesOnly); - allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersByOffice(loanBasicDetails.getClientOfficeId()); chargeTemplate = this.chargeReadPlatformService.retrieveLoanChargeTemplate(); } @@ -254,7 +255,7 @@ public class LoansApiResource { productOptions, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, - fundOptions, chargeOptions, chargeTemplate, allowedLoanOfficers); + fundOptions, chargeOptions, chargeTemplate, null); return this.apiJsonSerializerService.serializeLoanAccountDataToJson(prettyPrint, responseParameters, loanAccount); } @@ -584,4 +585,43 @@ public class LoansApiResource { final EntityIdentifier identifier = this.loanWritePlatformService.deleteLoanCharge(loanId, loanChargeId); return this.apiJsonSerializerService.serializeEntityIdentifier(identifier); } + + @POST + @Path("{loanId}/assign") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response assignLoanOfficer( + @PathParam("loanId") final Long loanId, + final String jsonRequestBody){ + + final LoanReassignmentCommand command = this.apiDataConversionService.convertJsonToLoanReassignmentCommand(loanId, jsonRequestBody); + + EntityIdentifier identifier = this.loanWritePlatformService.loanReassignment(command); + + return Response.ok().entity(identifier).build(); + } + + @GET + @Path("{loanId}/assign/template") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String assignLoanOfficerTemplate( + @PathParam("loanId") final Long loanId, + @Context final UriInfo uriInfo){ + + final Set responseParameters = ApiParameterHelper + .extractFieldsForResponseIfProvided(uriInfo + .getQueryParameters()); + + final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); + + LoanBasicDetailsData loanBasicDetails = this.loanReadPlatformService.retrieveLoanAccountDetails(loanId); + + Collection allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersByOffice(loanBasicDetails.getOfficeId()); + Long fromLoanOfficerId = loanBasicDetails.getLoanOfficerId(); + + LoanReassignmentData loanReassignmentData = LoanReassignmentData.template(fromLoanOfficerId, allowedLoanOfficers, new LocalDate()); + + return this.apiJsonSerializerService.serializeLoanReassignmentDataToJson(prettyPrint, responseParameters, loanReassignmentData); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/StaffApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/StaffApiResource.java index 7a9f5caa0..ac3578ae0 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/StaffApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/StaffApiResource.java @@ -19,7 +19,7 @@ import javax.ws.rs.core.UriInfo; import org.apache.commons.lang.StringUtils; import org.joda.time.LocalDate; -import org.mifosng.platform.api.commands.BulkLoanReassignmentCommand; +import org.mifosng.platform.api.commands.LoanReassignmentCommand; import org.mifosng.platform.api.commands.StaffCommand; import org.mifosng.platform.api.data.EntityIdentifier; import org.mifosng.platform.api.data.LoanReassignmentData; @@ -154,7 +154,7 @@ public class StaffApiResource { @Produces({ MediaType.APPLICATION_JSON }) public Response loanReassignment(final String jsonRequestBody){ - BulkLoanReassignmentCommand command = + LoanReassignmentCommand command = this.apiDataConversionService.convertJsonToBulkLoanReassignmentCommand(jsonRequestBody); EntityIdentifier loanOfficerIdentifier = this.loanWritePlatformService.bulkLoanReassignment(command); @@ -191,7 +191,7 @@ public class StaffApiResource { staffAccountSummaryCollectionData = this.readPlatformService.retrieveLoanOfficerAccountSummary(loanOfficerId); } - final LoanReassignmentData loanReassignmentData = new LoanReassignmentData(officeId, loanOfficerId, + final LoanReassignmentData loanReassignmentData = LoanReassignmentData.templateForBulk(officeId, loanOfficerId, new LocalDate(), offices, loanOfficers, staffAccountSummaryCollectionData); return this.apiJsonSerializerService.serializeLoanReassignmentDataToJson(prettyPrint, responseParameters, loanReassignmentData); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/BulkLoanReassignmentCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/BulkLoanReassignmentCommand.java deleted file mode 100644 index 8767d1419..000000000 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/BulkLoanReassignmentCommand.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.mifosng.platform.api.commands; - -import org.joda.time.LocalDate; - -/** - * Immutable data object for reassigning loan officers on loans in bulk. - */ -public class BulkLoanReassignmentCommand { - - private final Long fromLoanOfficerId; - private final Long toLoanOfficerId; - private final LocalDate assignmentDate; - - private final String[] loans; - - public BulkLoanReassignmentCommand(final Long fromLoanOfficerId, - final Long toLoanOfficerId, final LocalDate assignmentDate, - final String[] loans) { - this.fromLoanOfficerId = fromLoanOfficerId; - this.toLoanOfficerId = toLoanOfficerId; - this.assignmentDate = assignmentDate; - this.loans = loans; - } - - public Long getFromLoanOfficerId() { - return fromLoanOfficerId; - } - - public Long getToLoanOfficerId() { - return toLoanOfficerId; - } - - public LocalDate getAssignmentDate() { - return assignmentDate; - } - - public String[] getLoans() { - return loans; - } -} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanReassignmentCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanReassignmentCommand.java new file mode 100644 index 000000000..6e94ed4cd --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanReassignmentCommand.java @@ -0,0 +1,55 @@ +package org.mifosng.platform.api.commands; + +import org.joda.time.LocalDate; + +/** + * Immutable data object for reassigning loan officers on loans in bulk. + */ +public class LoanReassignmentCommand { + + private final Long loanId; + + private final Long fromLoanOfficerId; + private final Long toLoanOfficerId; + private final LocalDate assignmentDate; + + private final String[] loans; + + public LoanReassignmentCommand(Long loanId, Long fromLoanOfficerId, + Long toLoanOfficerId, LocalDate assignmentDate) { + this.loanId = loanId; + this.fromLoanOfficerId = fromLoanOfficerId; + this.toLoanOfficerId = toLoanOfficerId; + this.assignmentDate = assignmentDate; + this.loans = null; + } + + public LoanReassignmentCommand(Long fromLoanOfficerId, Long toLoanOfficerId, + LocalDate assignmentDate, String[] loans) { + this.fromLoanOfficerId = fromLoanOfficerId; + this.toLoanOfficerId = toLoanOfficerId; + this.assignmentDate = assignmentDate; + this.loans = loans; + this.loanId = null; + } + + public Long getLoanId() { + return loanId; + } + + public Long getFromLoanOfficerId() { + return fromLoanOfficerId; + } + + public Long getToLoanOfficerId() { + return toLoanOfficerId; + } + + public LocalDate getAssignmentDate() { + return assignmentDate; + } + + public String[] getLoans() { + return loans; + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanBasicDetailsData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanBasicDetailsData.java index 95dd94fc6..148681dfd 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanBasicDetailsData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanBasicDetailsData.java @@ -560,4 +560,15 @@ public class LoanBasicDetailsData { public DisbursementData toDisburementData() { return new DisbursementData(this.expectedDisbursementDate, this.actualDisbursementDate, this.principal); } + + public Long getOfficeId(){ + Long officeId = this.clientOfficeId; + + if (officeId == null){ + officeId = this.groupOfficeId; + } + + return officeId; + } + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanReassignmentData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanReassignmentData.java index 1c7218cc6..6dafa1b16 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanReassignmentData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanReassignmentData.java @@ -24,7 +24,22 @@ public class LoanReassignmentData { @SuppressWarnings("unused") private final StaffAccountSummaryCollectionData accountSummaryCollection; - public LoanReassignmentData( + public static LoanReassignmentData templateForBulk(final Long officeId, + final Long fromLoanOfficerId, + final LocalDate assignmentDate, + final Collection officeOptions, + final Collection loanOfficerOptions, + final StaffAccountSummaryCollectionData accountSummaryCollection) { + return new LoanReassignmentData(officeId, fromLoanOfficerId, assignmentDate, officeOptions, loanOfficerOptions, accountSummaryCollection); + } + + public static LoanReassignmentData template(final Long fromLoanOfficerId, + final Collection loanOfficerOptions, + final LocalDate assignmentDate){ + return new LoanReassignmentData(null, fromLoanOfficerId, assignmentDate, null, loanOfficerOptions, null); + } + + private LoanReassignmentData( final Long officeId, final Long fromLoanOfficerId, final LocalDate assignmentDate, diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/PortfolioApiDataConversionService.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/PortfolioApiDataConversionService.java index bb9c48b78..c43dc6e80 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/PortfolioApiDataConversionService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/PortfolioApiDataConversionService.java @@ -2,7 +2,7 @@ package org.mifosng.platform.api.infrastructure; import org.mifosng.platform.api.commands.AdjustLoanTransactionCommand; import org.mifosng.platform.api.commands.BranchMoneyTransferCommand; -import org.mifosng.platform.api.commands.BulkLoanReassignmentCommand; +import org.mifosng.platform.api.commands.LoanReassignmentCommand; import org.mifosng.platform.api.commands.ChargeCommand; import org.mifosng.platform.api.commands.ClientCommand; import org.mifosng.platform.api.commands.ClientIdentifierCommand; @@ -76,7 +76,9 @@ public interface PortfolioApiDataConversionService { StaffCommand convertJsonToStaffCommand(Long resourceIdentifier, String json); - BulkLoanReassignmentCommand convertJsonToBulkLoanReassignmentCommand(String json); + LoanReassignmentCommand convertJsonToLoanReassignmentCommand(Long resourceIdentifier, String json); + + LoanReassignmentCommand convertJsonToBulkLoanReassignmentCommand(String json); DepositAccountWithdrawalCommand convertJsonToDepositWithdrawalCommand(Long resourceIdentifier, String json); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/PortfolioApiDataConversionServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/PortfolioApiDataConversionServiceImpl.java index b61b2651e..fb9b9062d 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/PortfolioApiDataConversionServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/PortfolioApiDataConversionServiceImpl.java @@ -19,7 +19,7 @@ import org.joda.time.LocalDate; import org.joda.time.format.DateTimeFormat; import org.mifosng.platform.api.commands.AdjustLoanTransactionCommand; import org.mifosng.platform.api.commands.BranchMoneyTransferCommand; -import org.mifosng.platform.api.commands.BulkLoanReassignmentCommand; +import org.mifosng.platform.api.commands.LoanReassignmentCommand; import org.mifosng.platform.api.commands.ChargeCommand; import org.mifosng.platform.api.commands.ClientCommand; import org.mifosng.platform.api.commands.ClientIdentifierCommand; @@ -157,7 +157,32 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo } @Override - public BulkLoanReassignmentCommand convertJsonToBulkLoanReassignmentCommand(final String json) { + public LoanReassignmentCommand convertJsonToLoanReassignmentCommand(Long resourceIdentifier, String json) { + + if (StringUtils.isBlank(json)) { + throw new InvalidJsonException(); + } + + Type typeOfMap = new TypeToken>(){}.getType(); + Map requestMap = gsonConverter.fromJson(json, typeOfMap); + + Set supportedParams = new HashSet( + Arrays.asList("fromLoanOfficerId", "toLoanOfficerId", "assignmentDate", "locale", "dateFormat") + ); + + checkForUnsupportedParameters(requestMap, supportedParams); + + Set modifiedParameters = new HashSet(); + + Long fromLoanOfficerId = extractLongParameter("fromLoanOfficerId", requestMap, modifiedParameters); + Long toLoanOfficerId = extractLongParameter("toLoanOfficerId", requestMap, modifiedParameters); + LocalDate assignmentDate = extractLocalDateParameter("assignmentDate", requestMap, modifiedParameters); + + return new LoanReassignmentCommand(resourceIdentifier, fromLoanOfficerId, toLoanOfficerId, assignmentDate); + } + + @Override + public LoanReassignmentCommand convertJsonToBulkLoanReassignmentCommand(final String json) { if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); @@ -196,7 +221,7 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo } // - return new BulkLoanReassignmentCommand(fromLoanOfficerId, toLoanOfficerId, assignmentDate, loans); + return new LoanReassignmentCommand(fromLoanOfficerId, toLoanOfficerId, assignmentDate, loans); } @Override diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/Loan.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/Loan.java index b15bda1d7..6a89777f7 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/Loan.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/Loan.java @@ -448,7 +448,6 @@ public class Loan extends AbstractAuditableCustom { public void modifyLoanApplication(final LoanApplicationCommand command, final Client client, final LoanProduct loanProduct, final Fund fund, final LoanTransactionProcessingStrategy strategy, final LoanScheduleData modifiedLoanSchedule, final Set charges, - final Staff loanOfficer, final LoanLifecycleStateMachine loanLifecycleStateMachine) { // FIXME - KW - whilst the methods are named isXXXChanged, this really only is asking has the parameter for that field been passed in request, @@ -462,9 +461,6 @@ public class Loan extends AbstractAuditableCustom { if (command.isFundChanged()) { this.fund = fund; } - if(command.isLoanOfficerChanged()){ - this.loanofficer = loanOfficer; - } if (command.isTransactionStrategyChanged()) { this.transactionProcessingStrategy = strategy; } @@ -1601,18 +1597,20 @@ public class Loan extends AbstractAuditableCustom { public void reassignLoanOfficer(final Staff newLoanOfficer, final LocalDate assignmentDate) { final LoanOfficerAssignmentHistory latestHistoryRecord = findLatestIncompleteHistoryRecord(); - - if (this.loanofficer.identifiedBy(newLoanOfficer)) { + + if (latestHistoryRecord != null && this.loanofficer.identifiedBy(newLoanOfficer)) { latestHistoryRecord.updateStartDate(assignmentDate); - } else if (latestHistoryRecord.matchesStartDateOf(assignmentDate)) { + } else if (latestHistoryRecord != null && latestHistoryRecord.matchesStartDateOf(assignmentDate)) { latestHistoryRecord.updateLoanOfficer(newLoanOfficer); this.loanofficer = newLoanOfficer; - } else if (latestHistoryRecord.hasStartDateBefore(assignmentDate)) { + } else if (latestHistoryRecord != null && latestHistoryRecord.hasStartDateBefore(assignmentDate)) { throw new LoanOfficerAssignmentException(this.getId(), assignmentDate); } else { - // loan officer correctly changed from previous loan officer to new loan officer - latestHistoryRecord.updateEndDate(assignmentDate); - + if (latestHistoryRecord != null){ + // loan officer correctly changed from previous loan officer to new loan officer + latestHistoryRecord.updateEndDate(assignmentDate); + } + this.loanofficer = newLoanOfficer; final LoanOfficerAssignmentHistory loanOfficerAssignmentHistory = LoanOfficerAssignmentHistory.createNew(this, this.loanofficer, assignmentDate); this.loanOfficerHistory.add(loanOfficerAssignmentHistory); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReassignmentCommandValidator.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReassignmentCommandValidator.java new file mode 100644 index 000000000..4aac7385e --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReassignmentCommandValidator.java @@ -0,0 +1,54 @@ +package org.mifosng.platform.loan.service; + +import org.mifosng.platform.DataValidatorBuilder; +import org.mifosng.platform.api.commands.LoanReassignmentCommand; +import org.mifosng.platform.api.data.ApiParameterError; +import org.mifosng.platform.exceptions.PlatformApiDataValidationException; + +import java.util.ArrayList; +import java.util.List; + +public class LoanReassignmentCommandValidator { + + private final LoanReassignmentCommand command; + + public LoanReassignmentCommandValidator(LoanReassignmentCommand command) { + this.command = command; + } + + public void validateForBulkLoanReassignment(){ + List dataValidationErrors = new ArrayList(); + + DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loans.reassignment"); + + baseDataValidator.reset().parameter("fromLoanOfficerId").value(command.getFromLoanOfficerId()). + notNull().integerGreaterThanZero(); + baseDataValidator.reset().parameter("toLoanOfficerId").value(command.getToLoanOfficerId()).notNull(). + integerGreaterThanZero().notSameAsParameter("fromLoanOfficerId", command.getFromLoanOfficerId()); + + baseDataValidator.reset().parameter("assignmentDate").value(command.getAssignmentDate()).notNull(); + + baseDataValidator.reset().parameter("loans").value(command.getLoans()).arrayNotEmpty(); + + if (!dataValidationErrors.isEmpty()) { + throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); + } + } + + public void validateForLoanReassignment(){ + List dataValidationErrors = new ArrayList(); + + DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loans.reassignment"); + + baseDataValidator.reset().parameter("toLoanOfficerId").value(command.getToLoanOfficerId()).notNull(). + integerGreaterThanZero().notSameAsParameter("fromLoanOfficerId", command.getFromLoanOfficerId()); + + baseDataValidator.reset().parameter("assignmentDate").value(command.getAssignmentDate()).notNull(); + + baseDataValidator.reset().parameter("loanId").value(command.getLoanId()).notNull(); + + if (!dataValidationErrors.isEmpty()) { + throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); + } + } +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformService.java index 68d72286a..8116903f5 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformService.java @@ -1,7 +1,7 @@ package org.mifosng.platform.loan.service; import org.mifosng.platform.api.commands.AdjustLoanTransactionCommand; -import org.mifosng.platform.api.commands.BulkLoanReassignmentCommand; +import org.mifosng.platform.api.commands.LoanReassignmentCommand; import org.mifosng.platform.api.commands.LoanChargeCommand; import org.mifosng.platform.api.commands.LoanStateTransitionCommand; import org.mifosng.platform.api.commands.LoanTransactionCommand; @@ -70,5 +70,8 @@ public interface LoanWritePlatformService { EntityIdentifier waiveLoanCharge(LoanChargeCommand command); @PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'BULKREASSIGN_LOAN')") - EntityIdentifier bulkLoanReassignment(final BulkLoanReassignmentCommand command); + EntityIdentifier bulkLoanReassignment(final LoanReassignmentCommand command); + + @PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER')") + EntityIdentifier loanReassignment(final LoanReassignmentCommand command); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 2c7f397e0..e7a54b575 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -10,7 +10,7 @@ import org.apache.commons.lang.StringUtils; import org.joda.time.LocalDate; import org.mifosng.platform.api.LoanScheduleData; import org.mifosng.platform.api.commands.AdjustLoanTransactionCommand; -import org.mifosng.platform.api.commands.BulkLoanReassignmentCommand; +import org.mifosng.platform.api.commands.LoanReassignmentCommand; import org.mifosng.platform.api.commands.CalculateLoanScheduleCommand; import org.mifosng.platform.api.commands.LoanApplicationCommand; import org.mifosng.platform.api.commands.LoanChargeCommand; @@ -55,7 +55,6 @@ import org.mifosng.platform.loan.domain.LoanTransactionRepository; import org.mifosng.platform.loan.domain.PeriodFrequencyType; import org.mifosng.platform.security.PlatformSecurityContext; import org.mifosng.platform.staff.domain.Staff; -import org.mifosng.platform.staff.service.BulkLoanReassignmentCommandValidator; import org.mifosng.platform.user.domain.AppUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.context.SecurityContextHolder; @@ -158,7 +157,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf } final Fund fund = this.loanAssembler.findFundByIdIfProvided(command.getFundId()); - final Staff loanOfficer = this.loanAssembler.findLoanOfficerByIdIfProvided(command.getLoanOfficerId()); final LoanTransactionProcessingStrategy strategy = this.loanAssembler.findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId()); final Set charges = this.loanChargeAssembler.assembleFrom(command.getCharges(), loanProduct.getCharges(), loan.getPrincpal().getAmount()); @@ -166,7 +164,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf // FIXME - kw - restrict ability to modify loan to modifying the 'loan application' stage - once it has been disbursed, should be allowed to use this feature // - other facilities are in place such as 'undo disbursal' - loan.modifyLoanApplication(command, client, loanProduct, fund, strategy, loanSchedule, charges, loanOfficer, defaultLoanLifecycleStateMachine()); + loan.modifyLoanApplication(command, client, loanProduct, fund, strategy, loanSchedule, charges, defaultLoanLifecycleStateMachine()); this.loanRepository.save(loan); @@ -732,14 +730,39 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf return loanCharge; } - @Transactional + @Transactional @Override - public EntityIdentifier bulkLoanReassignment(final BulkLoanReassignmentCommand command) { + public EntityIdentifier loanReassignment(LoanReassignmentCommand command) { this.context.authenticatedUser(); - BulkLoanReassignmentCommandValidator validator = new BulkLoanReassignmentCommandValidator(command); - validator.validateLoanReassignment(); + LoanReassignmentCommandValidator validator = new LoanReassignmentCommandValidator(command); + validator.validateForLoanReassignment(); + + final Staff fromLoanOfficer = loanAssembler.findLoanOfficerByIdIfProvided(command.getFromLoanOfficerId()); + final Staff toLoanOfficer = loanAssembler.findLoanOfficerByIdIfProvided(command.getToLoanOfficerId()); + + final Loan loan = retrieveLoanBy(command.getLoanId()); + + if (!loan.hasLoanOfficer(fromLoanOfficer)){ + throw new LoanOfficerAssignmentException(loan.getId(), fromLoanOfficer.getId()); + } + + loan.reassignLoanOfficer(toLoanOfficer, command.getAssignmentDate()); + + this.loanRepository.saveAndFlush(loan); + + return new EntityIdentifier(loan.getId()); + } + + @Transactional + @Override + public EntityIdentifier bulkLoanReassignment(final LoanReassignmentCommand command) { + + this.context.authenticatedUser(); + + LoanReassignmentCommandValidator validator = new LoanReassignmentCommandValidator(command); + validator.validateForBulkLoanReassignment(); Staff fromLoanOfficer = loanAssembler.findLoanOfficerByIdIfProvided(command.getFromLoanOfficerId()); Staff toLoanOfficer = loanAssembler.findLoanOfficerByIdIfProvided(command.getToLoanOfficerId()); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/BulkLoanReassignmentCommandValidator.java b/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/BulkLoanReassignmentCommandValidator.java deleted file mode 100644 index 972ad9192..000000000 --- a/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/BulkLoanReassignmentCommandValidator.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.mifosng.platform.staff.service; - -import org.mifosng.platform.DataValidatorBuilder; -import org.mifosng.platform.api.commands.BulkLoanReassignmentCommand; -import org.mifosng.platform.api.data.ApiParameterError; -import org.mifosng.platform.exceptions.PlatformApiDataValidationException; - -import java.util.ArrayList; -import java.util.List; - -public class BulkLoanReassignmentCommandValidator { - - private final BulkLoanReassignmentCommand command; - - public BulkLoanReassignmentCommandValidator(BulkLoanReassignmentCommand command) { - this.command = command; - } - - public void validateLoanReassignment(){ - List dataValidationErrors = new ArrayList(); - - DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("staff.account.transfer"); - - baseDataValidator.reset().parameter("fromLoanOfficerId").value(command.getFromLoanOfficerId()). - notNull().integerGreaterThanZero(); - baseDataValidator.reset().parameter("toLoanOfficerId").value(command.getToLoanOfficerId()).notNull(). - integerGreaterThanZero().notSameAsParameter("fromLoanOfficerId", command.getFromLoanOfficerId()); - - baseDataValidator.reset().parameter("assignmentDate").value(command.getAssignmentDate()).notNull(); - - baseDataValidator.reset().parameter("loans").value(command.getLoans()).arrayNotEmpty(); - - if (!dataValidationErrors.isEmpty()) { - throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); - } - } -}