diff --git a/.gitignore b/.gitignore index 4a29984cd..d10cc96f4 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ repos *.jar *.war *.ear +*.bak diff --git a/mifosng-db/patches/patch-0006-m_loan-patch.sql b/mifosng-db/patches/patch-0006-m_loan-patch.sql new file mode 100755 index 000000000..c37090683 --- /dev/null +++ b/mifosng-db/patches/patch-0006-m_loan-patch.sql @@ -0,0 +1,3 @@ +ALTER TABLE `m_loan` + ADD COLUMN `loan_officer_id` BIGINT(20) NULL AFTER `fund_id`, + ADD CONSTRAINT `FK_m_loan_m_staff` FOREIGN KEY (`loan_officer_id`) REFERENCES `m_staff` (`id`); \ No newline at end of file diff --git a/mifosng-db/patches/patch-0007-m_staff-patch.sql b/mifosng-db/patches/patch-0007-m_staff-patch.sql new file mode 100755 index 000000000..4c233a6b1 --- /dev/null +++ b/mifosng-db/patches/patch-0007-m_staff-patch.sql @@ -0,0 +1,9 @@ +ALTER TABLE `m_staff` + ADD COLUMN `office_id` BIGINT(20) NULL AFTER `id`, + ADD CONSTRAINT `FK_m_staff_m_office` FOREIGN KEY (`office_id`) REFERENCES `m_office` (`id`); + +ALTER TABLE `m_staff` + ADD COLUMN `is_loan_officer` TINYINT(1) NOT NULL DEFAULT 0 AFTER `id`; + +update m_staff set office_id=1; + 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 1fbdbfa9b..3ff70c676 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 @@ -40,6 +40,7 @@ import org.mifosng.platform.api.data.LoanRepaymentPeriodData; import org.mifosng.platform.api.data.LoanRepaymentTransactionData; import org.mifosng.platform.api.data.LoanSchedule; import org.mifosng.platform.api.data.LoanTransactionData; +import org.mifosng.platform.api.data.StaffData; import org.mifosng.platform.api.data.TransactionProcessingStrategyData; import org.mifosng.platform.api.infrastructure.ApiDataConversionService; import org.mifosng.platform.api.infrastructure.ApiJsonSerializerService; @@ -52,6 +53,7 @@ import org.mifosng.platform.loan.service.LoanReadPlatformService; import org.mifosng.platform.loan.service.LoanWritePlatformService; import org.mifosng.platform.loanproduct.service.LoanDropdownReadPlatformService; import org.mifosng.platform.loanproduct.service.LoanProductReadPlatformService; +import org.mifosng.platform.staff.service.StaffReadPlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @@ -88,6 +90,9 @@ public class LoansApiResource { @Autowired private ApiJsonSerializerService apiJsonSerializerService; + @Autowired + private StaffReadPlatformService staffReadPlatformService; + @GET @Path("template") @Consumes({ MediaType.APPLICATION_JSON }) @@ -118,6 +123,9 @@ public class LoansApiResource { Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); if (responseParameters.isEmpty()) { responseParameters.addAll(typicalResponseParameters); + }else if (responseParameters.contains("loanOfficerOptions") && (responseParameters.size() == 1)) { + // TODO Vishwas: check if response parameters should be additive + responseParameters.addAll(typicalResponseParameters); } boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); @@ -146,10 +154,19 @@ public class LoansApiResource { final boolean convenienceDataRequired = false; Collection charges = loanBasicDetails.getCharges(); + + // populate loan officers if query param is passed in + Collection allowedLoanOfficers = null; + if (responseParameters.contains("loanOfficerOptions")) { + // get applicable loan officers + allowedLoanOfficers = this.staffReadPlatformService + .retrieveAllStaff(" office_id = " + + loanBasicDetails.getClientOfficeId() + " and is_loan_officer = 1"); + } final LoanAccountData newLoanAccount = new LoanAccountData(loanBasicDetails, convenienceDataRequired, null, null, null, null, charges, productOptions, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions, transactionProcessingStrategyOptions, interestRateFrequencyTypeOptions, - amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions); + amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, allowedLoanOfficers); return this.apiJsonSerializerService.serialzieLoanAccountDataToJson(prettyPrint, responseParameters, newLoanAccount); } @@ -176,6 +193,10 @@ public class LoansApiResource { Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); if (responseParameters.isEmpty()) { responseParameters.addAll(typicalResponseParameters); + } else if ((responseParameters.contains("loanOfficerName") || responseParameters + .contains("loanOfficerId")) && (responseParameters.size() <= 2)) { + // TODO Vishwas: check if response parameters should be additive + responseParameters.addAll(typicalResponseParameters); } boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); @@ -241,11 +262,19 @@ public class LoansApiResource { chargeOptions.removeAll(charges); } } + + Collection allowedLoanOfficers = null; + if (responseParameters.contains("loanOfficerOptions")) { + // get applicable loan officers + allowedLoanOfficers = this.staffReadPlatformService + .retrieveAllStaff(" office_id = " + + loanBasicDetails.getClientOfficeId() + " and is_loan_officer = 1"); + } final LoanAccountData loanAccount = new LoanAccountData(loanBasicDetails, convenienceDataRequired, summary, repaymentSchedule, loanRepayments, permissions, charges, productOptions, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions, transactionProcessingStrategyOptions, interestRateFrequencyTypeOptions, - amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions); + amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, allowedLoanOfficers); return this.apiJsonSerializerService.serialzieLoanAccountDataToJson(prettyPrint, responseParameters, loanAccount); } 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 76f37a4b6..6515e9545 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 @@ -1,5 +1,6 @@ package org.mifosng.platform.api; +import java.util.ArrayList; import java.util.Collection; import java.util.Set; @@ -10,19 +11,25 @@ import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; +import org.apache.commons.lang.StringUtils; import org.mifosng.platform.api.commands.StaffCommand; import org.mifosng.platform.api.data.EntityIdentifier; +import org.mifosng.platform.api.data.OfficeLookup; 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.organisation.service.OfficeReadPlatformService; import org.mifosng.platform.staff.service.StaffReadPlatformService; import org.mifosng.platform.staff.service.StaffWritePlatformService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @@ -44,10 +51,18 @@ public class StaffApiResource { @Autowired private ApiJsonSerializerService apiJsonSerializerService; + @Autowired + private OfficeReadPlatformService officeReadPlatformService; + + private final static Logger logger = LoggerFactory + .getLogger(StaffApiResource.class); + @GET @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String retrieveStaffs(@Context final UriInfo uriInfo) { + public String retrieveStaff(@Context final UriInfo uriInfo, + @QueryParam("sqlSearch") final String sqlSearch, + @QueryParam("officeId") final Integer officeId) { Set responseParameters = ApiParameterHelper .extractFieldsForResponseIfProvided(uriInfo @@ -55,8 +70,9 @@ public class StaffApiResource { boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo .getQueryParameters()); + final String extraCriteria = getStaffCriteria(sqlSearch, officeId); final Collection staff = this.readPlatformService - .retrieveAllStaff(); + .retrieveAllStaff(extraCriteria); return this.apiJsonSerializerService.serializeStaffDataToJson( prettyPrint, responseParameters, staff); @@ -87,8 +103,14 @@ public class StaffApiResource { .getQueryParameters()); final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo .getQueryParameters()); + boolean template = ApiParameterHelper.template(uriInfo + .getQueryParameters()); final StaffData staff = this.readPlatformService.retrieveStaff(staffId); + if (template) { + staff.setAllowedOffices(new ArrayList( + officeReadPlatformService.retrieveAllOfficesForLookup())); + } return this.apiJsonSerializerService.serializeStaffDataToJson( prettyPrint, responseParameters, staff); @@ -108,4 +130,24 @@ public class StaffApiResource { return Response.ok().entity(new EntityIdentifier(entityId)).build(); } + + private String getStaffCriteria(String sqlSearch, Integer officeId) { + + String extraCriteria = ""; + + if (sqlSearch != null) { + extraCriteria = " and (" + sqlSearch + ")"; + } + if (officeId != null) { + extraCriteria += " and office_id = " + officeId; + } + + if (StringUtils.isNotBlank(extraCriteria)) { + extraCriteria = extraCriteria.substring(4); + } + logger.info("extraCriteria; " + extraCriteria); + + return extraCriteria; + } + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanApplicationCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanApplicationCommand.java index 27d9f5b4c..a779024f1 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanApplicationCommand.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanApplicationCommand.java @@ -17,6 +17,7 @@ public class LoanApplicationCommand { private final String externalId; private final Long fundId; + private final Long loanOfficerId; private final Long transactionProcessingStrategyId; private final BigDecimal principal; @@ -63,13 +64,15 @@ public class LoanApplicationCommand { final Integer interestCalculationPeriodMethod, final Integer repaymentEvery, final Integer repaymentFrequency, final Integer numberOfRepayments, Integer amortizationMethod, final Integer loanTermFrequency, final Integer loanTermFrequencyType, - final BigDecimal toleranceAmount, final LoanChargeCommand[] charges) { + final BigDecimal toleranceAmount, final LoanChargeCommand[] charges, + final Long loanOfficerId) { this.modifiedParameters = modifiedParameters; this.loanId = loanId; this.clientId = clientId; this.productId = productId; this.externalId = externalId; this.fundId = fundId; + this.loanOfficerId = loanOfficerId; this.transactionProcessingStrategyId = transactionProcessingStrategyId; this.submittedOnDate = submittedOnDate; @@ -231,6 +234,10 @@ public class LoanApplicationCommand { public boolean isFundChanged() { return this.modifiedParameters.contains("fundId"); } + + public boolean isLoanOfficerChanged() { + return this.modifiedParameters.contains("loanOfficerId"); + } public boolean isTransactionStrategyChanged() { return this.modifiedParameters.contains("transactionProcessingStrategyId"); @@ -259,4 +266,8 @@ public class LoanApplicationCommand { public boolean isInterestChargedFromDateChanged() { return this.modifiedParameters.contains("interestChargedFromDate"); } + + public Long getLoanOfficerId() { + return loanOfficerId; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/StaffCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/StaffCommand.java index 640cd0102..44d6a0358 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/StaffCommand.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/StaffCommand.java @@ -10,16 +10,20 @@ public class StaffCommand { private final Long id; private final String firstName; private final String lastName; + private final Long officeId; + private final boolean loanOfficerFlag; private final Set modifiedParameters; public StaffCommand(final Set modifiedParameters, final Long id, - final String firstName, final String lastName) { + final Long officeId, final String firstName, final String lastName, + final boolean loanOfficerFlag) { this.modifiedParameters = modifiedParameters; this.id = id; this.firstName = firstName; this.lastName = lastName; - + this.officeId = officeId; + this.loanOfficerFlag = loanOfficerFlag; } public Long getId() { @@ -34,6 +38,14 @@ public class StaffCommand { return lastName; } + public Long getOfficeId() { + return officeId; + } + + public boolean isLoanOfficerFlag() { + return loanOfficerFlag; + } + public boolean isFirstNameChanged() { return this.modifiedParameters.contains("firstname"); } @@ -42,4 +54,12 @@ public class StaffCommand { return this.modifiedParameters.contains("lastname"); } + public boolean isLoanOfficerFlagChanged() { + return this.modifiedParameters.contains("loanOfficerFlag"); + } + + public boolean isOfficeChanged() { + return this.modifiedParameters.contains("officeId"); + } + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountData.java index e361c172b..650f7a480 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountData.java @@ -1,7 +1,9 @@ package org.mifosng.platform.api.data; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import org.joda.time.LocalDate; @@ -20,6 +22,8 @@ public class LoanAccountData { private final EnumOptionData status; private final Long fundId; private final String fundName; + private Long loanOfficerId; + private String loanOfficerName; private final CurrencyData currency; private final BigDecimal principal; private final BigDecimal inArrearsTolerance; @@ -66,6 +70,7 @@ public class LoanAccountData { private final Collection interestCalculationPeriodTypeOptions; private final Collection fundOptions; private final Collection chargeOptions; + private final Collection loanOfficerOptions; public LoanAccountData( final LoanBasicDetailsData basicDetails, @@ -84,7 +89,8 @@ public class LoanAccountData { final Collection interestTypeOptions, final Collection interestCalculationPeriodTypeOptions, final Collection fundOptions, - final Collection chargeOptions) { + final Collection chargeOptions, + final Collection loanOfficerOptions) { this.summary = summary; this.repaymentSchedule = repaymentSchedule; this.loanRepayments = loanRepayments; @@ -100,6 +106,7 @@ public class LoanAccountData { this.interestCalculationPeriodTypeOptions = interestCalculationPeriodTypeOptions; this.fundOptions = fundOptions; this.chargeOptions = chargeOptions; + this.loanOfficerOptions = loanOfficerOptions; if (convenienceDataRequired) { int maxSubmittedOnOffsetFromToday = basicDetails @@ -131,6 +138,9 @@ public class LoanAccountData { this.loanProductDescription = basicDetails.getLoanProductDescription(); this.fundId = basicDetails.getFundId(); this.fundName = basicDetails.getFundName(); + this.loanOfficerId = basicDetails.getLoanOfficerId(); + this.loanOfficerName = basicDetails.getLoanOfficerName(); + this.submittedOnDate = basicDetails.getSubmittedOnDate(); this.approvedOnDate = basicDetails.getApprovedOnDate(); @@ -364,4 +374,20 @@ public class LoanAccountData { public Collection getChargeOptions() { return chargeOptions; } + + public Long getLoanOfficerId() { + return loanOfficerId; + } + + public void setLoanOfficerId(Long loanOfficerId) { + this.loanOfficerId = loanOfficerId; + } + + public String getLoanOfficerName() { + return loanOfficerName; + } + + public void setLoanOfficerName(String loanOfficerName) { + this.loanOfficerName = loanOfficerName; + } } \ 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 184ab424b..513fa69cd 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 @@ -13,9 +13,14 @@ import org.joda.time.Months; */ public class LoanBasicDetailsData { + public Long getClientOfficeId() { + return clientOfficeId; + } + private final Long id; private final String externalId; private final Long clientId; + private final Long clientOfficeId; private final String clientName; private final Long loanProductId; private final String loanProductName; @@ -23,6 +28,8 @@ public class LoanBasicDetailsData { private final EnumOptionData status; private final Long fundId; private final String fundName; + private Long loanOfficerId; + private String loanOfficerName; private final CurrencyData currency; private final BigDecimal principal; private final BigDecimal inArrearsTolerance; @@ -52,8 +59,9 @@ public class LoanBasicDetailsData { private final Collection charges; - public static LoanBasicDetailsData populateForNewLoanCreation(final Long clientId, final String clientName, final LocalDate expectedDisbursementDate) { - return new LoanBasicDetailsData(clientId, clientName, expectedDisbursementDate); + public static LoanBasicDetailsData populateForNewLoanCreation(final Long clientId, final String clientName, final LocalDate expectedDisbursementDate, + final Long clientOfficeId) { + return new LoanBasicDetailsData(clientId, clientName, expectedDisbursementDate, clientOfficeId); } public static LoanBasicDetailsData populateForNewLoanCreation(final LoanBasicDetailsData loanAccount, final LoanProductData product) { @@ -61,7 +69,7 @@ public class LoanBasicDetailsData { final Integer termFrequency = product.getNumberOfRepayments() * product.getRepaymentEvery(); final EnumOptionData termPeriodFrequencyType = product.getRepaymentFrequencyType(); return new LoanBasicDetailsData( - loanAccount.clientId, loanAccount.clientName, + loanAccount.clientId, loanAccount.clientName, loanAccount.clientOfficeId, product.getId(), product.getName(), product.getDescription(), product.getFundId(), product.getFundName(), product.getCurrency(), product.getPrincipal(), product.getInArrearsTolerance(), termFrequency, termPeriodFrequencyType, product.getNumberOfRepayments(), product.getRepaymentEvery(), product.getRepaymentFrequencyType(), @@ -71,7 +79,7 @@ public class LoanBasicDetailsData { } private LoanBasicDetailsData( - final Long clientId, final String clientName, + final Long clientId, final String clientName, final Long clientOfficeId, final Long productId, final String productName, final String productDescription, final Long fundId, final String fundName, final CurrencyData currency, final BigDecimal principal, final BigDecimal inArrearsTolerance, final Integer termFrequency, @@ -90,6 +98,7 @@ public class LoanBasicDetailsData { this.externalId = null; this.clientId = clientId; this.clientName = clientName; + this.clientOfficeId = clientOfficeId; this.loanProductId = productId; this.loanProductName = productName; this.loanProductDescription= productDescription; @@ -134,18 +143,20 @@ public class LoanBasicDetailsData { this.charges = charges; } - private LoanBasicDetailsData(final Long clientId, final String clientName, final LocalDate expectedDisbursementDate) { + private LoanBasicDetailsData(final Long clientId, final String clientName, final LocalDate expectedDisbursementDate, final Long clientOfficeId) { this.id = null; this.externalId = null; this.clientId = clientId; this.clientName = clientName; + this.clientOfficeId = clientOfficeId; this.loanProductId = null; this.loanProductName = null; this.loanProductDescription= null; this.status = null; this.fundId = null; this.fundName = null; - + this.loanOfficerId = null; + this.loanOfficerName = null; this.currency = null; this.principal = null; this.inArrearsTolerance = null; @@ -181,7 +192,7 @@ public class LoanBasicDetailsData { final Long id, final String externalId, final Long clientId, final String clientName, - final Long loanProductId, + final Long clientOfficeId, final Long loanProductId, final String loanProductName, final String loanProductDescription, final Long fundId, String fundName, @@ -210,16 +221,20 @@ public class LoanBasicDetailsData { final Integer termFrequency, final EnumOptionData termPeriodFrequencyType, final Integer transactionStrategyId, - final Collection charges) { + final Collection charges, + final Long loanOfficerId, String loanOfficerName) { this.id = id; this.externalId = externalId; this.clientId = clientId; this.clientName = clientName; + this.clientOfficeId = clientOfficeId; this.loanProductId = loanProductId; this.loanProductName = loanProductName; this.loanProductDescription = loanProductDescription; this.fundId = fundId; this.fundName = fundName; + this.loanOfficerId = loanOfficerId; + this.loanOfficerName = loanOfficerName; this.closedOnDate = closedOnDate; this.submittedOnDate = submittedOnDate; this.approvedOnDate = approvedOnDate; @@ -476,4 +491,20 @@ public class LoanBasicDetailsData { public Collection getCharges() { return charges; } + + public Long getLoanOfficerId() { + return loanOfficerId; + } + + public void setLoanOfficerId(Long loanOfficerId) { + this.loanOfficerId = loanOfficerId; + } + + public String getLoanOfficerName() { + return loanOfficerName; + } + + public void setLoanOfficerName(String loanOfficerName) { + this.loanOfficerName = loanOfficerName; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/StaffData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/StaffData.java index b4f004ac4..287830d7c 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/StaffData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/StaffData.java @@ -1,6 +1,8 @@ package org.mifosng.platform.api.data; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; public class StaffData implements Serializable { @@ -8,17 +10,23 @@ public class StaffData implements Serializable { private String firstname; private String lastname; private String displayName; + private final Long officeId; + private final String officeName; + private final Boolean loanOfficerFlag; - public StaffData() { - // - } + private List allowedOffices = new ArrayList(); public StaffData(final Long id, final String firstname, - final String lastname,final String displayName) { + final String lastname, final String displayName, + final Long officeId, final String officeName, + final Boolean loanOfficerFlag) { this.id = id; this.firstname = firstname; this.lastname = lastname; - this.displayName= displayName; + this.displayName = displayName; + this.officeName = officeName; + this.loanOfficerFlag = loanOfficerFlag; + this.officeId = officeId; } public Long getId() { @@ -53,5 +61,24 @@ public class StaffData implements Serializable { this.displayName = displayName; } - + public Long getOfficeId() { + return officeId; + } + + public String getOfficeName() { + return officeName; + } + + public Boolean getLoanOfficerFlag() { + return loanOfficerFlag; + } + + public List getAllowedOffices() { + return allowedOffices; + } + + public void setAllowedOffices(List allowedOffices) { + this.allowedOffices = allowedOffices; + } + } \ No newline at end of file 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 533177e36..4622aa0b4 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 @@ -134,7 +134,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { Set supportedParams = new HashSet( - Arrays.asList("firstname", "lastname") + Arrays.asList("firstname", "lastname","officeId", "loanOfficerFlag") ); checkForUnsupportedParameters(requestMap, supportedParams); @@ -143,8 +143,10 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { String firstname = extractStringParameter("firstname", requestMap, modifiedParameters); String lastname = extractStringParameter("lastname", requestMap, modifiedParameters); + Boolean isLoanOfficer = extractBooleanParameter("loanOfficerFlag", requestMap, modifiedParameters); + Long officeId = extractLongParameter("officeId", requestMap, modifiedParameters); - return new StaffCommand(modifiedParameters, resourceIdentifier, firstname, lastname); + return new StaffCommand(modifiedParameters, resourceIdentifier, officeId,firstname, lastname, isLoanOfficer); } @Override @@ -445,7 +447,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { "loanTermFrequency", "loanTermFrequencyType", "charges", "repaymentFrequencyType", "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType", "expectedDisbursementDate", "repaymentsStartingFromDate", "interestChargedFromDate", "submittedOnDate", "submittedOnNote", - "locale", "dateFormat") + "locale", "dateFormat", "loanOfficerId") ); checkForUnsupportedParameters(requestMap, supportedParams); @@ -455,6 +457,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { Long clientId = extractLongParameter("clientId", requestMap, modifiedParameters); Long productId = extractLongParameter("productId", requestMap, modifiedParameters); Long fundId = extractLongParameter("fundId", requestMap, modifiedParameters); + Long loanOfficerId = extractLongParameter("loanOfficerId", requestMap, modifiedParameters); Long transactionProcessingStrategyId = extractLongParameter("transactionProcessingStrategyId", requestMap, modifiedParameters); String externalId = extractStringParameter("externalId", requestMap, modifiedParameters); @@ -523,7 +526,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { principal, interestRatePerPeriod, interestRateFrequencyTypeValue, interestTypeValue, interestCalculationPeriodTypeValue, repaymentEvery, repaymentFrequencyType, numberOfRepayments, amortizationTypeValue, loanTermFrequency, loanTermFrequencyType, - inArrearsToleranceValue, charges); + inArrearsToleranceValue, charges,loanOfficerId); } @Override 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 5ee90239e..f75fa34b9 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 @@ -63,7 +63,8 @@ public class GoogleGsonApiJsonSerializerService implements ApiJsonSerializerServ private static final Set FUND_DATA_PARAMETERS = new HashSet( Arrays.asList("id", "name", "externalId")); private static final Set STAFF_DATA_PARAMETERS = new HashSet( - Arrays.asList("id", "firstname", "lastname","displayName")); + Arrays.asList("id", "firstname", "lastname","displayName", "officeId", "officeName", + "loanOfficerFlag","allowedOffices")); private static final Set LOAN_PRODUCT_DATA_PARAMETERS = new HashSet( Arrays.asList("id", "name", "description", "fundId", "fundName", "transactionProcessingStrategyId", @@ -149,7 +150,8 @@ public class GoogleGsonApiJsonSerializerService implements ApiJsonSerializerServ "lifeCycleStatusDate", "summary", "repaymentSchedule", "loanRepayments", "permissions", "convenienceData", "charges", "productOptions", "amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions", - "repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions", "transactionProcessingStrategyOptions", "chargeOptions")); + "repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions", "transactionProcessingStrategyOptions", "chargeOptions", + "loanOfficerId", "loanOfficerName", "loanOfficerOptions")); private static final Set LOAN_TRANSACTION_DATA_PARAMETERS = new HashSet( Arrays.asList("id", "transactionType", "date", "principal", diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/StaffNotFoundException.java b/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/StaffNotFoundException.java index d40131a5f..d197ebe66 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/StaffNotFoundException.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/StaffNotFoundException.java @@ -7,7 +7,7 @@ public class StaffNotFoundException extends AbstractPlatformResourceNotFoundException { public StaffNotFoundException(final Long id) { - super("error.msg.fund.id.invalid", "Staff with identifier " + id + super("error.msg.staff.id.invalid", "Staff with identifier " + id + " does not exist", id); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/StaffRoleException.java b/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/StaffRoleException.java new file mode 100755 index 000000000..0521f1f79 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/StaffRoleException.java @@ -0,0 +1,21 @@ +package org.mifosng.platform.exceptions; + +/** + * A {@link RuntimeException} thrown when staff resources are not found. + */ +public class StaffRoleException extends + AbstractPlatformResourceNotFoundException { + + public static enum STAFF_ROLE { + LOAN_OFFICER, BRANCH_MANAGER; + @Override + public String toString() { + return name().toString().replaceAll("-", " ").toLowerCase(); + } + } + + public StaffRoleException(final Long id, STAFF_ROLE role) { + super("error.msg.staff.id.invalid.role", "Staff with identifier " + id + + " is not a " + role.toString(), id); + } +} \ No newline at end of file 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 d2e42ec32..23b9ab240 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 @@ -38,6 +38,7 @@ import org.mifosng.platform.exceptions.InvalidLoanStateTransitionException; import org.mifosng.platform.exceptions.InvalidLoanTransactionTypeException; import org.mifosng.platform.fund.domain.Fund; import org.mifosng.platform.infrastructure.AbstractAuditableCustom; +import org.mifosng.platform.staff.domain.Staff; import org.mifosng.platform.user.domain.AppUser; @Entity @@ -57,6 +58,10 @@ public class Loan extends AbstractAuditableCustom { @JoinColumn(name = "fund_id", nullable = true) private Fund fund; + @ManyToOne + @JoinColumn(name = "loan_officer_id", nullable = true) + private Staff loanofficer; + @ManyToOne @JoinColumn(name = "loan_transaction_strategy_id", nullable = true) private LoanTransactionProcessingStrategy transactionProcessingStrategy; @@ -157,10 +162,10 @@ public class Loan extends AbstractAuditableCustom { @Transient private final LoanRepaymentScheduleTransactionProcessorFactory transactionProcessor = new LoanRepaymentScheduleTransactionProcessorFactory(); - public static Loan createNew(final Fund fund, final LoanTransactionProcessingStrategy transactionProcessingStrategy, + public static Loan createNew(final Fund fund,final Staff loanOfficer, final LoanTransactionProcessingStrategy transactionProcessingStrategy, final LoanProduct loanProduct, final Client client, final LoanProductRelatedDetail loanRepaymentScheduleDetail) { - return new Loan(client, fund, transactionProcessingStrategy, loanProduct, loanRepaymentScheduleDetail, null); + return new Loan(client, fund,loanOfficer, transactionProcessingStrategy, loanProduct, loanRepaymentScheduleDetail, null); } protected Loan() { @@ -170,11 +175,12 @@ public class Loan extends AbstractAuditableCustom { this.charges = null; } - public Loan(final Client client, Fund fund, LoanTransactionProcessingStrategy transactionProcessingStrategy, final LoanProduct loanProduct, + public Loan(final Client client, Fund fund, Staff loanOfficer, LoanTransactionProcessingStrategy transactionProcessingStrategy, final LoanProduct loanProduct, final LoanProductRelatedDetail loanRepaymentScheduleDetail, final LoanStatus loanStatus) { this.client = client; this.fund = fund; + this.loanofficer = loanOfficer; this.transactionProcessingStrategy = transactionProcessingStrategy; this.loanProduct = loanProduct; this.loanRepaymentScheduleDetail = loanRepaymentScheduleDetail; @@ -194,6 +200,10 @@ public class Loan extends AbstractAuditableCustom { return this.loanProduct; } + public Staff getLoanofficer() { + return loanofficer; + } + public LoanProductRelatedDetail repaymentScheduleDetail() { return this.loanRepaymentScheduleDetail; } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanAssembler.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanAssembler.java index 1e3909476..e1982271d 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanAssembler.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanAssembler.java @@ -23,6 +23,8 @@ import org.mifosng.platform.exceptions.FundNotFoundException; import org.mifosng.platform.exceptions.InvalidCurrencyException; import org.mifosng.platform.exceptions.LoanProductNotFoundException; import org.mifosng.platform.exceptions.LoanTransactionProcessingStrategyNotFoundException; +import org.mifosng.platform.exceptions.StaffNotFoundException; +import org.mifosng.platform.exceptions.StaffRoleException; import org.mifosng.platform.fund.domain.Fund; import org.mifosng.platform.fund.domain.FundRepository; import org.mifosng.platform.loan.domain.AmortizationMethod; @@ -41,6 +43,8 @@ import org.mifosng.platform.loan.domain.LoanTransactionProcessingStrategy; import org.mifosng.platform.loan.domain.LoanTransactionProcessingStrategyRepository; import org.mifosng.platform.loan.domain.PeriodFrequencyType; import org.mifosng.platform.loanschedule.domain.AprCalculator; +import org.mifosng.platform.staff.domain.Staff; +import org.mifosng.platform.staff.domain.StaffRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils; @@ -54,6 +58,7 @@ public class LoanAssembler { private final FundRepository fundRepository; private final ChargeRepository chargeRepository; private final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository; + private final StaffRepository staffRepository; @Autowired public LoanAssembler( @@ -61,12 +66,14 @@ public class LoanAssembler { final ClientRepository clientRepository, final FundRepository fundRepository, final ChargeRepository chargeRepository, - final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository) { + final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository, + final StaffRepository staffRepository) { this.loanProductRepository = loanProductRepository; this.clientRepository = clientRepository; this.fundRepository = fundRepository; this.chargeRepository = chargeRepository; this.loanTransactionProcessingStrategyRepository = loanTransactionProcessingStrategyRepository; + this.staffRepository = staffRepository; } public Loan assembleFrom(final LoanApplicationCommand command) { @@ -94,7 +101,10 @@ public class LoanAssembler { Fund fund = findFundByIdIfProvided(command.getFundId()); LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId()); - Loan loan = Loan.createNew(fund, loanTransactionProcessingStrategy, loanProduct, client, loanRepaymentScheduleDetail); + //optionally associate a loan officer to the loan + Staff loanOfficer= findLoanOfficerByIdIfProvided(command.getLoanOfficerId()); + + Loan loan = Loan.createNew(fund,loanOfficer, loanTransactionProcessingStrategy, loanProduct, client, loanRepaymentScheduleDetail); loan.setExternalId(command.getExternalId()); final Set charges = this.assembleSetOfCharges(command, loan, loanProduct, currency.getCode()); @@ -159,6 +169,20 @@ public class LoanAssembler { return fund; } + private Staff findLoanOfficerByIdIfProvided(final Long loanOfficerId) { + Staff staff = null; + if (loanOfficerId != null) { + staff = this.staffRepository.findOne(loanOfficerId); + if (staff == null) { + throw new StaffNotFoundException(loanOfficerId); + } else if (!staff.getLoanOfficerFlag()) { + throw new StaffRoleException(loanOfficerId, + StaffRoleException.STAFF_ROLE.LOAN_OFFICER); + } + } + return staff; + } + public LoanTransactionProcessingStrategy findStrategyByIdIfProvided(final Long transactionProcessingStrategyId) { LoanTransactionProcessingStrategy strategy = null; if (transactionProcessingStrategyId != null) { diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java index f8925cb3b..5f512276b 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java @@ -234,7 +234,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { final LocalDate expectedDisbursementDate = new LocalDate(); final ClientData clientAccount = this.clientReadPlatformService.retrieveIndividualClient(clientId); - LoanBasicDetailsData loanDetails = LoanBasicDetailsData.populateForNewLoanCreation(clientAccount.getId(), clientAccount.getDisplayName(), expectedDisbursementDate); + LoanBasicDetailsData loanDetails = LoanBasicDetailsData.populateForNewLoanCreation(clientAccount.getId(), clientAccount.getDisplayName(), expectedDisbursementDate, + clientAccount.getOfficeId()); if (productId != null) { LoanProductData selectedProduct = this.loanProductReadPlatformService.retrieveLoanProduct(productId); @@ -371,7 +372,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { public String loanSchema() { return "l.id as id, l.external_id as externalId, l.fund_id as fundId, f.name as fundName, " + " lp.id as loanProductId, lp.name as loanProductName, lp.description as loanProductDescription, c.id as clientId, c.display_name as clientName, " - + " l.submittedon_date as submittedOnDate," + + " c.office_id as clientOfficeId,l.submittedon_date as submittedOnDate," + " l.approvedon_date as approvedOnDate, l.expected_disbursedon_date as expectedDisbursementDate, l.disbursedon_date as actualDisbursementDate, l.expected_firstrepaymenton_date as expectedFirstRepaymentOnDate," + " l.interest_calculated_from_date as interestChargedFromDate, l.closedon_date as closedOnDate, l.expected_maturedon_date as expectedMaturityDate, " + " l.principal_amount as principal, l.arrearstolerance_amount as inArrearsTolerance, l.number_of_repayments as numberOfRepayments, l.repay_every as repaymentEvery," @@ -380,12 +381,14 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { + " l.term_frequency as termFrequency, l.term_period_frequency_enum as termPeriodFrequencyType, " + " l.amortization_method_enum as amortizationType, l.interest_method_enum as interestType, l.interest_calculated_in_period_enum as interestCalculationPeriodType," + " l.loan_status_id as lifeCycleStatusId, l.loan_transaction_strategy_id as transactionStrategyId, " - + " l.currency_code as currencyCode, l.currency_digits as currencyDigits, rc.`name` as currencyName, rc.display_symbol as currencyDisplaySymbol, rc.internationalized_name_code as currencyNameCode" + + " l.currency_code as currencyCode, l.currency_digits as currencyDigits, rc.`name` as currencyName, rc.display_symbol as currencyDisplaySymbol, rc.internationalized_name_code as currencyNameCode, " + + " l.loan_officer_id as loanOfficerId, s.display_name as loanOfficerName" + " from m_loan l" + " join m_client c on c.id = l.client_id" + " join m_product_loan lp on lp.id = l.product_id" + " join m_currency rc on rc.`code` = l.currency_code" - + " left join m_fund f on f.id = l.fund_id"; + + " left join m_fund f on f.id = l.fund_id" + + " left join m_staff s on s.id = l.loan_officer_id"; } @Override @@ -404,9 +407,12 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { Long id = rs.getLong("id"); String externalId = rs.getString("externalId"); Long clientId = JdbcSupport.getLong(rs, "clientId"); + Long clientOfficeId = JdbcSupport.getLong(rs, "clientOfficeId"); String clientName = rs.getString("clientName"); Long fundId = JdbcSupport.getLong(rs, "fundId"); String fundName = rs.getString("fundName"); + Long loanOfficerId = JdbcSupport.getLong(rs, "loanOfficerId"); + String loanOfficerName = rs.getString("loanOfficerName"); Long loanProductId = JdbcSupport.getLong(rs, "loanProductId"); String loanProductName = rs.getString("loanProductName"); String loanProductDescription = rs.getString("loanProductDescription"); @@ -471,7 +477,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { } Collection charges = null; - return new LoanBasicDetailsData(id, externalId, clientId, clientName, + return new LoanBasicDetailsData(id, externalId, clientId, clientName, clientOfficeId, loanProductId, loanProductName, loanProductDescription, fundId, fundName, closedOnDate, @@ -485,7 +491,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { amortizationType, interestType, interestCalculationPeriodType, status, - lifeCycleStatusDate, termFrequency, termPeriodFrequencyType, transactionStrategyId, charges); + lifeCycleStatusDate, termFrequency, termPeriodFrequencyType, transactionStrategyId, charges, + loanOfficerId, loanOfficerName); } } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/staff/domain/Staff.java b/mifosng-provider/src/main/java/org/mifosng/platform/staff/domain/Staff.java index 9779aab46..a15b47e5a 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/staff/domain/Staff.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/staff/domain/Staff.java @@ -2,17 +2,19 @@ package org.mifosng.platform.staff.domain; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; import javax.persistence.Table; import javax.persistence.UniqueConstraint; import org.apache.commons.lang.StringUtils; import org.mifosng.platform.api.commands.StaffCommand; import org.mifosng.platform.infrastructure.AbstractAuditableCustom; +import org.mifosng.platform.organisation.domain.Office; import org.mifosng.platform.user.domain.AppUser; @Entity -@Table(name = "m_staff", uniqueConstraints = { - @UniqueConstraint(columnNames = { "display_name" }, name = "display_name")}) +@Table(name = "m_staff", uniqueConstraints = { @UniqueConstraint(columnNames = { "display_name" }, name = "display_name") }) public class Staff extends AbstractAuditableCustom { @Column(name = "firstname", length = 50) @@ -25,21 +27,39 @@ public class Staff extends AbstractAuditableCustom { @Column(name = "display_name", length = 100) private String displayName; - public static Staff createNew(final String firstname, final String lastname) { - return new Staff(firstname, lastname); + // Office to which this employee belongs + @SuppressWarnings("unused") + @ManyToOne + @JoinColumn(name = "office_id", nullable = false) + private Office office; + + // Flag determines if employee is a loan Officer + @SuppressWarnings("unused") + @Column(name = "is_loan_officer ", nullable = false) + private Boolean loanOfficerFlag; + + public static Staff createNew(Office staffOffice, final String firstname, + final String lastname, boolean isLoanOfficer) { + return new Staff(staffOffice, firstname, lastname, isLoanOfficer); } protected Staff() { // } - private Staff(final String firstname, final String lastname) { + private Staff(final Office staffOffice, final String firstname, + final String lastname, final boolean isLoanOfficer) { + this.office = staffOffice; this.firstname = StringUtils.defaultIfEmpty(firstname, null); this.lastname = StringUtils.defaultIfEmpty(lastname, null); + this.loanOfficerFlag = isLoanOfficer; deriveDisplayName(firstname); } - public void update(final StaffCommand command) { + public void update(final StaffCommand command, final Office staffOffice) { + if (command.isOfficeChanged()) { + this.office = staffOffice; + } if (command.isFirstNameChanged()) { this.firstname = StringUtils.defaultIfEmpty(command.getFirstName(), @@ -54,6 +74,10 @@ public class Staff extends AbstractAuditableCustom { if (command.isLastNameChanged() || command.isFirstNameChanged()) { deriveDisplayName(firstname); } + + if (command.isLoanOfficerFlagChanged()) { + this.loanOfficerFlag = command.isLoanOfficerFlag(); + } } private void deriveDisplayName(final String firstname) { @@ -64,4 +88,8 @@ public class Staff extends AbstractAuditableCustom { } } + public Boolean getLoanOfficerFlag() { + return loanOfficerFlag; + } + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffCommandValidator.java b/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffCommandValidator.java index 484549d70..afb0bb06c 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffCommandValidator.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffCommandValidator.java @@ -29,6 +29,10 @@ public class StaffCommandValidator { baseDataValidator.reset().parameter("lastname") .value(command.getLastName()).notBlank() .notExceedingLengthOf(50); + baseDataValidator.reset().parameter("officeId") + .value(command.getOfficeId()).notNull() + .integerGreaterThanZero(); + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException( 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 70a6fbf39..7a40b9746 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 @@ -8,5 +8,5 @@ public interface StaffReadPlatformService { StaffData retrieveStaff(Long staffId); - Collection retrieveAllStaff(); + Collection retrieveAllStaff(final String extraCriteria); } \ 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 50199afbf..ec7815290 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 @@ -4,6 +4,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collection; +import org.apache.commons.lang.StringUtils; import org.mifosng.platform.api.data.StaffData; import org.mifosng.platform.exceptions.StaffNotFoundException; import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource; @@ -30,7 +31,9 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService { private static final class StaffMapper implements RowMapper { public String schema() { - return " s.id as id, s.firstname as firstname, s.lastname as lastname, s.display_name as displayName from m_staff s "; + return " s.id as id,s.office_id as officeId, o.name as officeName, s.firstname as firstname, s.lastname as lastname," + + " s.display_name as displayName, s.is_loan_officer as isLoanOfficer from m_staff s " + + " join m_office o on o.id = s.office_id"; } @Override @@ -41,19 +44,27 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService { String firstname = rs.getString("firstname"); String lastname = rs.getString("lastname"); String displayName = rs.getString("displayName"); - - return new StaffData(id, firstname, lastname,displayName); + Long officeId = rs.getLong("officeId"); + boolean isLoanOfficer = rs.getBoolean("isLoanOfficer"); + String officeName = rs.getString("officeName"); + + return new StaffData(id, firstname, lastname, displayName, + officeId, officeName, isLoanOfficer); } + } @Override - public Collection retrieveAllStaff() { + public Collection retrieveAllStaff(final String extraCriteria) { context.authenticatedUser(); StaffMapper rm = new StaffMapper(); - String sql = "select " + rm.schema() + " order by s.lastname"; - + String sql = "select " + rm.schema(); + if (StringUtils.isNotBlank(extraCriteria)) { + sql += " where " + extraCriteria; + } + sql = sql + " order by s.lastname"; return this.jdbcTemplate.query(sql, rm, new Object[] {}); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffWritePlatformServiceJpaRepositoryImpl.java index 0826e3bdf..94db060b8 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/staff/service/StaffWritePlatformServiceJpaRepositoryImpl.java @@ -2,11 +2,14 @@ package org.mifosng.platform.staff.service; import org.apache.commons.lang.StringUtils; import org.mifosng.platform.api.commands.StaffCommand; -import org.mifosng.platform.exceptions.StaffNotFoundException; +import org.mifosng.platform.exceptions.OfficeNotFoundException; import org.mifosng.platform.exceptions.PlatformDataIntegrityException; +import org.mifosng.platform.exceptions.StaffNotFoundException; +import org.mifosng.platform.organisation.domain.Office; +import org.mifosng.platform.organisation.domain.OfficeRepository; +import org.mifosng.platform.security.PlatformSecurityContext; import org.mifosng.platform.staff.domain.Staff; import org.mifosng.platform.staff.domain.StaffRepository; -import org.mifosng.platform.security.PlatformSecurityContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -23,13 +26,16 @@ public class StaffWritePlatformServiceJpaRepositoryImpl implements private final PlatformSecurityContext context; private final StaffRepository staffRepository; + private final OfficeRepository officeRepository; @Autowired public StaffWritePlatformServiceJpaRepositoryImpl( final PlatformSecurityContext context, - final StaffRepository staffRepository) { + final StaffRepository staffRepository, + final OfficeRepository officeRepository) { this.context = context; this.staffRepository = staffRepository; + this.officeRepository = officeRepository; } @Transactional @@ -42,8 +48,14 @@ public class StaffWritePlatformServiceJpaRepositoryImpl implements StaffCommandValidator validator = new StaffCommandValidator(command); validator.validateForCreate(); - Staff staff = Staff.createNew(command.getFirstName(), - command.getLastName()); + Office staffOffice = this.officeRepository.findOne(command + .getOfficeId()); + if (staffOffice == null) { + throw new OfficeNotFoundException(command.getOfficeId()); + } + + Staff staff = Staff.createNew(staffOffice, command.getFirstName(), + command.getLastName(), command.isLoanOfficerFlag()); this.staffRepository.saveAndFlush(staff); @@ -69,7 +81,17 @@ public class StaffWritePlatformServiceJpaRepositoryImpl implements if (staff == null) { throw new StaffNotFoundException(staffId); } - staff.update(command); + + Office staffOffice = null; + Long officeId = command.getOfficeId(); + if (command.isOfficeChanged() && officeId != null) { + staffOffice = this.officeRepository.findOne(officeId); + if (staffOffice == null) { + throw new OfficeNotFoundException(command.getOfficeId()); + } + } + + staff.update(command, staffOffice); this.staffRepository.saveAndFlush(staff);