diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm
index 2c7a1d70e..c30f91868 100644
--- a/api-docs/apiLive.htm
+++ b/api-docs/apiLive.htm
@@ -3901,12 +3901,14 @@ GET https://DomainName/mifosng-provider/api/v1/groups
The type of transaction processing strategy to be used.
At present some MFI specific ones exist. This is an important point of change for many MFIs.
Responsible for things like payment order and how early or late repayments should be processed.
- Out of the box, four available:
+ Out of the box options available are:
- id=1, code=mifos-standard-strategy, name=Mifos style
- id=2, code=heavensfamily-strategy, name=Heavensfamily
- id=3, code=creocore-strategy, name=Creocore
- id=4, code=rbi-india-strategy, name=RBI (India)
+ - id=5, code=principal-interest-penalties-fees-order-strategy, name=Principal Interest Penalties Fees Order
+ - id=6, code=interest-principal-penalties-fees-order-strategy, name=Interest Principal Penalties Fees Order
|
@@ -3973,6 +3975,13 @@ GET https://DomainName/mifosng-provider/api/v1/groups
If entered, productId, productName and selectedProduct
fields are returned.
+
+ loanOfficersInSelectedOfficeOnly
+
+ Boolean optional
+
+ Defaults to false if not provided. If loanOfficersInSelectedOfficeOnly=true only loan officers
+ who are associated with the select branch are returned.
Example Requests:
loans/template?templateType=individual&clientId=1
@@ -6995,12 +7004,14 @@ Request Body:
The type of transaction processing strategy to be used.
At present some MFI specific ones exist. This is an important point of change for many MFIs.
Responsible for things like payment order and how early or late repayments should be processed.
- Out of the box, four available:
+ Out of the box options available are:
- id=1, code=mifos-standard-strategy, name=Mifos style
- id=2, code=heavensfamily-strategy, name=Heavensfamily
- id=3, code=creocore-strategy, name=Creocore
- id=4, code=rbi-india-strategy, name=RBI (India)
+ - id=5, code=principal-interest-penalties-fees-order-strategy, name=Principal Interest Penalties Fees Order
+ - id=6, code=interest-principal-penalties-fees-order-strategy, name=Interest Principal Penalties Fees Order
|
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/organisation/staff/api/StaffApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/organisation/staff/api/StaffApiResource.java
index 1138c4e18..22009a5e7 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/organisation/staff/api/StaffApiResource.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/organisation/staff/api/StaffApiResource.java
@@ -22,7 +22,6 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
-import org.apache.commons.lang.StringUtils;
import org.mifosplatform.commands.domain.CommandWrapper;
import org.mifosplatform.commands.service.CommandWrapperBuilder;
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -81,8 +80,7 @@ public class StaffApiResource {
context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions);
- final String extraCriteria = getStaffCriteria(sqlSearch, officeId);
- final Collection staff = this.readPlatformService.retrieveAllStaff(extraCriteria);
+ final Collection staff = this.readPlatformService.retrieveAllStaff(sqlSearch, officeId);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, staff, RESPONSE_DATA_PARAMETERS);
@@ -131,22 +129,4 @@ public class StaffApiResource {
return this.toApiJsonSerializer.serialize(result);
}
-
- private String getStaffCriteria(final String sqlSearch, final Long 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);
- }
-
- return extraCriteria;
- }
}
\ No newline at end of file
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/organisation/staff/service/StaffReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/organisation/staff/service/StaffReadPlatformService.java
index d9fb62873..3d5e42ef0 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/organisation/staff/service/StaffReadPlatformService.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/organisation/staff/service/StaffReadPlatformService.java
@@ -13,9 +13,15 @@ public interface StaffReadPlatformService {
StaffData retrieveStaff(Long staffId);
- Collection retrieveAllStaff(final String extraCriteria);
-
Collection retrieveAllStaffForDropdown(Long officeId);
- Collection retrieveAllLoanOfficersByOffice(final Long officeId);
+ Collection retrieveAllLoanOfficersInOfficeById(final Long officeId);
+
+ /**
+ * returns all loan officers in offices that are above the provided
+ * officeId.
+ */
+ Collection retrieveAllLoanOfficersInOfficeAndItsParentOfficeHierarchy(Long officeId);
+
+ Collection retrieveAllStaff(String sqlSearch, Long officeId);
}
\ No newline at end of file
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/organisation/staff/service/StaffReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/organisation/staff/service/StaffReadPlatformServiceImpl.java
index 18c3d381c..677e46cd1 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/organisation/staff/service/StaffReadPlatformServiceImpl.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/organisation/staff/service/StaffReadPlatformServiceImpl.java
@@ -26,6 +26,7 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService {
private final JdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context;
private final StaffLookupMapper lookupMapper = new StaffLookupMapper();
+ private final StaffInOfficeHierarchyMapper staffInOfficeHierarchyMapper = new StaffInOfficeHierarchyMapper();
@Autowired
public StaffReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource) {
@@ -56,6 +57,43 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService {
}
}
+ private static final class StaffInOfficeHierarchyMapper implements RowMapper {
+
+ final String schema;
+
+ public StaffInOfficeHierarchyMapper() {
+
+ StringBuilder sqlBuilder = new StringBuilder(200);
+ sqlBuilder.append("s.id as id, s.office_id as officeId, o.name as officeName,");
+ sqlBuilder.append("s.firstname as firstname, s.lastname as lastname,");
+ sqlBuilder.append("s.display_name as displayName, s.is_loan_officer as isLoanOfficer ");
+ sqlBuilder.append("from m_office o ");
+ sqlBuilder.append("join m_office ohierarchy on o.hierarchy like concat(ohierarchy.hierarchy, '%') ");
+ sqlBuilder.append("join m_staff s on s.office_id = ohierarchy.id and s.is_loan_officer is true ");
+ sqlBuilder.append("where o.id = ? ");
+
+ this.schema = sqlBuilder.toString();
+ }
+
+ public String schema() {
+ return this.schema;
+ }
+
+ @Override
+ public StaffData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
+
+ final Long id = rs.getLong("id");
+ final String firstname = rs.getString("firstname");
+ final String lastname = rs.getString("lastname");
+ final String displayName = rs.getString("displayName");
+ final Long officeId = rs.getLong("officeId");
+ final String officeName = rs.getString("officeName");
+ final boolean isLoanOfficer = rs.getBoolean("isLoanOfficer");
+
+ return StaffData.instance(id, firstname, lastname, displayName, officeId, officeName, isLoanOfficer);
+ }
+ }
+
private static final class StaffLookupMapper implements RowMapper {
private final String schemaSql;
@@ -84,19 +122,7 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService {
}
@Override
- public Collection retrieveAllStaff(final String extraCriteria) {
-
- final StaffMapper rm = new StaffMapper();
- 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[] {});
- }
-
- @Override
- public Collection retrieveAllLoanOfficersByOffice(final Long officeId) {
+ public Collection retrieveAllLoanOfficersInOfficeById(final Long officeId) {
return retrieveAllStaff(" office_id=" + officeId + " and is_loan_officer=1");
}
@@ -132,4 +158,48 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService {
throw new StaffNotFoundException(staffId);
}
}
+
+ @Override
+ public Collection retrieveAllStaff(final String sqlSearch, final Long officeId) {
+ final String extraCriteria = getStaffCriteria(sqlSearch, officeId);
+ return retrieveAllStaff(extraCriteria);
+ }
+
+ private Collection retrieveAllStaff(final String extraCriteria) {
+
+ final StaffMapper rm = new StaffMapper();
+ 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[] {});
+ }
+
+ private String getStaffCriteria(final String sqlSearch, final Long 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);
+ }
+
+ return extraCriteria;
+ }
+
+ @Override
+ public Collection retrieveAllLoanOfficersInOfficeAndItsParentOfficeHierarchy(final Long officeId) {
+
+ String sql = "select " + this.staffInOfficeHierarchyMapper.schema();
+ sql = sql + " order by s.lastname";
+
+ return this.jdbcTemplate.query(sql, this.staffInOfficeHierarchyMapper, new Object[] { officeId });
+ }
}
\ No newline at end of file
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/BulkLoansApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/BulkLoansApiResource.java
index 7e9b2db4b..3350bf505 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/BulkLoansApiResource.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/BulkLoansApiResource.java
@@ -88,7 +88,7 @@ public class BulkLoansApiResource {
StaffAccountSummaryCollectionData staffAccountSummaryCollectionData = null;
if (officeId != null) {
- loanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersByOffice(officeId);
+ loanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersInOfficeById(officeId);
}
if (loanOfficerId != null) {
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java
index 3e9437e05..19536882e 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java
@@ -5,6 +5,7 @@
*/
package org.mifosplatform.portfolio.loanaccount.api;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
@@ -12,6 +13,7 @@ import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
@@ -162,6 +164,7 @@ public class LoansApiResource {
@Produces({ MediaType.APPLICATION_JSON })
public String template(@QueryParam("clientId") final Long clientId, @QueryParam("groupId") final Long groupId,
@QueryParam("productId") final Long productId, @QueryParam("templateType") final String templateType,
+ @DefaultValue("false") @QueryParam("loanOfficersInSelectedOfficeOnly") final boolean loanOfficersInSelectedOfficeOnly,
@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions);
@@ -223,7 +226,28 @@ public class LoansApiResource {
throw new NotSupportedLoanTemplateTypeException(errorMsg, templateType);
}
- if (officeId != null) allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersByOffice(officeId);
+ if (officeId != null) {
+ if (loanOfficersInSelectedOfficeOnly) {
+ // only bring back loan officers in selected branch/office
+ Collection loanOfficersInBranch = this.staffReadPlatformService
+ .retrieveAllLoanOfficersInOfficeById(officeId);
+
+ if (!CollectionUtils.isEmpty(loanOfficersInBranch)) {
+ allowedLoanOfficers = new ArrayList(loanOfficersInBranch);
+ }
+ } else {
+ // by default bring back all loan officers in selected
+ // branch/office as well as loan officers in officer above
+ // this office
+ Collection loanOfficersInHierarchy = this.staffReadPlatformService
+ .retrieveAllLoanOfficersInOfficeAndItsParentOfficeHierarchy(officeId);
+
+ if (!CollectionUtils.isEmpty(loanOfficersInHierarchy)) {
+ allowedLoanOfficers = new ArrayList(loanOfficersInHierarchy);
+ }
+ }
+ }
+
// add product options, allowed loan officers and calendar options
// (calendar options will be null in individual loan)
newLoanAccount = LoanAccountData.associationsAndTemplate(newLoanAccount, productOptions, allowedLoanOfficers, calendarOptions);
@@ -336,9 +360,9 @@ public class LoansApiResource {
chargeTemplate = this.loanChargeReadPlatformService.retrieveLoanChargeTemplate();
if (loanBasicDetails.officeId() != null) {
- allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersByOffice(loanBasicDetails.officeId());
+ allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersInOfficeById(loanBasicDetails.officeId());
} else if (loanBasicDetails.groupOfficeId() != null) {
- allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersByOffice(loanBasicDetails.groupOfficeId());
+ allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersInOfficeById(loanBasicDetails.groupOfficeId());
}
loanPurposeOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode("LoanPurpose");
@@ -492,8 +516,8 @@ public class LoansApiResource {
// for officeId and loanOfficerId in current way!
final LoanAccountData loanBasicDetails = this.loanReadPlatformService.retrieveOne(loanId);
- final Collection allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersByOffice(loanBasicDetails
- .officeId());
+ final Collection allowedLoanOfficers = this.staffReadPlatformService
+ .retrieveAllLoanOfficersInOfficeById(loanBasicDetails.officeId());
final Long fromLoanOfficerId = loanBasicDetails.loanOfficerId();
final BulkTransferLoanOfficerData loanReassignmentData = BulkTransferLoanOfficerData.template(fromLoanOfficerId,