Branch Specific Products and Charges - initial commit

This commit is contained in:
Binny G Sreevas
2014-12-06 14:16:28 +05:30
parent c7f3f416ad
commit 9d11434ee7
26 changed files with 1230 additions and 38 deletions
@@ -53,4 +53,8 @@ public class CodeValueData implements Serializable {
public Long getId() { public Long getId() {
return this.id; return this.id;
} }
public String getName() {
return this.name;
}
} }
@@ -11,4 +11,6 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface CodeValueRepository extends JpaRepository<CodeValue, Long>, JpaSpecificationExecutor<CodeValue> { public interface CodeValueRepository extends JpaRepository<CodeValue, Long>, JpaSpecificationExecutor<CodeValue> {
CodeValue findByCodeNameAndId(String codeName, Long id); CodeValue findByCodeNameAndId(String codeName, Long id);
CodeValue findByCodeNameAndLabel (String codeName, String label);
} }
@@ -43,4 +43,11 @@ public class CodeValueRepositoryWrapper {
if (codeValue == null) { throw new CodeValueNotFoundException(codeName, id); } if (codeValue == null) { throw new CodeValueNotFoundException(codeName, id); }
return codeValue; return codeValue;
} }
public CodeValue findOneByCodeNameAndLabelWithNotFoundDetection(final String codeName, final String label) {
final CodeValue codeValue = this.repository.findByCodeNameAndLabel(codeName, label);
if (codeValue == null) { throw new CodeValueNotFoundException(codeName, label); }
return codeValue;
}
} }
@@ -20,4 +20,9 @@ public class CodeValueNotFoundException extends AbstractPlatformResourceNotFound
super("error.msg.codevalue.codename.id.combination.invalid", "Code value with identifier " + id super("error.msg.codevalue.codename.id.combination.invalid", "Code value with identifier " + id
+ " does not exist for a code with name " + codeName, id, codeName); + " does not exist for a code with name " + codeName, id, codeName);
} }
public CodeValueNotFoundException(final String codeName, final String label) {
super("error.msg.codevalue.codename.id.combination.invalid", "Code value with label " + label
+ " does not exist for a code with name " + codeName, label, codeName);
}
} }
@@ -0,0 +1,35 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.infrastructure.entityaccess;
public class MifosEntityAccessConstants {
public static final String GLOBAL_CONFIG_FOR_OFFICE_SPECIFIC_PRODUCTS = "office-specific-products-enabled";
public static final String GLOBAL_CONFIG_FOR_RESTRICT_PRODUCTS_TO_USER_OFFICE = "restrict-products-to-user-office";
public static final String ENTITY_ACCESS_CODENAME = "Entity to Entity Access Types";
/***
* Enum of all parameters passed in while creating/updating an entity access
***/
public static enum ENTITY_ACCESS_JSON_INPUT_PARAMS {
ENTITY_TYPE("entityType"),
ENTITY_ID("entityId"),
ENTITY_ACCESS_TYPE_ID("entityAccessTypeId"),
SECOND_ENTITY_TYPE("secondEntityType"),
SECOND_ENTITY_ID("secondEntityId")
;
private final String value;
private ENTITY_ACCESS_JSON_INPUT_PARAMS(final String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
}
}
@@ -0,0 +1,33 @@
package org.mifosplatform.infrastructure.entityaccess.data;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntity;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityAccessType;
public class MifosEntityAccessData {
private MifosEntity firstEntity;
private MifosEntityAccessType accessType;
private MifosEntity secondEntity;
public MifosEntityAccessData (
MifosEntity firstEntity,
MifosEntityAccessType accessType,
MifosEntity secondEntity
) {
this.firstEntity = firstEntity;
this.accessType = accessType;
this.secondEntity = secondEntity;
}
public MifosEntity getFirstEntity() {
return this.firstEntity;
}
public MifosEntityAccessType getAccessType() {
return this.accessType;
}
public MifosEntity getSecondEntity() {
return this.secondEntity;
}
}
@@ -0,0 +1,23 @@
package org.mifosplatform.infrastructure.entityaccess.domain;
public class MifosEntity {
private Long entityId;
private MifosEntityType type;
@SuppressWarnings("unused")
private MifosEntity() {
}
public MifosEntity(Long entityId, MifosEntityType type) {
this.entityId = entityId;
this.type = type;
}
public Long getId () {
return this.entityId;
}
public MifosEntityType getType () {
return this.type;
}
}
@@ -0,0 +1,152 @@
package org.mifosplatform.infrastructure.entityaccess.domain;
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
import java.util.LinkedHashMap;
import java.util.Map;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.entityaccess.MifosEntityAccessConstants;
import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity
@Table(name = "m_entity_to_entity_access")
public class MifosEntityAccess extends AbstractPersistable<Long> {
@Column(name = "entity_type", length = 50)
private String entityType;
@Column(name = "entity_id")
private Long entityId;
@ManyToOne
@JoinColumn(name = "access_type_code_value_id", nullable = false)
private CodeValue accessType;
@Column(name = "second_entity_type", length = 50)
private String secondEntityType;
@Column(name = "second_entity_id")
private Long secondEntityId;
protected MifosEntityAccess () {
}
public static MifosEntityAccess createNew(final String entityType, final Long entityId,
final CodeValue accessType,
final String secondEntityType, final Long secondEntityId) {
return new MifosEntityAccess(entityType, entityId, accessType,
secondEntityType, secondEntityId);
}
public MifosEntityAccess(final String entityType, final Long entityId,
final CodeValue accessType,
final String secondEntityType, final Long secondEntityId) {
this.entityType = entityType;
this.entityId = entityId;
this.accessType = accessType;
this.secondEntityType = secondEntityType;
this.secondEntityId = secondEntityId;
}
public static MifosEntityAccess fromJson(final CodeValue accessType, final JsonCommand command) {
final String entityType = command.stringValueOfParameterNamed(
MifosEntityAccessConstants.ENTITY_ACCESS_JSON_INPUT_PARAMS.ENTITY_TYPE.getValue());
final Long entityId = command.longValueOfParameterNamed(
MifosEntityAccessConstants.ENTITY_ACCESS_JSON_INPUT_PARAMS.ENTITY_ID.getValue());
final String secondEntityType = command.stringValueOfParameterNamed(
MifosEntityAccessConstants.ENTITY_ACCESS_JSON_INPUT_PARAMS.SECOND_ENTITY_ID.getValue());
final Long secondEntityId = command.longValueOfParameterNamed(
MifosEntityAccessConstants.ENTITY_ACCESS_JSON_INPUT_PARAMS.SECOND_ENTITY_ID.getValue());
return new MifosEntityAccess (entityType, entityId, accessType,
secondEntityType, secondEntityId);
}
public Map<String, Object> update(final JsonCommand command) {
final Map<String, Object> actualChanges = new LinkedHashMap<>();
String paramName = null;
paramName = MifosEntityAccessConstants.ENTITY_ACCESS_JSON_INPUT_PARAMS.ENTITY_TYPE.getValue();
if (command.isChangeInStringParameterNamed(paramName, this.entityType)) {
final String newValue = command.stringValueOfParameterNamed(paramName);
actualChanges.put(paramName, newValue);
this.entityType = newValue;
}
paramName = MifosEntityAccessConstants.ENTITY_ACCESS_JSON_INPUT_PARAMS.ENTITY_ID.getValue();
if (command.isChangeInLongParameterNamed(paramName, getEntityId())) {
this.entityId = command.longValueOfParameterNamed(paramName);
actualChanges.put(paramName, this.entityId);
}
Long existingAccessTypeId = null;
if (this.accessType != null) {
existingAccessTypeId = this.accessType.getId();
}
paramName = MifosEntityAccessConstants.ENTITY_ACCESS_JSON_INPUT_PARAMS.ENTITY_ACCESS_TYPE_ID.getValue();
if (command.isChangeInLongParameterNamed(paramName, existingAccessTypeId)) {
final Long newValue = command.longValueOfParameterNamed(paramName);
actualChanges.put(paramName, newValue);
}
paramName = MifosEntityAccessConstants.ENTITY_ACCESS_JSON_INPUT_PARAMS.SECOND_ENTITY_TYPE.getValue();
if (command.isChangeInStringParameterNamed(paramName, this.secondEntityType)) {
final String newValue = command.stringValueOfParameterNamed(paramName);
actualChanges.put(paramName, newValue);
this.secondEntityType = newValue;
}
paramName = MifosEntityAccessConstants.ENTITY_ACCESS_JSON_INPUT_PARAMS.SECOND_ENTITY_ID.getValue();
if (command.isChangeInLongParameterNamed(paramName, getSecondEntityId())) {
this.secondEntityId = command.longValueOfParameterNamed(paramName);
actualChanges.put(paramName, this.secondEntityId);
}
return actualChanges;
}
public String getEntityType() {
return this.entityType;
}
public Long getEntityId() {
return this.entityId;
}
public CodeValue getAccessType() {
return this.accessType;
}
public void updateAccessType(final CodeValue accessType) {
this.accessType = accessType;
}
public String getSecondEntityType() {
return this.secondEntityType;
}
public Long getSecondEntityId() {
return this.secondEntityId;
}
}
@@ -0,0 +1,13 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.infrastructure.entityaccess.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface MifosEntityAccessRepository extends JpaRepository<MifosEntityAccess, Long>, JpaSpecificationExecutor<MifosEntityAccess> {
// no added behaviour
}
@@ -0,0 +1,46 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.infrastructure.entityaccess.domain;
import org.mifosplatform.infrastructure.entityaccess.exception.MifosEntityAccessNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* <p>
* Wrapper for {@link MifosEntityAccessRepository} that adds NULL checking and Error
* handling capabilities
* </p>
*/
@Service
public class MifosEntityAccessRepositoryWrapper {
private final MifosEntityAccessRepository repository;
@Autowired
public MifosEntityAccessRepositoryWrapper(final MifosEntityAccessRepository repository) {
this.repository = repository;
}
public MifosEntityAccess findOneWithNotFoundDetection(final Long id) {
final MifosEntityAccess mifosEntityAccess = this.repository.findOne(id);
if (mifosEntityAccess == null) { throw new MifosEntityAccessNotFoundException(id); }
return mifosEntityAccess;
}
public void save(final MifosEntityAccess mifosEntityAccess) {
this.repository.save(mifosEntityAccess);
}
public void saveAndFlush(final MifosEntityAccess mifosEntityAccess) {
this.repository.saveAndFlush(mifosEntityAccess);
}
public void delete(final MifosEntityAccess mifosEntityAccess) {
this.repository.delete(mifosEntityAccess);
}
}
@@ -0,0 +1,33 @@
package org.mifosplatform.infrastructure.entityaccess.domain;
public class MifosEntityAccessType {
private String str;
public static final MifosEntityAccessType OFFICE_ACCESS_TO_LOAN_PRODUCTS = new MifosEntityAccessType("Office Access to Loan Products");
public static final MifosEntityAccessType OFFICE_ACCESS_TO_SAVINGS_PRODUCTS = new MifosEntityAccessType("Office Access to Savings Products");
public static final MifosEntityAccessType OFFICE_ACCESS_TO_CHARGES = new MifosEntityAccessType("Office Access to Fees/Charges");
private MifosEntityAccessType (String str) {
this.str = str;
}
public String toStr () {
return this.str;
}
public static MifosEntityAccessType get (String type) {
MifosEntityAccessType retType = null;
if (type.equals(OFFICE_ACCESS_TO_LOAN_PRODUCTS.str)) {
retType = OFFICE_ACCESS_TO_LOAN_PRODUCTS;
} else if (type.equals(OFFICE_ACCESS_TO_SAVINGS_PRODUCTS.str)) {
retType = OFFICE_ACCESS_TO_SAVINGS_PRODUCTS;
} else if (type.equals(OFFICE_ACCESS_TO_CHARGES.str)) {
retType = OFFICE_ACCESS_TO_CHARGES;
}
return retType;
}
}
@@ -0,0 +1,47 @@
package org.mifosplatform.infrastructure.entityaccess.domain;
public class MifosEntityType {
private String type;
private String description;
private String table_name;
public static MifosEntityType OFFICE = new MifosEntityType ("office", "Offices", "m_office");
public static MifosEntityType LOAN_PRODUCT = new MifosEntityType ("loan_product", "Loan Products", "m_product_loan");
public static MifosEntityType SAVINGS_PRODUCT = new MifosEntityType ("savings_product", "Savings Products", "m_savings_product");
public static MifosEntityType CHARGE = new MifosEntityType ("charge", "Fees/Charges", "m_charge");
private MifosEntityType (String type, String description, String table_name) {
this.type = type;
this.description = description;
this.table_name = table_name;
}
public String getType () {
return this.type;
}
public String getDescription () {
return this.description;
}
public String getTable () {
return this.table_name;
}
public static MifosEntityType get (String type) {
MifosEntityType retType = null;
if (type.equals(OFFICE.type)) {
retType = OFFICE;
} else if (type.equals(LOAN_PRODUCT.type)) {
retType = LOAN_PRODUCT;
} else if (type.equals(SAVINGS_PRODUCT)) {
retType = SAVINGS_PRODUCT;
} else if (type.equals(CHARGE))
retType = CHARGE;
return retType;
}
}
@@ -0,0 +1,18 @@
package org.mifosplatform.infrastructure.entityaccess.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityAccessType;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityType;
public class MifosEntityAccessConfigurationException extends AbstractPlatformDomainRuleException {
public MifosEntityAccessConfigurationException(final Long firstEntityId,
final MifosEntityType entityType1,
final MifosEntityAccessType accessType,
final MifosEntityType entityType2) {
super("error.msg.entityaccess.config",
"Error while getting entity access configuration for " + entityType1.getType() + ":" + firstEntityId +
" with type " + accessType.toStr() + " against " + entityType2.getType());
}
}
@@ -0,0 +1,18 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.infrastructure.entityaccess.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
/**
* A {@link RuntimeException} thrown when office resources are not found.
*/
public class MifosEntityAccessNotFoundException extends AbstractPlatformResourceNotFoundException {
public MifosEntityAccessNotFoundException(final Long id) {
super("error.msg.entityaccess.id.invalid", "MifosEntityAccess with identifier " + id + " does not exist", id);
}
}
@@ -0,0 +1,27 @@
package org.mifosplatform.infrastructure.entityaccess.service;
import java.util.Collection;
import org.mifosplatform.infrastructure.entityaccess.data.MifosEntityAccessData;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityAccessType;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityType;
public interface MifosEntityAccessReadService {
Collection<MifosEntityAccessData> retrieveEntityAccessFor (Long entityId, MifosEntityType type,
MifosEntityAccessType accessType, MifosEntityType secondType,
boolean includeAllOffices);
String getSQLQueryInClause_WithListOfIDsForEntityAccess (Long entityId, MifosEntityType firstEntityType,
MifosEntityAccessType accessType, MifosEntityType secondEntityType,
boolean includeAllOffices);
String getSQLQueryInClauseIDList_ForLoanProductsForOffice (Long loanProductId,
boolean includeAllOffices);
String getSQLQueryInClauseIDList_ForSavingsProductsForOffice(
Long savingsProductId, boolean includeAllOffices);
String getSQLQueryInClauseIDList_ForChargesForOffice(Long officeId,
boolean includeAllOffices);
}
@@ -0,0 +1,251 @@
package org.mifosplatform.infrastructure.entityaccess.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import javax.sql.DataSource;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.infrastructure.dataqueries.service.GenericDataServiceImpl;
import org.mifosplatform.infrastructure.entityaccess.MifosEntityAccessConstants;
import org.mifosplatform.infrastructure.entityaccess.data.MifosEntityAccessData;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntity;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityAccessType;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityType;
import org.mifosplatform.infrastructure.entityaccess.exception.MifosEntityAccessConfigurationException;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.useradministration.domain.AppUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
public class MifosEntityAccessReadServiceImpl implements MifosEntityAccessReadService {
private final PlatformSecurityContext context;
private final JdbcTemplate jdbcTemplate;
private final static Logger logger = LoggerFactory.getLogger(GenericDataServiceImpl.class);
@Autowired
public MifosEntityAccessReadServiceImpl(final PlatformSecurityContext context,
final RoutingDataSource dataSource) {
this.context = context;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
/*
* (non-Javadoc)
* @see org.mifosplatform.infrastructure.entityaccess.service.MifosEntityAccessReadService#getSQLQueryWithListOfIDsForEntityAccess
* (Long,
* org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityType,
* org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityAccessType,
* org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityType,
* boolean)
*
* This method returns the list of entity IDs as a comma separated list
* Or null if there is no entity restrictions or if there
*/
@Override
public String getSQLQueryInClause_WithListOfIDsForEntityAccess (
Long firstEntityId,
MifosEntityType firstEntityType,
MifosEntityAccessType accessType,
MifosEntityType secondEntityType,
boolean includeAllOffices) {
Collection<MifosEntityAccessData> accesslist = retrieveEntityAccessFor (
firstEntityId, firstEntityType, accessType, secondEntityType, includeAllOffices);
String returnIdListStr = null;
StringBuffer accessListCSVStrBuf = null;
if ( (accesslist != null) && (accesslist.size() > 0) ) {
logger.debug("Found " + accesslist.size() +
" access type restrictions while getting entity access configuration for " +
firstEntityType.getType() + ":" + firstEntityId +
" with type " + accessType.toStr() + " against " + secondEntityType.getType()
);
accessListCSVStrBuf = new StringBuffer (" ");
for (int i = 0; i < accesslist.size(); i++) {
MifosEntityAccessData accessData = (MifosEntityAccessData) accesslist.toArray()[i];
if (accessData == null) {
throw new MifosEntityAccessConfigurationException(firstEntityId, firstEntityType,
accessType, secondEntityType);
}
if (accessData.getSecondEntity().getId() == 0) { // If there is any ID that zero, then allow access to all
accessListCSVStrBuf = null;
break;
}
if (i>0) {
accessListCSVStrBuf.append(',');
}
accessListCSVStrBuf.append(accessData.getSecondEntity().getId());
}
} else {
logger.debug("Found zero access type restrictions while getting entity access configuration for " +
firstEntityType.getType() + ":" + firstEntityId +
" with type " + accessType.toStr() + " against " + secondEntityType.getType()
);
accessListCSVStrBuf = new StringBuffer();
accessListCSVStrBuf.append ("false"); // Append false so that no rows will be returned
}
if (accessListCSVStrBuf != null) {
returnIdListStr = accessListCSVStrBuf.toString();
}
logger.debug("List of IDs applicable:" + returnIdListStr);
return returnIdListStr;
}
@Override
public Collection<MifosEntityAccessData> retrieveEntityAccessFor(
Long firstEntityId,
MifosEntityType firstEntityType,
MifosEntityAccessType accessType,
MifosEntityType secondEntityType,
boolean includeAllSubOffices) {
final AppUser currentUser = this.context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
String hierarchySearchString = null;
if (includeAllSubOffices) {
hierarchySearchString = "." + "%";
} else {
hierarchySearchString = hierarchy + "%";
}
String sql = getSQLForRetriveEntityAccessFor(firstEntityType,
accessType, secondEntityType);
Collection<MifosEntityAccessData> entityAccessData = null;
MifosEntityAccessDataMapper mapper = new MifosEntityAccessDataMapper();
if (includeAllSubOffices && (firstEntityType.getTable().equals("m_office")) ) {
sql += " where firstentity.hierarchy like ? order by firstEntity.hierarchy";
entityAccessData = this.jdbcTemplate.query(sql, mapper, new Object[] { firstEntityId, hierarchySearchString });
} else {
entityAccessData = this.jdbcTemplate.query(sql, mapper, new Object[] { firstEntityId });
}
return entityAccessData;
}
private String getSQLForRetriveEntityAccessFor (
MifosEntityType firstEntityType,
MifosEntityAccessType accessType,
MifosEntityType secondEntityType) {
StringBuffer str = new StringBuffer ("select eea.entity_id as entity_id, entity_type as entity_type, ");
str.append("access_type_code_value_id as access_id, cv.code_value as access_type_desc, c.code_name as code, ");
str.append("firstentity.id as first_entity_id, firstentity.name as entity_name, ");
str.append("otherentity.id as second_entity_id, otherentity.name as second_entity_name, ");
str.append("eea.second_entity_type as second_entity_type ");
str.append("from m_entity_to_entity_access eea ");
str.append("left join m_code_value cv on (cv.code_value = ");
str.append("'");
str.append(accessType.toStr());
str.append("' ");
str.append("and eea.access_type_code_value_id = cv.id) ");
str.append("left join m_code c on (c.code_name = '");
str.append(MifosEntityAccessConstants.ENTITY_ACCESS_CODENAME);
str.append("' and cv.code_id = c.id) ");
str.append("left join ");
str.append(firstEntityType.getTable());
str.append(" firstentity on (eea.entity_type = ");
str.append("'");
str.append(firstEntityType.getType());
str.append("'");
str.append(" and eea.entity_id = firstentity.id) left join ");
str.append(secondEntityType.getTable());
str.append(" otherentity on (eea.second_entity_type = ");
str.append("'");
str.append(secondEntityType.getType());
str.append("' ");
str.append("and eea.second_entity_id = otherentity.id) ");
str.append("where eea.access_type_code_value_id = cv.id ");
str.append("and eea.entity_id = ? ");
logger.debug(str.toString());
return str.toString();
}
private static final class MifosEntityAccessDataMapper implements RowMapper<MifosEntityAccessData> {
@Override
public MifosEntityAccessData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final String entityType = rs.getString("entity_type");
final Long entityId = rs.getLong("entity_id");
final String entityName = rs.getString("entity_name");
final Long accessId = rs.getLong("access_id");
final String accessTypeDesc = rs.getString("access_type_desc");
final String code = rs.getString("code");
final Long secondEntityId = rs.getLong("second_entity_id");
final String secondEntityName = rs.getString("second_entity_name");
final String secondEntityType = rs.getString("second_entity_type");
MifosEntity firstEntity = null;
MifosEntityType etype = MifosEntityType.get(entityType);
if (entityId != null && etype != null) {
firstEntity = new MifosEntity(entityId, etype);
}
MifosEntity secondEntity = null;
MifosEntityType secondetype = MifosEntityType.get(secondEntityType);
if (entityId != null && etype != null) {
secondEntity = new MifosEntity(secondEntityId, secondetype);
}
MifosEntityAccessType accessType = null;
if (accessTypeDesc != null) {
accessType = MifosEntityAccessType.get(accessTypeDesc);
}
MifosEntityAccessData returnMifosEntityAccessData = null;
if (firstEntity != null && secondEntity != null && accessType != null) {
returnMifosEntityAccessData = new MifosEntityAccessData(firstEntity, accessType, secondEntity);
}
return returnMifosEntityAccessData;
}
}
@Override
public String getSQLQueryInClauseIDList_ForLoanProductsForOffice(
Long officeId, boolean includeAllOffices) {
MifosEntityType firstEntityType = MifosEntityType.OFFICE;
MifosEntityAccessType accessType = MifosEntityAccessType.OFFICE_ACCESS_TO_LOAN_PRODUCTS;
MifosEntityType secondEntityType = MifosEntityType.LOAN_PRODUCT;
return getSQLQueryInClause_WithListOfIDsForEntityAccess (
officeId, firstEntityType, accessType,
secondEntityType, includeAllOffices);
}
@Override
public String getSQLQueryInClauseIDList_ForSavingsProductsForOffice(
Long officeId, boolean includeAllOffices) {
MifosEntityType firstEntityType = MifosEntityType.OFFICE;
MifosEntityAccessType accessType = MifosEntityAccessType.OFFICE_ACCESS_TO_SAVINGS_PRODUCTS;
MifosEntityType secondEntityType = MifosEntityType.SAVINGS_PRODUCT;
return getSQLQueryInClause_WithListOfIDsForEntityAccess (
officeId, firstEntityType, accessType,
secondEntityType, includeAllOffices);
}
@Override
public String getSQLQueryInClauseIDList_ForChargesForOffice(
Long officeId, boolean includeAllOffices) {
MifosEntityType firstEntityType = MifosEntityType.OFFICE;
MifosEntityAccessType accessType = MifosEntityAccessType.OFFICE_ACCESS_TO_CHARGES;
MifosEntityType secondEntityType = MifosEntityType.CHARGE;
return getSQLQueryInClause_WithListOfIDsForEntityAccess (
officeId, firstEntityType, accessType,
secondEntityType, includeAllOffices);
}
}
@@ -0,0 +1,130 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.infrastructure.entityaccess.service;
import java.util.Collection;
import java.util.Iterator;
import org.mifosplatform.infrastructure.configuration.domain.GlobalConfigurationProperty;
import org.mifosplatform.infrastructure.configuration.domain.GlobalConfigurationRepositoryWrapper;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.codes.domain.CodeValueRepositoryWrapper;
import org.mifosplatform.infrastructure.codes.service.CodeValueReadPlatformService;
import org.mifosplatform.infrastructure.entityaccess.MifosEntityAccessConstants;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityAccessType;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityType;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class MifosEntityAccessUtil {
private final PlatformSecurityContext context;
private final GlobalConfigurationRepositoryWrapper globalConfigurationRepository;
private final CodeValueReadPlatformService codeValueReadPlatformService;
private final CodeValueRepositoryWrapper codeValueRepository;
private final MifosEntityAccessWriteService mifosEntityAccessWriteService;
private final MifosEntityAccessReadService mifosEntityAccessReadService;
@Autowired
public MifosEntityAccessUtil (
final PlatformSecurityContext context,
final GlobalConfigurationRepositoryWrapper globalConfigurationRepository,
final MifosEntityAccessWriteService mifosEntityAccessWriteService,
final CodeValueReadPlatformService codeValueReadPlatformService,
final CodeValueRepositoryWrapper codeValueRepository,
final MifosEntityAccessReadService mifosEntityAccessReadService) {
this.context = context;
this.globalConfigurationRepository = globalConfigurationRepository;
this.mifosEntityAccessWriteService = mifosEntityAccessWriteService;
this.codeValueReadPlatformService = codeValueReadPlatformService;
this.codeValueRepository = codeValueRepository;
this.mifosEntityAccessReadService = mifosEntityAccessReadService;
}
@Transactional
public void checkConfigurationAndAddProductResrictionsForUserOffice (
final MifosEntityAccessType mifosEntityAccessType,
final MifosEntityType mifosEntityType,
final Long productOrChargeId) {
AppUser thisUser = this.context.authenticatedUser();
// check if the office specific products are enabled. If yes, then save this product or charge against a specific office
// i.e. this product or charge is specific for this office.
final GlobalConfigurationProperty property = this.globalConfigurationRepository
.findOneByNameWithNotFoundDetection(
MifosEntityAccessConstants.GLOBAL_CONFIG_FOR_OFFICE_SPECIFIC_PRODUCTS);
if (property.isEnabled() ) {
// If this property is enabled, then Mifos need to restrict access to this loan product to only the office of the current user
final GlobalConfigurationProperty restrictToUserOfficeProperty = this.globalConfigurationRepository
.findOneByNameWithNotFoundDetection(
MifosEntityAccessConstants.GLOBAL_CONFIG_FOR_RESTRICT_PRODUCTS_TO_USER_OFFICE);
if (restrictToUserOfficeProperty.isEnabled() ) {
final Long officeId = thisUser.getOffice().getId();
Collection<CodeValueData> codevalues = codeValueReadPlatformService.retrieveCodeValuesByCode(
MifosEntityAccessConstants.ENTITY_ACCESS_CODENAME);
if (codevalues != null) {
Iterator<CodeValueData> iterator = codevalues.iterator();
while(iterator.hasNext()) {
CodeValueData oneCodeValue = iterator.next();
if ( (oneCodeValue != null) &&
(oneCodeValue.getName().equals(mifosEntityAccessType.toStr())) ) {
CodeValue cv = codeValueRepository.findOneByCodeNameAndLabelWithNotFoundDetection(
MifosEntityAccessConstants.ENTITY_ACCESS_CODENAME,
mifosEntityAccessType.toStr()
);
if (cv != null) {
mifosEntityAccessWriteService.addNewEntityAccess(
MifosEntityType.OFFICE.getType(), officeId,
cv,
mifosEntityType.getType(), productOrChargeId);
}
}
}
}
}
}
}
public String getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled (
MifosEntityType mifosEntityType) {
String inClause = "";
final GlobalConfigurationProperty property = this.globalConfigurationRepository
.findOneByNameWithNotFoundDetection(
MifosEntityAccessConstants.GLOBAL_CONFIG_FOR_OFFICE_SPECIFIC_PRODUCTS);
if (property.isEnabled() ) {
// Get 'SQL In Clause' for fetching only products/charges that are relevant for current user's office
if (mifosEntityType.equals(MifosEntityType.SAVINGS_PRODUCT)) {
inClause = mifosEntityAccessReadService.
getSQLQueryInClauseIDList_ForSavingsProductsForOffice (
this.context.authenticatedUser().getOffice().getId(), false);
} else if (mifosEntityType.equals(MifosEntityType.LOAN_PRODUCT)) {
inClause = mifosEntityAccessReadService.
getSQLQueryInClauseIDList_ForLoanProductsForOffice (
this.context.authenticatedUser().getOffice().getId(), false);
} else if (mifosEntityType.equals(MifosEntityType.CHARGE)) {
inClause = mifosEntityAccessReadService.
getSQLQueryInClauseIDList_ForChargesForOffice(
this.context.authenticatedUser().getOffice().getId(), false);
}
}
return inClause;
}
}
@@ -0,0 +1,30 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.infrastructure.entityaccess.service;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
public interface MifosEntityAccessWriteService {
CommandProcessingResult createEntityAccess (
final JsonCommand command);
void addNewEntityAccess (final String entityType, final Long entityId,
final CodeValue accessType,
final String secondEntityType, final Long secondEntityId);
/*
CommandProcessingResult updateEntityAccess (
final Long entityAccessId, final JsonCommand command);
CommandProcessingResult removeEntityAccess (
final String entityType, final Long entityId,
final Long accessType,
final String secondEntityType, final Long secondEntityId);
*/
}
@@ -0,0 +1,72 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.infrastructure.entityaccess.service;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.codes.domain.CodeValueRepositoryWrapper;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityAccess;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityAccessRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class MifosEntityAccessWriteServiceImpl implements
MifosEntityAccessWriteService {
private final static Logger logger = LoggerFactory.getLogger(MifosEntityAccessWriteServiceImpl.class);
private final CodeValueRepositoryWrapper codeValueRepositoryWrapper;
private final MifosEntityAccessRepository entityAccessRepository;
@Autowired
public MifosEntityAccessWriteServiceImpl(
final MifosEntityAccessRepository entityAccessRepository,
final CodeValueRepositoryWrapper codeValueRepositoryWrapper) {
this.entityAccessRepository = entityAccessRepository;
this.codeValueRepositoryWrapper = codeValueRepositoryWrapper;
}
@Override
public CommandProcessingResult createEntityAccess(JsonCommand command) {
// TODO Auto-generated method stub
return null;
}
@Override
@Transactional
public void addNewEntityAccess (final String entityType, final Long entityId,
final CodeValue accessType,
final String secondEntityType, final Long secondEntityId) {
MifosEntityAccess entityAccess = MifosEntityAccess.createNew(entityType, entityId,
accessType, secondEntityType, secondEntityId);
entityAccessRepository.save(entityAccess);
}
/*
@Override
public CommandProcessingResult updateEntityAccess(Long entityAccessId,
JsonCommand command) {
// TODO Auto-generated method stub
return null;
}
@Override
public CommandProcessingResult removeEntityAccess(String entityType,
Long entityId, Long accessType, String secondEntityType,
Long secondEntityId) {
// TODO Auto-generated method stub
return null;
}
*/
}
@@ -16,6 +16,8 @@ import org.joda.time.MonthDay;
import org.mifosplatform.infrastructure.core.data.EnumOptionData; import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport; import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource; import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityType;
import org.mifosplatform.infrastructure.entityaccess.service.MifosEntityAccessUtil;
import org.mifosplatform.organisation.monetary.data.CurrencyData; import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.organisation.monetary.service.CurrencyReadPlatformService; import org.mifosplatform.organisation.monetary.service.CurrencyReadPlatformService;
import org.mifosplatform.portfolio.charge.data.ChargeData; import org.mifosplatform.portfolio.charge.data.ChargeData;
@@ -42,15 +44,18 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
private final CurrencyReadPlatformService currencyReadPlatformService; private final CurrencyReadPlatformService currencyReadPlatformService;
private final ChargeDropdownReadPlatformService chargeDropdownReadPlatformService; private final ChargeDropdownReadPlatformService chargeDropdownReadPlatformService;
private final DropdownReadPlatformService dropdownReadPlatformService; private final DropdownReadPlatformService dropdownReadPlatformService;
private final MifosEntityAccessUtil mifosEntityAccessUtil;
@Autowired @Autowired
public ChargeReadPlatformServiceImpl(final CurrencyReadPlatformService currencyReadPlatformService, public ChargeReadPlatformServiceImpl(final CurrencyReadPlatformService currencyReadPlatformService,
final ChargeDropdownReadPlatformService chargeDropdownReadPlatformService, final RoutingDataSource dataSource, final ChargeDropdownReadPlatformService chargeDropdownReadPlatformService, final RoutingDataSource dataSource,
final DropdownReadPlatformService dropdownReadPlatformService) { final DropdownReadPlatformService dropdownReadPlatformService,
final MifosEntityAccessUtil mifosEntityAccessUtil) {
this.chargeDropdownReadPlatformService = chargeDropdownReadPlatformService; this.chargeDropdownReadPlatformService = chargeDropdownReadPlatformService;
this.jdbcTemplate = new JdbcTemplate(dataSource); this.jdbcTemplate = new JdbcTemplate(dataSource);
this.currencyReadPlatformService = currencyReadPlatformService; this.currencyReadPlatformService = currencyReadPlatformService;
this.dropdownReadPlatformService = dropdownReadPlatformService; this.dropdownReadPlatformService = dropdownReadPlatformService;
this.mifosEntityAccessUtil = mifosEntityAccessUtil;
} }
@Override @Override
@@ -58,7 +63,11 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
public Collection<ChargeData> retrieveAllCharges() { public Collection<ChargeData> retrieveAllCharges() {
final ChargeMapper rm = new ChargeMapper(); final ChargeMapper rm = new ChargeMapper();
final String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 order by c.name "; String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
sql += " order by c.name ";
return this.jdbcTemplate.query(sql, rm, new Object[] {}); return this.jdbcTemplate.query(sql, rm, new Object[] {});
} }
@@ -67,8 +76,12 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
public Collection<ChargeData> retrieveAllChargesForCurrency(String currencyCode) { public Collection<ChargeData> retrieveAllChargesForCurrency(String currencyCode) {
final ChargeMapper rm = new ChargeMapper(); final ChargeMapper rm = new ChargeMapper();
final String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 and c.currency_code='" + currencyCode String sql = "select " + rm.chargeSchema() + " where c.is_deleted=0 and c.currency_code='" + currencyCode
+ "' order by c.name "; + "' ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
sql += " order by c.name ";
return this.jdbcTemplate.query(sql, rm, new Object[] {}); return this.jdbcTemplate.query(sql, rm, new Object[] {});
} }
@@ -78,7 +91,9 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
try { try {
final ChargeMapper rm = new ChargeMapper(); final ChargeMapper rm = new ChargeMapper();
final String sql = "select " + rm.chargeSchema() + " where c.id = ? and c.is_deleted=0 "; String sql = "select " + rm.chargeSchema() + " where c.id = ? and c.is_deleted=0 ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { chargeId }); return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { chargeId });
} catch (final EmptyResultDataAccessException e) { } catch (final EmptyResultDataAccessException e) {
@@ -112,7 +127,9 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
public Collection<ChargeData> retrieveLoanProductCharges(final Long loanProductId) { public Collection<ChargeData> retrieveLoanProductCharges(final Long loanProductId) {
final ChargeMapper rm = new ChargeMapper(); final ChargeMapper rm = new ChargeMapper();
final String sql = "select " + rm.loanProductChargeSchema() + " where c.is_deleted=0 and c.is_active=1 and plc.product_loan_id=?"; String sql = "select " + rm.loanProductChargeSchema() + " where c.is_deleted=0 and c.is_active=1 and plc.product_loan_id=? ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
return this.jdbcTemplate.query(sql, rm, new Object[] { loanProductId }); return this.jdbcTemplate.query(sql, rm, new Object[] { loanProductId });
} }
@@ -122,8 +139,9 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
final ChargeMapper rm = new ChargeMapper(); final ChargeMapper rm = new ChargeMapper();
final String sql = "select " + rm.loanProductChargeSchema() String sql = "select " + rm.loanProductChargeSchema()
+ " where c.is_deleted=0 and c.is_active=1 and plc.product_loan_id=? and c.charge_time_enum=?"; + " where c.is_deleted=0 and c.is_active=1 and plc.product_loan_id=? and c.charge_time_enum=? ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
return this.jdbcTemplate.query(sql, rm, new Object[] { loanProductId, chargeTime.getValue() }); return this.jdbcTemplate.query(sql, rm, new Object[] { loanProductId, chargeTime.getValue() });
} }
@@ -133,7 +151,9 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
final ChargeMapper rm = new ChargeMapper(); final ChargeMapper rm = new ChargeMapper();
Object[] params = new Object[] { ChargeAppliesTo.LOAN.getValue() }; Object[] params = new Object[] { ChargeAppliesTo.LOAN.getValue() };
String sql = "select " + rm.chargeSchema() String sql = "select " + rm.chargeSchema()
+ " where c.is_deleted=0 and c.is_active=1 and c.is_penalty=0 and c.charge_applies_to_enum=? order by c.name "; + " where c.is_deleted=0 and c.is_active=1 and c.is_penalty=0 and c.charge_applies_to_enum=? ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
sql += " order by c.name ";
return this.jdbcTemplate.query(sql, rm, params); return this.jdbcTemplate.query(sql, rm, params);
} }
@@ -145,7 +165,10 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
Object[] params = new Object[] { loanId, ChargeAppliesTo.LOAN.getValue() }; Object[] params = new Object[] { loanId, ChargeAppliesTo.LOAN.getValue() };
params = processChargeExclusionsForLoans(excludeChargeTimes, excludeClause, params); params = processChargeExclusionsForLoans(excludeChargeTimes, excludeClause, params);
String sql = "select " + rm.chargeSchema() + " join m_loan la on la.currency_code = c.currency_code" + " where la.id=?" String sql = "select " + rm.chargeSchema() + " join m_loan la on la.currency_code = c.currency_code" + " where la.id=?"
+ " and c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=?" + excludeClause + " order by c.name "; + " and c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=?" + excludeClause + " ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
sql += " order by c.name ";
return this.jdbcTemplate.query(sql, rm, params); return this.jdbcTemplate.query(sql, rm, params);
} }
@@ -179,7 +202,9 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
Object[] params = new Object[] { loanProductId, ChargeAppliesTo.LOAN.getValue() }; Object[] params = new Object[] { loanProductId, ChargeAppliesTo.LOAN.getValue() };
params = processChargeExclusionsForLoans(excludeChargeTimes, excludeClause, params); params = processChargeExclusionsForLoans(excludeChargeTimes, excludeClause, params);
String sql = "select " + rm.chargeSchema() + " join m_product_loan lp on lp.currency_code = c.currency_code" + " where lp.id=?" String sql = "select " + rm.chargeSchema() + " join m_product_loan lp on lp.currency_code = c.currency_code" + " where lp.id=?"
+ " and c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=?" + excludeClause + " order by c.name "; + " and c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=?" + excludeClause + " ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
sql += " order by c.name ";
return this.jdbcTemplate.query(sql, rm, params); return this.jdbcTemplate.query(sql, rm, params);
} }
@@ -188,11 +213,28 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
public Collection<ChargeData> retrieveLoanApplicablePenalties() { public Collection<ChargeData> retrieveLoanApplicablePenalties() {
final ChargeMapper rm = new ChargeMapper(); final ChargeMapper rm = new ChargeMapper();
final String sql = "select " + rm.chargeSchema() String sql = "select " + rm.chargeSchema()
+ " where c.is_deleted=0 and c.is_active=1 and c.is_penalty=1 and c.charge_applies_to_enum=? order by c.name "; + " where c.is_deleted=0 and c.is_active=1 and c.is_penalty=1 and c.charge_applies_to_enum=? ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
sql += " order by c.name ";
return this.jdbcTemplate.query(sql, rm, new Object[] { ChargeAppliesTo.LOAN.getValue() }); return this.jdbcTemplate.query(sql, rm, new Object[] { ChargeAppliesTo.LOAN.getValue() });
} }
private String addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled () {
String sql = "";
// Check if branch specific products are enabled. If yes, fetch only charges mapped to current user's office
String inClause = mifosEntityAccessUtil.
getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(
MifosEntityType.CHARGE);
if ( (inClause != null) && (!(inClause.trim().isEmpty())) ) {
sql += " and c.id in ( " + inClause + " ) ";
}
return sql;
}
private static final class ChargeMapper implements RowMapper<ChargeData> { private static final class ChargeMapper implements RowMapper<ChargeData> {
public String chargeSchema() { public String chargeSchema() {
@@ -271,11 +313,13 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
final ChargeMapper rm = new ChargeMapper(); final ChargeMapper rm = new ChargeMapper();
String sql = "select " + rm.chargeSchema() String sql = "select " + rm.chargeSchema()
+ " where c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=? order by c.name "; + " where c.is_deleted=0 and c.is_active=1 and c.charge_applies_to_enum=? ";
if (feeChargesOnly) { if (feeChargesOnly) {
sql = "select " + rm.chargeSchema() sql = "select " + rm.chargeSchema()
+ " where c.is_deleted=0 and c.is_active=1 and c.is_penalty=0 and c.charge_applies_to_enum=? order by c.name "; + " where c.is_deleted=0 and c.is_active=1 and c.is_penalty=0 and c.charge_applies_to_enum=? ";
} }
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
sql += " order by c.name ";
return this.jdbcTemplate.query(sql, rm, new Object[] { ChargeAppliesTo.SAVINGS.getValue() }); return this.jdbcTemplate.query(sql, rm, new Object[] { ChargeAppliesTo.SAVINGS.getValue() });
} }
@@ -284,8 +328,10 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
public Collection<ChargeData> retrieveSavingsApplicablePenalties() { public Collection<ChargeData> retrieveSavingsApplicablePenalties() {
final ChargeMapper rm = new ChargeMapper(); final ChargeMapper rm = new ChargeMapper();
final String sql = "select " + rm.chargeSchema() String sql = "select " + rm.chargeSchema()
+ " where c.is_deleted=0 and c.is_active=1 and c.is_penalty=1 and c.charge_applies_to_enum=? order by c.name "; + " where c.is_deleted=0 and c.is_active=1 and c.is_penalty=1 and c.charge_applies_to_enum=? ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
sql += " order by c.name ";
return this.jdbcTemplate.query(sql, rm, new Object[] { ChargeAppliesTo.SAVINGS.getValue() }); return this.jdbcTemplate.query(sql, rm, new Object[] { ChargeAppliesTo.SAVINGS.getValue() });
} }
@@ -293,8 +339,9 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
public Collection<ChargeData> retrieveSavingsProductCharges(final Long savingsProductId) { public Collection<ChargeData> retrieveSavingsProductCharges(final Long savingsProductId) {
final ChargeMapper rm = new ChargeMapper(); final ChargeMapper rm = new ChargeMapper();
final String sql = "select " + rm.savingsProductChargeSchema() String sql = "select " + rm.savingsProductChargeSchema()
+ " where c.is_deleted=0 and c.is_active=1 and spc.savings_product_id=?"; + " where c.is_deleted=0 and c.is_active=1 and spc.savings_product_id=? ";
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
return this.jdbcTemplate.query(sql, rm, new Object[] { savingsProductId }); return this.jdbcTemplate.query(sql, rm, new Object[] { savingsProductId });
} }
@@ -15,6 +15,10 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException; import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource; import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityAccessType;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityType;
import org.mifosplatform.infrastructure.entityaccess.service.MifosEntityAccessUtil;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.charge.domain.Charge; import org.mifosplatform.portfolio.charge.domain.Charge;
import org.mifosplatform.portfolio.charge.domain.ChargeRepository; import org.mifosplatform.portfolio.charge.domain.ChargeRepository;
import org.mifosplatform.portfolio.charge.exception.ChargeCannotBeDeletedException; import org.mifosplatform.portfolio.charge.exception.ChargeCannotBeDeletedException;
@@ -36,21 +40,27 @@ import org.springframework.transaction.annotation.Transactional;
public class ChargeWritePlatformServiceJpaRepositoryImpl implements ChargeWritePlatformService { public class ChargeWritePlatformServiceJpaRepositoryImpl implements ChargeWritePlatformService {
private final static Logger logger = LoggerFactory.getLogger(ChargeWritePlatformServiceJpaRepositoryImpl.class); private final static Logger logger = LoggerFactory.getLogger(ChargeWritePlatformServiceJpaRepositoryImpl.class);
private final PlatformSecurityContext context;
private final ChargeDefinitionCommandFromApiJsonDeserializer fromApiJsonDeserializer; private final ChargeDefinitionCommandFromApiJsonDeserializer fromApiJsonDeserializer;
private final JdbcTemplate jdbcTemplate; private final JdbcTemplate jdbcTemplate;
private final DataSource dataSource; private final DataSource dataSource;
private final ChargeRepository chargeRepository; private final ChargeRepository chargeRepository;
private final LoanProductRepository loanProductRepository; private final LoanProductRepository loanProductRepository;
private final MifosEntityAccessUtil mifosEntityAccessUtil;
@Autowired @Autowired
public ChargeWritePlatformServiceJpaRepositoryImpl(final ChargeDefinitionCommandFromApiJsonDeserializer fromApiJsonDeserializer, public ChargeWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
final ChargeRepository chargeRepository, final LoanProductRepository loanProductRepository, final RoutingDataSource dataSource) { final ChargeDefinitionCommandFromApiJsonDeserializer fromApiJsonDeserializer,
final ChargeRepository chargeRepository, final LoanProductRepository loanProductRepository, final RoutingDataSource dataSource,
final MifosEntityAccessUtil mifosEntityAccessUtil
) {
this.context = context;
this.fromApiJsonDeserializer = fromApiJsonDeserializer; this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.dataSource = dataSource; this.dataSource = dataSource;
this.jdbcTemplate = new JdbcTemplate(this.dataSource); this.jdbcTemplate = new JdbcTemplate(this.dataSource);
this.chargeRepository = chargeRepository; this.chargeRepository = chargeRepository;
this.loanProductRepository = loanProductRepository; this.loanProductRepository = loanProductRepository;
this.mifosEntityAccessUtil = mifosEntityAccessUtil;
} }
@Transactional @Transactional
@@ -58,11 +68,19 @@ public class ChargeWritePlatformServiceJpaRepositoryImpl implements ChargeWriteP
@CacheEvict(value = "charges", key = "T(org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil).getTenant().getTenantIdentifier().concat('ch')") @CacheEvict(value = "charges", key = "T(org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil).getTenant().getTenantIdentifier().concat('ch')")
public CommandProcessingResult createCharge(final JsonCommand command) { public CommandProcessingResult createCharge(final JsonCommand command) {
try { try {
this.context.authenticatedUser();
this.fromApiJsonDeserializer.validateForCreate(command.json()); this.fromApiJsonDeserializer.validateForCreate(command.json());
final Charge charge = Charge.fromJson(command); final Charge charge = Charge.fromJson(command);
this.chargeRepository.save(charge); this.chargeRepository.save(charge);
// check if the office specific products are enabled. If yes, then save this savings product against a specific office
// i.e. this savings product is specific for this office.
mifosEntityAccessUtil.checkConfigurationAndAddProductResrictionsForUserOffice(
MifosEntityAccessType.OFFICE_ACCESS_TO_CHARGES,
MifosEntityType.CHARGE,
charge.getId());
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(charge.getId()).build(); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(charge.getId()).build();
} catch (final DataIntegrityViolationException dve) { } catch (final DataIntegrityViolationException dve) {
handleDataIntegrityIssues(command, dve); handleDataIntegrityIssues(command, dve);
@@ -17,6 +17,8 @@ import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport; import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.DateUtils; import org.mifosplatform.infrastructure.core.service.DateUtils;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource; import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityType;
import org.mifosplatform.infrastructure.entityaccess.service.MifosEntityAccessUtil;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.monetary.data.CurrencyData; import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.portfolio.charge.data.ChargeData; import org.mifosplatform.portfolio.charge.data.ChargeData;
@@ -40,13 +42,16 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
private final PlatformSecurityContext context; private final PlatformSecurityContext context;
private final JdbcTemplate jdbcTemplate; private final JdbcTemplate jdbcTemplate;
private final ChargeReadPlatformService chargeReadPlatformService; private final ChargeReadPlatformService chargeReadPlatformService;
private final MifosEntityAccessUtil mifosEntityAccessUtil;
@Autowired @Autowired
public LoanProductReadPlatformServiceImpl(final PlatformSecurityContext context, public LoanProductReadPlatformServiceImpl(final PlatformSecurityContext context,
final ChargeReadPlatformService chargeReadPlatformService, final RoutingDataSource dataSource) { final ChargeReadPlatformService chargeReadPlatformService, final RoutingDataSource dataSource,
final MifosEntityAccessUtil mifosEntityAccessUtil) {
this.context = context; this.context = context;
this.chargeReadPlatformService = chargeReadPlatformService; this.chargeReadPlatformService = chargeReadPlatformService;
this.jdbcTemplate = new JdbcTemplate(dataSource); this.jdbcTemplate = new JdbcTemplate(dataSource);
this.mifosEntityAccessUtil = mifosEntityAccessUtil;
} }
@Override @Override
@@ -79,7 +84,15 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
final LoanProductMapper rm = new LoanProductMapper(null, null); final LoanProductMapper rm = new LoanProductMapper(null, null);
final String sql = "select " + rm.loanProductSchema(); String sql = "select " + rm.loanProductSchema();
// Check if branch specific products are enabled. If yes, fetch only products mapped to current user's office
String inClause = mifosEntityAccessUtil.
getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(
MifosEntityType.LOAN_PRODUCT);
if ( (inClause != null) && (!(inClause.trim().isEmpty())) ) {
sql += " where lp.id in ( " + inClause + " ) ";
}
return this.jdbcTemplate.query(sql, rm, new Object[] {}); return this.jdbcTemplate.query(sql, rm, new Object[] {});
} }
@@ -91,7 +104,15 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
final LoanProductLookupMapper rm = new LoanProductLookupMapper(); final LoanProductLookupMapper rm = new LoanProductLookupMapper();
final String sql = "select " + rm.schema(); String sql = "select " + rm.schema();
// Check if branch specific products are enabled. If yes, fetch only products mapped to current user's office
String inClause = mifosEntityAccessUtil.
getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(
MifosEntityType.LOAN_PRODUCT);
if ( (inClause != null) && (!(inClause.trim().isEmpty())) ) {
sql += " where id in ( " + inClause + " ) ";
}
return this.jdbcTemplate.query(sql, rm, new Object[] {}); return this.jdbcTemplate.query(sql, rm, new Object[] {});
} }
@@ -350,7 +371,15 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
final LoanProductMapper rm = new LoanProductMapper(null, null); final LoanProductMapper rm = new LoanProductMapper(null, null);
final String sql = "select " + rm.loanProductSchema() + " where lp.currency_code='" + currencyCode + "'"; String sql = "select " + rm.loanProductSchema() + " where lp.currency_code='" + currencyCode + "'";
// Check if branch specific products are enabled. If yes, fetch only products mapped to current user's office
String inClause = mifosEntityAccessUtil.
getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(
MifosEntityType.LOAN_PRODUCT);
if ( (inClause != null) && (!(inClause.trim().isEmpty())) ) {
sql += " and id in ( " + inClause + " ) ";
}
return this.jdbcTemplate.query(sql, rm, new Object[] {}); return this.jdbcTemplate.query(sql, rm, new Object[] {});
} }
@@ -362,7 +391,15 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
final LoanProductLookupMapper rm = new LoanProductLookupMapper(); final LoanProductLookupMapper rm = new LoanProductLookupMapper();
final String sql = "Select " + rm.productMixSchema(); String sql = "Select " + rm.productMixSchema();
// Check if branch specific products are enabled. If yes, fetch only products mapped to current user's office
String inClause = mifosEntityAccessUtil.
getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(
MifosEntityType.LOAN_PRODUCT);
if ( (inClause != null) && (!(inClause.trim().isEmpty())) ) {
sql += " and lp.id in ( " + inClause + " ) ";
}
return this.jdbcTemplate.query(sql, rm, new Object[] {}); return this.jdbcTemplate.query(sql, rm, new Object[] {});
} }
@@ -374,9 +411,26 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
final LoanProductLookupMapper rm = new LoanProductLookupMapper(); final LoanProductLookupMapper rm = new LoanProductLookupMapper();
final String sql = "Select " + rm.restrictedProductsSchema() + " where pm.product_id=? UNION Select " String sql = "Select " + rm.restrictedProductsSchema() + " where pm.product_id=? ";
// Check if branch specific products are enabled. If yes, fetch only products mapped to current user's office
String inClause1 = mifosEntityAccessUtil.
getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(
MifosEntityType.LOAN_PRODUCT);
if ( (inClause1 != null) && (!(inClause1.trim().isEmpty())) ) {
sql += " and rp.id in ( " + inClause1 + " ) ";
}
sql += " UNION Select "
+ rm.derivedRestrictedProductsSchema() + " where pm.restricted_product_id=?"; + rm.derivedRestrictedProductsSchema() + " where pm.restricted_product_id=?";
// Check if branch specific products are enabled. If yes, fetch only products mapped to current user's office
String inClause2 = mifosEntityAccessUtil.
getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(
MifosEntityType.LOAN_PRODUCT);
if ( (inClause2 != null) && (!(inClause2.trim().isEmpty())) ) {
sql += " and lp.id in ( " + inClause2 + " ) ";
}
return this.jdbcTemplate.query(sql, rm, new Object[] { productId, productId }); return this.jdbcTemplate.query(sql, rm, new Object[] { productId, productId });
} }
@@ -387,7 +441,17 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
final LoanProductLookupMapper rm = new LoanProductLookupMapper(); final LoanProductLookupMapper rm = new LoanProductLookupMapper();
final String sql = "Select " + rm.schema() + " where lp.id not in (" String sql = "Select " + rm.schema() + " where ";
// Check if branch specific products are enabled. If yes, fetch only products mapped to current user's office
String inClause = mifosEntityAccessUtil.
getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(
MifosEntityType.LOAN_PRODUCT);
if ( (inClause != null) && (!(inClause.trim().isEmpty())) ) {
sql += " lp.id in ( " + inClause + " ) and ";
}
sql += "lp.id not in ("
+ "Select pm.restricted_product_id from m_product_mix pm where pm.product_id=? " + "UNION " + "Select pm.restricted_product_id from m_product_mix pm where pm.product_id=? " + "UNION "
+ "Select pm.product_id from m_product_mix pm where pm.restricted_product_id=?)"; + "Select pm.product_id from m_product_mix pm where pm.restricted_product_id=?)";
@@ -15,6 +15,9 @@ import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException; import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityAccessType;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityType;
import org.mifosplatform.infrastructure.entityaccess.service.MifosEntityAccessUtil;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.charge.domain.Charge; import org.mifosplatform.portfolio.charge.domain.Charge;
import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper; import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper;
@@ -53,6 +56,7 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
private final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository; private final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository;
private final ChargeRepositoryWrapper chargeRepository; private final ChargeRepositoryWrapper chargeRepository;
private final ProductToGLAccountMappingWritePlatformService accountMappingWritePlatformService; private final ProductToGLAccountMappingWritePlatformService accountMappingWritePlatformService;
private final MifosEntityAccessUtil mifosEntityAccessUtil;
@Autowired @Autowired
public LoanProductWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, public LoanProductWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
@@ -60,7 +64,8 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
final AprCalculator aprCalculator, final FundRepository fundRepository, final AprCalculator aprCalculator, final FundRepository fundRepository,
final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository, final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository,
final ChargeRepositoryWrapper chargeRepository, final ChargeRepositoryWrapper chargeRepository,
final ProductToGLAccountMappingWritePlatformService accountMappingWritePlatformService) { final ProductToGLAccountMappingWritePlatformService accountMappingWritePlatformService,
final MifosEntityAccessUtil mifosEntityAccessUtil) {
this.context = context; this.context = context;
this.fromApiJsonDeserializer = fromApiJsonDeserializer; this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.loanProductRepository = loanProductRepository; this.loanProductRepository = loanProductRepository;
@@ -69,6 +74,7 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
this.loanTransactionProcessingStrategyRepository = loanTransactionProcessingStrategyRepository; this.loanTransactionProcessingStrategyRepository = loanTransactionProcessingStrategyRepository;
this.chargeRepository = chargeRepository; this.chargeRepository = chargeRepository;
this.accountMappingWritePlatformService = accountMappingWritePlatformService; this.accountMappingWritePlatformService = accountMappingWritePlatformService;
this.mifosEntityAccessUtil = mifosEntityAccessUtil;
} }
@Transactional @Transactional
@@ -98,6 +104,12 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
// save accounting mappings // save accounting mappings
this.accountMappingWritePlatformService.createLoanProductToGLAccountMapping(loanproduct.getId(), command); this.accountMappingWritePlatformService.createLoanProductToGLAccountMapping(loanproduct.getId(), command);
// check if the office specific products are enabled. If yes, then save this savings product against a specific office
// i.e. this savings product is specific for this office.
mifosEntityAccessUtil.checkConfigurationAndAddProductResrictionsForUserOffice(
MifosEntityAccessType.OFFICE_ACCESS_TO_LOAN_PRODUCTS,
MifosEntityType.LOAN_PRODUCT,
loanproduct.getId());
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -14,6 +14,8 @@ import org.mifosplatform.accounting.common.AccountingEnumerations;
import org.mifosplatform.infrastructure.core.data.EnumOptionData; import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport; import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource; import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityType;
import org.mifosplatform.infrastructure.entityaccess.service.MifosEntityAccessUtil;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.monetary.data.CurrencyData; import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.portfolio.savings.DepositAccountType; import org.mifosplatform.portfolio.savings.DepositAccountType;
@@ -32,11 +34,14 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
private final JdbcTemplate jdbcTemplate; private final JdbcTemplate jdbcTemplate;
private final SavingProductMapper savingsProductRowMapper = new SavingProductMapper(); private final SavingProductMapper savingsProductRowMapper = new SavingProductMapper();
private final SavingProductLookupMapper savingsProductLookupsRowMapper = new SavingProductLookupMapper(); private final SavingProductLookupMapper savingsProductLookupsRowMapper = new SavingProductLookupMapper();
private final MifosEntityAccessUtil mifosEntityAccessUtil;
@Autowired @Autowired
public SavingsProductReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource) { public SavingsProductReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource,
final MifosEntityAccessUtil mifosEntityAccessUtil) {
this.context = context; this.context = context;
this.jdbcTemplate = new JdbcTemplate(dataSource); this.jdbcTemplate = new JdbcTemplate(dataSource);
this.mifosEntityAccessUtil = mifosEntityAccessUtil;
} }
@Override @Override
@@ -44,7 +49,15 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
this.context.authenticatedUser(); this.context.authenticatedUser();
final String sql = "select " + this.savingsProductRowMapper.schema() + "where sp.deposit_type_enum = ?"; String sql = "select " + this.savingsProductRowMapper.schema() + "where sp.deposit_type_enum = ?";
// Check if branch specific products are enabled. If yes, fetch only products mapped to current user's office
String inClause = mifosEntityAccessUtil.
getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(
MifosEntityType.SAVINGS_PRODUCT);
if ( (inClause != null) && (!(inClause.trim().isEmpty())) ) {
sql += " and sp.id in ( " + inClause + " ) ";
}
return this.jdbcTemplate.query(sql, this.savingsProductRowMapper, new Object[] { DepositAccountType.SAVINGS_DEPOSIT.getValue() }); return this.jdbcTemplate.query(sql, this.savingsProductRowMapper, new Object[] { DepositAccountType.SAVINGS_DEPOSIT.getValue() });
} }
@@ -52,7 +65,16 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
@Override @Override
public Collection<SavingsProductData> retrieveAllForLookup() { public Collection<SavingsProductData> retrieveAllForLookup() {
final String sql = "select " + this.savingsProductLookupsRowMapper.schema() + " where sp.deposit_type_enum = ?"; String sql = "select " + this.savingsProductLookupsRowMapper.schema() + " where sp.deposit_type_enum = ? ";
// Check if branch specific products are enabled. If yes, fetch only products mapped to current user's office
String inClause = mifosEntityAccessUtil.
getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(
MifosEntityType.SAVINGS_PRODUCT);
if ( (inClause != null) && (!(inClause.trim().isEmpty())) ) {
sql += " and id in ( " + inClause + " ) ";
}
return this.jdbcTemplate.query(sql, this.savingsProductLookupsRowMapper, return this.jdbcTemplate.query(sql, this.savingsProductLookupsRowMapper,
new Object[] { DepositAccountType.SAVINGS_DEPOSIT.getValue() }); new Object[] { DepositAccountType.SAVINGS_DEPOSIT.getValue() });
@@ -188,8 +210,24 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
@Override @Override
public Collection<SavingsProductData> retrieveAllForLookupByType(Boolean isOverdraftType) { public Collection<SavingsProductData> retrieveAllForLookupByType(Boolean isOverdraftType) {
String sql = "select " + this.savingsProductLookupsRowMapper.schema(); String sql = "select " + this.savingsProductLookupsRowMapper.schema();
boolean inClauseAdded = false;
// Check if branch specific products are enabled. If yes, fetch only products mapped to current user's office
String inClause = mifosEntityAccessUtil.
getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(
MifosEntityType.SAVINGS_PRODUCT);
if ( (inClause != null) && (!(inClause.trim().isEmpty())) ) {
sql += " where id in ( " + inClause + " ) ";
inClauseAdded = true;
}
if (isOverdraftType != null) { if (isOverdraftType != null) {
sql += " where sp.allow_overdraft=?"; if (inClauseAdded) {
sql += " and sp.allow_overdraft=?";
} else {
sql += " where sp.allow_overdraft=?";
}
return this.jdbcTemplate.query(sql, this.savingsProductLookupsRowMapper, isOverdraftType); return this.jdbcTemplate.query(sql, this.savingsProductLookupsRowMapper, isOverdraftType);
} }
@@ -202,7 +240,15 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
this.context.authenticatedUser(); this.context.authenticatedUser();
final String sql = "select " + this.savingsProductRowMapper.schema() + " where sp.currency_code='" + currencyCode + "'"; String sql = "select " + this.savingsProductRowMapper.schema() + " where sp.currency_code='" + currencyCode + "'";
// Check if branch specific products are enabled. If yes, fetch only products mapped to current user's office
String inClause = mifosEntityAccessUtil.
getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(
MifosEntityType.SAVINGS_PRODUCT);
if ( (inClause != null) && (!(inClause.trim().isEmpty())) ) {
sql += " and id in ( " + inClause + " ) ";
}
return this.jdbcTemplate.query(sql, this.savingsProductRowMapper); return this.jdbcTemplate.query(sql, this.savingsProductRowMapper);
} }
@@ -16,6 +16,9 @@ import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException; import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityAccessType;
import org.mifosplatform.infrastructure.entityaccess.domain.MifosEntityType;
import org.mifosplatform.infrastructure.entityaccess.service.MifosEntityAccessUtil;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.charge.domain.Charge; import org.mifosplatform.portfolio.charge.domain.Charge;
import org.mifosplatform.portfolio.savings.DepositAccountType; import org.mifosplatform.portfolio.savings.DepositAccountType;
@@ -40,18 +43,22 @@ public class SavingsProductWritePlatformServiceJpaRepositoryImpl implements Savi
private final SavingsProductDataValidator fromApiJsonDataValidator; private final SavingsProductDataValidator fromApiJsonDataValidator;
private final SavingsProductAssembler savingsProductAssembler; private final SavingsProductAssembler savingsProductAssembler;
private final ProductToGLAccountMappingWritePlatformService accountMappingWritePlatformService; private final ProductToGLAccountMappingWritePlatformService accountMappingWritePlatformService;
private final MifosEntityAccessUtil mifosEntityAccessUtil;
@Autowired @Autowired
public SavingsProductWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, public SavingsProductWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
final SavingsProductRepository savingProductRepository, final SavingsProductDataValidator fromApiJsonDataValidator, final SavingsProductRepository savingProductRepository, final SavingsProductDataValidator fromApiJsonDataValidator,
final SavingsProductAssembler savingsProductAssembler, final SavingsProductAssembler savingsProductAssembler,
final ProductToGLAccountMappingWritePlatformService accountMappingWritePlatformService) { final ProductToGLAccountMappingWritePlatformService accountMappingWritePlatformService,
final MifosEntityAccessUtil mifosEntityAccessUtil
) {
this.context = context; this.context = context;
this.savingProductRepository = savingProductRepository; this.savingProductRepository = savingProductRepository;
this.fromApiJsonDataValidator = fromApiJsonDataValidator; this.fromApiJsonDataValidator = fromApiJsonDataValidator;
this.savingsProductAssembler = savingsProductAssembler; this.savingsProductAssembler = savingsProductAssembler;
this.logger = LoggerFactory.getLogger(SavingsProductWritePlatformServiceJpaRepositoryImpl.class); this.logger = LoggerFactory.getLogger(SavingsProductWritePlatformServiceJpaRepositoryImpl.class);
this.accountMappingWritePlatformService = accountMappingWritePlatformService; this.accountMappingWritePlatformService = accountMappingWritePlatformService;
this.mifosEntityAccessUtil = mifosEntityAccessUtil;
} }
/* /*
@@ -97,6 +104,13 @@ public class SavingsProductWritePlatformServiceJpaRepositoryImpl implements Savi
this.accountMappingWritePlatformService.createSavingProductToGLAccountMapping(product.getId(), command, this.accountMappingWritePlatformService.createSavingProductToGLAccountMapping(product.getId(), command,
DepositAccountType.SAVINGS_DEPOSIT); DepositAccountType.SAVINGS_DEPOSIT);
// check if the office specific products are enabled. If yes, then save this savings product against a specific office
// i.e. this savings product is specific for this office.
mifosEntityAccessUtil.checkConfigurationAndAddProductResrictionsForUserOffice(
MifosEntityAccessType.OFFICE_ACCESS_TO_SAVINGS_PRODUCTS,
MifosEntityType.SAVINGS_PRODUCT,
product.getId());
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withEntityId(product.getId()) // .withEntityId(product.getId()) //
.build(); .build();
@@ -0,0 +1,45 @@
-- Code required to store various types of Entity to Entity Access types that Mifos Supports
insert into m_code (code_name, is_system_defined)
values ('Entity to Entity Access Types', 1);
-- Three Code Values required to support:
-- a) Loan Products restricted to specific Offices
-- b) Savings Products restricted to specific Offices
-- c) Fees/Charges restricted to specific Offices
insert into m_code_value (code_id, code_value, order_position)
values (
(select id from m_code where code_name = 'Entity to Entity Access Types'),
'Office Access to Loan Products', 0);
insert into m_code_value (code_id, code_value, order_position)
values (
(select id from m_code where code_name = 'Entity to Entity Access Types'),
'Office Access to Savings Products', 0);
insert into m_code_value (code_id, code_value, order_position)
values (
(select id from m_code where code_name = 'Entity to Entity Access Types'),
'Office Access to Fees/Charges', 0);
-- Table where the actual restrictions will be stored
CREATE TABLE `m_entity_to_entity_access` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`entity_type` VARCHAR(50) NOT NULL,
`entity_id` BIGINT(20) NOT NULL,
`access_type_code_value_id` INT(11) NOT NULL,
`second_entity_type` VARCHAR(50) NOT NULL,
`second_entity_id` BIGINT(20) NOT NULL,
PRIMARY KEY (`id`),
INDEX `IDX_OFFICE` (`entity_type`,`entity_id`),
UNIQUE KEY `id_uniq_m_entity_to_entity_access` (`entity_type`,`entity_id`,`access_type_code_value_id`,`second_entity_type`,`second_entity_id`),
CONSTRAINT `FK_access_type_code_m_code_value` FOREIGN KEY (`access_type_code_value_id`) REFERENCES `m_code_value` (`id`)
);
-- Global Configurations for Entity access restrictions
insert into c_configuration (name, value, enabled, description)
values ('office-specific-products-enabled', 0, 0,
'Whether products and fees should be office specific or not? This property should NOT be changed once Mifos is Live.');
insert into c_configuration (name, value, enabled, description)
values ('restrict-products-to-user-office', 0, 0,
'This should be enabled only if, products & fees are office specific (i.e. office-specific-products-enabled is enabled). This property specifies if the products should be auto-restricted to office of the user who created the proudct? Note: This property should NOT be changed once Mifos is Live.');