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 5ba537432..0e88ef988 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 @@ -18,13 +18,17 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import org.apache.commons.lang.StringUtils; +import org.mifosng.platform.api.commands.BulkLoanReassignmentCommand; import org.mifosng.platform.api.commands.StaffCommand; import org.mifosng.platform.api.data.EntityIdentifier; +import org.mifosng.platform.api.data.LoanReassignmentData; import org.mifosng.platform.api.data.OfficeLookup; +import org.mifosng.platform.api.data.StaffAccountSummaryCollectionData; import org.mifosng.platform.api.data.StaffData; import org.mifosng.platform.api.infrastructure.ApiDataConversionService; import org.mifosng.platform.api.infrastructure.ApiJsonSerializerService; import org.mifosng.platform.api.infrastructure.ApiParameterHelper; +import org.mifosng.platform.loan.service.LoanWritePlatformService; import org.mifosng.platform.organisation.service.OfficeReadPlatformService; import org.mifosng.platform.staff.service.StaffReadPlatformService; import org.mifosng.platform.staff.service.StaffWritePlatformService; @@ -54,6 +58,9 @@ public class StaffApiResource { @Autowired private OfficeReadPlatformService officeReadPlatformService; + @Autowired + private LoanWritePlatformService loanWritePlatformService; + private final static Logger logger = LoggerFactory .getLogger(StaffApiResource.class); @@ -131,6 +138,53 @@ public class StaffApiResource { return Response.ok().entity(new EntityIdentifier(entityId)).build(); } + @POST + @Path("loanreassignment") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response loanReassignment(final String jsonRequestBody){ + + BulkLoanReassignmentCommand command = + this.apiDataConversionService.convertJsonToBulkLoanReassignmentCommand(jsonRequestBody); + + EntityIdentifier loanOfficerIdentifier = this.loanWritePlatformService.bulkLoanReassignment(command); + + return Response.ok().entity(loanOfficerIdentifier).build(); + } + + @GET + @Path("loanreassignment/template") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String loanReassignmentTemplate(@QueryParam("officeId") final Long officeId, + @QueryParam("fromLoanOfficerId") final Long loanOfficerId, + @Context final UriInfo uriInfo){ + + final Set responseParameters = ApiParameterHelper + .extractFieldsForResponseIfProvided(uriInfo + .getQueryParameters()); + + final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo + .getQueryParameters()); + + Collection offices = this.officeReadPlatformService.retrieveAllOfficesForLookup(); + + Collection loanOfficers = null; + StaffAccountSummaryCollectionData staffAccountSummaryCollectionData = null; + + if (officeId != null){ + loanOfficers = this.readPlatformService.retrieveAllLoanOfficersByOffice(officeId); + } + if (loanOfficerId != null){ + staffAccountSummaryCollectionData = this.readPlatformService.retrieveLoanOfficerAccountSummary(loanOfficerId); + } + + LoanReassignmentData loanReassignmentData = new LoanReassignmentData(officeId, loanOfficerId, offices, + loanOfficers, staffAccountSummaryCollectionData); + + return this.apiJsonSerializerService.serializeLoanReassignmentDataToJson(prettyPrint, responseParameters, loanReassignmentData); + } + private String getStaffCriteria(String sqlSearch, Integer officeId) { String extraCriteria = ""; 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 new file mode 100644 index 000000000..8e22cf59d --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/BulkLoanReassignmentCommand.java @@ -0,0 +1,35 @@ +package org.mifosng.platform.api.commands; + + +import java.util.Set; + +public class BulkLoanReassignmentCommand { + + private final Long fromLoanOfficerId; + private final Long toLoanOfficerId; + + private final String[] loans; + + private final Set modifiedParameters; + + public BulkLoanReassignmentCommand(Set modifiedParameters, Long fromLoanOfficerId, + Long toLoanOfficerId, String[] loans) { + this.fromLoanOfficerId = fromLoanOfficerId; + this.toLoanOfficerId = toLoanOfficerId; + this.loans = loans; + this.modifiedParameters = modifiedParameters; + } + + public Long getFromLoanOfficerId() { + return fromLoanOfficerId; + } + + public Long getToLoanOfficerId() { + return toLoanOfficerId; + } + + public String[] getLoans() { + return loans; + } + +} 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 new file mode 100644 index 000000000..efd883ec3 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanReassignmentData.java @@ -0,0 +1,46 @@ +package org.mifosng.platform.api.data; + +import java.util.Collection; + +public class LoanReassignmentData { + + private final Long officeId; + private final Long fromLoanOfficerId; + + //template + private final Collection officeOptions; + + private final Collection loanOfficerOptions; + + private final StaffAccountSummaryCollectionData accountSummaryCollection; + + public LoanReassignmentData(Long officeId, Long fromLoanOfficerId, + Collection officeOptions, Collection loanOfficerOptions, + StaffAccountSummaryCollectionData accountSummaryCollection) { + this.officeId = officeId; + this.fromLoanOfficerId = fromLoanOfficerId; + this.officeOptions = officeOptions; + this.loanOfficerOptions = loanOfficerOptions; + this.accountSummaryCollection = accountSummaryCollection; + } + + public Long getOfficeId() { + return officeId; + } + + public Long getFromLoanOfficerId() { + return fromLoanOfficerId; + } + + public Collection getOfficeOptions() { + return officeOptions; + } + + public Collection getLoanOfficerOptions() { + return loanOfficerOptions; + } + + public StaffAccountSummaryCollectionData getAccountSummaryCollection() { + return accountSummaryCollection; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/StaffAccountSummaryCollectionData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/StaffAccountSummaryCollectionData.java new file mode 100644 index 000000000..1195210bb --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/StaffAccountSummaryCollectionData.java @@ -0,0 +1,83 @@ +package org.mifosng.platform.api.data; + + +import java.util.Collection; +import java.util.List; + +public class StaffAccountSummaryCollectionData { + + private final List clients; + + private final List groups; + + public StaffAccountSummaryCollectionData(List clients, List groups) { + this.clients = clients; + this.groups = groups; + } + + public List getClients() { + return clients; + } + + public List getGroups() { + return groups; + } + + public static final class ClientSummary { + + private final Long id; + private final String displayName; + + private Collection loans; + + public ClientSummary(Long id, String displayName) { + this.id = id; + this.displayName = displayName; + } + + public Long getId() { + return id; + } + + public String getDisplayName() { + return displayName; + } + + public Collection getLoans() { + return loans; + } + + public void setLoans(Collection loans) { + this.loans = loans; + } + } + + public static final class GroupSummary { + + private final Long id; + private final String name; + + private Collection loans; + + public GroupSummary(Long id, String name) { + this.id = id; + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public Collection getLoans() { + return loans; + } + + public void setLoans(Collection loans) { + this.loans = loans; + } + } +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java index c9aa6a00a..0fe3c7c64 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java @@ -2,6 +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.ChargeCommand; import org.mifosng.platform.api.commands.ClientCommand; import org.mifosng.platform.api.commands.ClientIdentifierCommand; @@ -73,7 +74,9 @@ public interface ApiDataConversionService { DepositStateTransitionApprovalCommand convertJsonToDepositStateTransitionApprovalCommand(Long resourceIdentifier, String jsonRequestBody); StaffCommand convertJsonToStaffCommand(Long resourceIdentifier, String json); - + + BulkLoanReassignmentCommand convertJsonToBulkLoanReassignmentCommand(String jsonRequestBody); + DepositAccountWithdrawalCommand convertJsonToDepositWithdrawalCommand(Long resourceIdentifier, String jsonRequestBody); DepositAccountWithdrawInterestCommand convertJsonToDepositAccountWithdrawInterestCommand(Long resourceIdentifier, String jsonRequestBody); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java index 956498d91..d862fc817 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java @@ -19,6 +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.ChargeCommand; import org.mifosng.platform.api.commands.ClientCommand; import org.mifosng.platform.api.commands.ClientIdentifierCommand; @@ -152,7 +153,49 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { return new StaffCommand(modifiedParameters, resourceIdentifier, officeId,firstname, lastname, isLoanOfficer); } - + + @Override + public BulkLoanReassignmentCommand convertJsonToBulkLoanReassignmentCommand(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","loans") + ); + + checkForUnsupportedParameters(requestMap, supportedParams); + + Set modifiedParameters = new HashSet(); + + Long fromLoanOfficerId = extractLongParameter("fromLoanOfficerId", requestMap, modifiedParameters); + Long toLoanOfficerId = extractLongParameter("toLoanOfficerId", requestMap, modifiedParameters); + + // check array + JsonParser parser = new JsonParser(); + + String[] loans = null; + JsonElement element = parser.parse(json); + if (element.isJsonObject()) { + JsonObject object = element.getAsJsonObject(); + if (object.has("loans")) { + modifiedParameters.add("loans"); + JsonArray array = object.get("loans").getAsJsonArray(); + loans = new String[array.size()]; + for (int i=0; i responseParameters, LoanTransactionData newTransactionData); + String serializeLoanReassignmentDataToJson(boolean prettyPrint, Set responseParameters, LoanReassignmentData loanReassignmentData); + String serializeChargeDataToJson(boolean prettyPrint, Set responseParameters, Collection charges); String serializeChargeDataToJson(boolean prettyPrint, Set responseParameters, ChargeData charge); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java index 895c9c102..01b051b3c 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java @@ -27,6 +27,7 @@ import org.mifosng.platform.api.data.GroupData; import org.mifosng.platform.api.data.LoanAccountData; import org.mifosng.platform.api.data.LoanChargeData; 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.NoteData; import org.mifosng.platform.api.data.OfficeData; @@ -187,6 +188,10 @@ public class GoogleGsonApiJsonSerializerService implements ApiJsonSerializerServ private static final Set LOAN_TRANSACTION_NEW_DATA_PARAMETERS = new HashSet( Arrays.asList("id", "type", "date", "currency", "amount")); + private static final Set LOAN_REASSIGNMENT_DATA_PARAMETERS = new HashSet( + Arrays.asList("officeId", "fromLoanOfficerId", "officeOptions", "loanOfficerOptions", "accountSummaryCollection") + ); + private static final Set CHARGES_DATA_PARAMETERS = new HashSet( Arrays.asList("id", "name", "amount", "currency", "penalty", "active", "chargeAppliesTo", "chargeTimeType", @@ -568,6 +573,17 @@ public class GoogleGsonApiJsonSerializerService implements ApiJsonSerializerServ return helper.serializedJsonFrom(gsonDeserializer, transaction); } + @Override + public String serializeLoanReassignmentDataToJson(boolean prettyPrint, + Set responseParameters, + LoanReassignmentData loanReassignmentData) { + final Gson gsonDeserializer = helper + .createGsonBuilderWithParameterExclusionSerializationStrategy( + LOAN_REASSIGNMENT_DATA_PARAMETERS, prettyPrint, + responseParameters); + return helper.serializedJsonFrom(gsonDeserializer, loanReassignmentData); + } + @Override public String serializeChargeDataToJson(final boolean prettyPrint, final Set responseParameters, diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformService.java index e0b689f8f..f0340a499 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformService.java @@ -3,6 +3,7 @@ package org.mifosng.platform.client.service; import java.util.Collection; import org.mifosng.platform.api.data.ClientAccountSummaryCollectionData; +import org.mifosng.platform.api.data.ClientAccountSummaryData; import org.mifosng.platform.api.data.ClientData; import org.mifosng.platform.api.data.ClientIdentifierData; import org.mifosng.platform.api.data.ClientLookup; @@ -22,6 +23,8 @@ public interface ClientReadPlatformService { ClientAccountSummaryCollectionData retrieveClientAccountDetails(Long clientId); + Collection retrieveClientLoanAccountsByLoanOfficerId(Long clientId, Long loanOfficerId); + Collection retrieveAllClientNotes(Long clientId); NoteData retrieveClientNote(Long clientId, Long noteId); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformServiceImpl.java index 8c8a07797..e3a3b1977 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientReadPlatformServiceImpl.java @@ -272,6 +272,23 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService } } + @Override + public Collection retrieveClientLoanAccountsByLoanOfficerId(Long clientId, Long loanOfficerId) { + + this.context.authenticatedUser(); + + // Check if client exists + retrieveIndividualClient(clientId); + + ClientLoanAccountSummaryDataMapper rm = new ClientLoanAccountSummaryDataMapper(); + + String sql = "select " + rm.loanAccountSummarySchema() + " where l.client_id = ? and l.loan_officer_id = ?"; + + List loanAccounts = this.jdbcTemplate.query(sql, rm, new Object[] {clientId, loanOfficerId}); + + return loanAccounts; + } + private static final class ClientLoanAccountSummaryDataMapper implements RowMapper { diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/LoanOfficerAssignmentException.java b/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/LoanOfficerAssignmentException.java new file mode 100644 index 000000000..6c4d66842 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/LoanOfficerAssignmentException.java @@ -0,0 +1,11 @@ +package org.mifosng.platform.exceptions; + + +public class LoanOfficerAssignmentException extends + AbstractPlatformDomainRuleException { + + public LoanOfficerAssignmentException(final Long loanId, final Long loanOfficerId) { + super("error.msg.loan.not.assigned.to.loan.officer", "Loan with identifier " + loanId + + " is not assigned to Loan Officer with identifier " + loanOfficerId + ".", loanId); + } +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupReadPlatformService.java index 36d71efa1..491d2c062 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupReadPlatformService.java @@ -4,6 +4,7 @@ import java.util.Collection; import org.mifosng.platform.api.data.GroupAccountSummaryCollectionData; import org.mifosng.platform.api.data.ClientLookup; +import org.mifosng.platform.api.data.GroupAccountSummaryData; import org.mifosng.platform.api.data.GroupData; public interface GroupReadPlatformService { @@ -17,4 +18,6 @@ public interface GroupReadPlatformService { Collection retrieveClientMembers(Long groupId); GroupAccountSummaryCollectionData retrieveGroupAccountDetails(Long groupId); + + Collection retrieveGroupLoanAccountsByLoanOfficerId(Long groupId, Long loanOfficerId); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupReadPlatformServiceImpl.java index 10f42c0e8..20bc94373 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/group/service/GroupReadPlatformServiceImpl.java @@ -181,6 +181,23 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService { } } + @Override + public Collection retrieveGroupLoanAccountsByLoanOfficerId(Long groupId, Long loanOfficerId) { + + this.context.authenticatedUser(); + + // Check if group exists + retrieveGroup(groupId); + + GroupLoanAccountSummaryDataMapper rm = new GroupLoanAccountSummaryDataMapper(); + + String sql = "select " + rm.loanAccountSummarySchema() + " where l.group_id = ? and l.loan_officer_id = ?"; + + List loanAccounts = this.jdbcTemplate.query(sql, rm, new Object[] {groupId, loanOfficerId}); + + return loanAccounts; + } + private static final class GroupLoanAccountSummaryDataMapper implements RowMapper { 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 55b2e59d0..7f8434622 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 @@ -300,6 +300,10 @@ public class Loan extends AbstractAuditableCustom { return loanofficer; } + public void setLoanofficer(Staff loanofficer) { + this.loanofficer = loanofficer; + } + public LoanProductRelatedDetail repaymentScheduleDetail() { return this.loanRepaymentScheduleDetail; } 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 dda9288e0..224efb8ec 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,6 +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.LoanChargeCommand; import org.mifosng.platform.api.commands.LoanStateTransitionCommand; import org.mifosng.platform.api.commands.LoanTransactionCommand; @@ -64,4 +65,7 @@ public interface LoanWritePlatformService { @PreAuthorize(value = "hasRole('ORGANISATION_ADMINISTRATION_SUPER_USER_ROLE')") EntityIdentifier deleteLoanCharge(final Long loanId, final Long loanChargeId); + + @PreAuthorize(value = "hasRole('ORGANISATION_ADMINISTRATION_SUPER_USER_ROLE')") + EntityIdentifier bulkLoanReassignment(final BulkLoanReassignmentCommand 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 790c8a96b..39e051824 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,6 +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.CalculateLoanScheduleCommand; import org.mifosng.platform.api.commands.LoanApplicationCommand; import org.mifosng.platform.api.commands.LoanChargeCommand; @@ -32,6 +33,7 @@ import org.mifosng.platform.exceptions.ClientNotFoundException; import org.mifosng.platform.exceptions.InvalidCurrencyException; import org.mifosng.platform.exceptions.LoanNotFoundException; import org.mifosng.platform.exceptions.LoanNotInSubmittedAndPendingApprovalStateCannotBeDeleted; +import org.mifosng.platform.exceptions.LoanOfficerAssignmentException; import org.mifosng.platform.exceptions.LoanProductNotFoundException; import org.mifosng.platform.exceptions.LoanTransactionNotFoundException; import org.mifosng.platform.exceptions.NoAuthorizationException; @@ -52,6 +54,7 @@ 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; @@ -724,4 +727,35 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf return new EntityIdentifier(loanCharge.getId()); } + + @Override + public EntityIdentifier bulkLoanReassignment(BulkLoanReassignmentCommand command) { + + this.context.authenticatedUser(); + + BulkLoanReassignmentCommandValidator validator = new BulkLoanReassignmentCommandValidator(command); + validator.validateLoanReassignment(); + + Staff fromLoanOfficer = loanAssembler.findLoanOfficerByIdIfProvided(command.getFromLoanOfficerId()); + Staff toLoanOfficer = loanAssembler.findLoanOfficerByIdIfProvided(command.getToLoanOfficerId()); + + for (String loanIdString : command.getLoans()){ + final Long loanId = Long.valueOf(loanIdString); + + final Loan loan = this.loanRepository.findOne(loanId); + if (loan == null) { + throw new LoanNotFoundException(loanId); + } + if (!loan.getLoanofficer().equals(fromLoanOfficer)){ + throw new LoanOfficerAssignmentException(loan.getId(), fromLoanOfficer.getId()); + } + + loan.setLoanofficer(toLoanOfficer); + this.loanRepository.save(loan); + } + + this.loanRepository.flush(); + + return new EntityIdentifier(toLoanOfficer.getId()); + } } \ No newline at end of file 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 new file mode 100644 index 000000000..294c0f705 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/BulkLoanReassignmentCommandValidator.java @@ -0,0 +1,35 @@ +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("loans").value(command.getLoans()).arrayNotEmpty(); + + 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/staff/service/StaffReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffReadPlatformService.java index 1468a0318..1ab4adf64 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffReadPlatformService.java @@ -2,6 +2,7 @@ package org.mifosng.platform.staff.service; import java.util.Collection; +import org.mifosng.platform.api.data.StaffAccountSummaryCollectionData; import org.mifosng.platform.api.data.StaffData; public interface StaffReadPlatformService { @@ -11,4 +12,6 @@ public interface StaffReadPlatformService { Collection retrieveAllStaff(final String extraCriteria); Collection retrieveAllLoanOfficersByOffice(final long officeId); + + StaffAccountSummaryCollectionData retrieveLoanOfficerAccountSummary(final long loanOfficerId); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffReadPlatformServiceImpl.java index d3c816757..d36f4e9dd 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffReadPlatformServiceImpl.java @@ -3,10 +3,17 @@ package org.mifosng.platform.staff.service; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collection; +import java.util.List; import org.apache.commons.lang.StringUtils; +import org.mifosng.platform.api.data.ClientAccountSummaryData; +import org.mifosng.platform.api.data.GroupAccountSummaryData; +import org.mifosng.platform.api.data.StaffAccountSummaryCollectionData; import org.mifosng.platform.api.data.StaffData; +import org.mifosng.platform.client.service.ClientReadPlatformService; import org.mifosng.platform.exceptions.StaffNotFoundException; +import org.mifosng.platform.group.service.GroupReadPlatformService; +import org.mifosng.platform.infrastructure.JdbcSupport; import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource; import org.mifosng.platform.security.PlatformSecurityContext; import org.springframework.beans.factory.annotation.Autowired; @@ -20,13 +27,18 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService { private final JdbcTemplate jdbcTemplate; private final PlatformSecurityContext context; + private final ClientReadPlatformService clientReadPlatformService; + private final GroupReadPlatformService groupReadPlatformService; @Autowired - public StaffReadPlatformServiceImpl( - final PlatformSecurityContext context, - final TenantAwareRoutingDataSource dataSource) { + public StaffReadPlatformServiceImpl(final PlatformSecurityContext context, + final TenantAwareRoutingDataSource dataSource, + final ClientReadPlatformService clientReadPlatformService, + final GroupReadPlatformService groupReadPlatformService) { this.context = context; this.jdbcTemplate = new JdbcTemplate(dataSource); + this.clientReadPlatformService = clientReadPlatformService; + this.groupReadPlatformService = groupReadPlatformService; } private static final class StaffMapper implements RowMapper { @@ -93,4 +105,74 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService { throw new StaffNotFoundException(staffId); } } + + @Override + public StaffAccountSummaryCollectionData retrieveLoanOfficerAccountSummary(long loanOfficerId) { + + context.authenticatedUser(); + + StaffClientMapper staffClientMapper = new StaffClientMapper(); + String clientSql = "select distinct " + staffClientMapper.schema(); + + StaffGroupMapper staffGroupMapper = new StaffGroupMapper(); + String groupSql = "select distinct " + staffGroupMapper.schema(); + + List clientSummaryList = + this.jdbcTemplate.query(clientSql, staffClientMapper, new Object[]{loanOfficerId}); + + for (StaffAccountSummaryCollectionData.ClientSummary clientSummary : clientSummaryList){ + + Collection clientLoanAccounts = + this.clientReadPlatformService.retrieveClientLoanAccountsByLoanOfficerId(clientSummary.getId(), loanOfficerId); + + clientSummary.setLoans(clientLoanAccounts); + } + + List groupSummaryList = + this.jdbcTemplate.query(groupSql, staffGroupMapper, new Object[]{loanOfficerId}); + + for (StaffAccountSummaryCollectionData.GroupSummary groupSummary : groupSummaryList){ + + Collection groupLoanAccounts = + this.groupReadPlatformService.retrieveGroupLoanAccountsByLoanOfficerId(groupSummary.getId(), loanOfficerId); + + groupSummary.setLoans(groupLoanAccounts); + } + + return new StaffAccountSummaryCollectionData(clientSummaryList, groupSummaryList); + } + + private static final class StaffClientMapper implements RowMapper { + + public String schema(){ + return " c.id as id, c.display_name as displayName from m_client c " + + " join m_loan l on c.id = l.client_id where l.loan_officer_id = ? "; + } + + @Override + public StaffAccountSummaryCollectionData.ClientSummary mapRow(ResultSet rs, int rowNum) throws SQLException { + Long id = JdbcSupport.getLong(rs, "id"); + String displayName = rs.getString("displayName"); + + return new StaffAccountSummaryCollectionData.ClientSummary(id, displayName); + } + + } + + private static final class StaffGroupMapper implements RowMapper { + + public String schema(){ + return " g.id as id, g.name as name from m_group g" + + " join m_loan l on g.id = l.group_id where l.loan_officer_id = ? "; + } + + @Override + public StaffAccountSummaryCollectionData.GroupSummary mapRow(ResultSet rs, int rowNum) throws SQLException { + Long id = JdbcSupport.getLong(rs, "id"); + String name = rs.getString("name"); + + return new StaffAccountSummaryCollectionData.GroupSummary(id, name); + } + + } } \ No newline at end of file