Fixed issue with entity datatable check

This commit is contained in:
Satish
2016-12-19 09:45:57 +05:30
parent 94baf15b97
commit 8b20f0818c
10 changed files with 301 additions and 260 deletions
@@ -33,7 +33,7 @@ public enum EntityTables {
LOAN("m_loan", LOAN("m_loan",
new Integer[]{StatusEnum.CREATE.getCode(), new Integer[]{StatusEnum.CREATE.getCode(),
StatusEnum.APPROVE.getCode(), StatusEnum.APPROVE.getCode(),
StatusEnum.ACTIVATE.getCode(), StatusEnum.DISBURSE.getCode(),
StatusEnum.WITHDRAWN.getCode(), StatusEnum.WITHDRAWN.getCode(),
StatusEnum.REJECTED.getCode(), StatusEnum.REJECTED.getCode(),
StatusEnum.WRITE_OFF.getCode()}, StatusEnum.WRITE_OFF.getCode()},
@@ -26,7 +26,7 @@ import org.apache.fineract.infrastructure.core.data.EnumOptionData;
public enum StatusEnum { public enum StatusEnum {
CREATE("create", 100), APPROVE("approve", 200), ACTIVATE("activate", 300), WITHDRAWN("withdraw", 400), REJECTED("reject", 500), CLOSE( CREATE("create", 100), APPROVE("approve", 200), ACTIVATE("activate", 300), WITHDRAWN("withdraw", 400), REJECTED("reject", 500), CLOSE(
"close", 600), WRITE_OFF("write off", 601), RESCHEDULE("reschedule", 602), OVERPAY("overpay", 700); "close", 600), WRITE_OFF("write off", 601), RESCHEDULE("reschedule", 602), OVERPAY("overpay", 700), DISBURSE("disburse", 800);
private String name; private String name;
@@ -85,6 +85,9 @@ public enum StatusEnum {
case 700: case 700:
ret = StatusEnum.OVERPAY; ret = StatusEnum.OVERPAY;
break; break;
case 800:
ret = StatusEnum.DISBURSE;
break;
default: default:
break; break;
} }
@@ -23,10 +23,16 @@ import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainR
/** /**
* A {@link AbstractPlatformDomainRuleException} thrown when datatable resources are not found. * A {@link AbstractPlatformDomainRuleException} thrown when datatable resources are not found.
*/ */
public class DatatabaleEntryRequiredException extends AbstractPlatformDomainRuleException{ public class DatatableEntryRequiredException extends AbstractPlatformDomainRuleException {
public DatatabaleEntryRequiredException(String datatableName) { public DatatableEntryRequiredException(String datatableName) {
super("error.msg.entry.required.in.datatable." + datatableName, "The datatable " + datatableName super("error.msg.entry.required.in.datatable." + datatableName, "The datatable " + datatableName
+ " needs to be filled in before the current action can be proceeded", datatableName); + " needs to be filled in before the current action can be proceeded", datatableName);
}
public DatatableEntryRequiredException(String datatableName, Long appTableId) {
super("error.msg.entry.cannot.be.deleted.datatable." + datatableName + ".attached.to.entity.datatable.check",
"The entry cannot be deleted, due to datatable " + datatableName + " is attached to an Entity-Datatable check",
datatableName, appTableId);
} }
} }
@@ -55,261 +55,242 @@ import com.google.gson.JsonObject;
@Service @Service
public class EntityDatatableChecksWritePlatformServiceImpl implements EntityDatatableChecksWritePlatformService { public class EntityDatatableChecksWritePlatformServiceImpl implements EntityDatatableChecksWritePlatformService {
private final static Logger logger = LoggerFactory.getLogger(EntityDatatableChecksWritePlatformServiceImpl.class); private final static Logger logger = LoggerFactory.getLogger(EntityDatatableChecksWritePlatformServiceImpl.class);
private final PlatformSecurityContext context; private final PlatformSecurityContext context;
private final EntityDatatableChecksDataValidator fromApiJsonDeserializer; private final EntityDatatableChecksDataValidator fromApiJsonDeserializer;
private final EntityDatatableChecksRepository entityDatatableChecksRepository; private final EntityDatatableChecksRepository entityDatatableChecksRepository;
private final ReadWriteNonCoreDataService readWriteNonCoreDataService; private final ReadWriteNonCoreDataService readWriteNonCoreDataService;
private final LoanProductReadPlatformService loanProductReadPlatformService; private final LoanProductReadPlatformService loanProductReadPlatformService;
private final SavingsProductReadPlatformService savingsProductReadPlatformService; private final SavingsProductReadPlatformService savingsProductReadPlatformService;
private final FromJsonHelper fromApiJsonHelper; private final FromJsonHelper fromApiJsonHelper;
private final ConfigurationDomainService configurationDomainService; private final ConfigurationDomainService configurationDomainService;
@Autowired @Autowired
public EntityDatatableChecksWritePlatformServiceImpl(final PlatformSecurityContext context, public EntityDatatableChecksWritePlatformServiceImpl(final PlatformSecurityContext context,
final EntityDatatableChecksDataValidator fromApiJsonDeserializer, final EntityDatatableChecksDataValidator fromApiJsonDeserializer,
final EntityDatatableChecksRepository entityDatatableChecksRepository, final EntityDatatableChecksRepository entityDatatableChecksRepository,
final ReadWriteNonCoreDataService readWriteNonCoreDataService, final ReadWriteNonCoreDataService readWriteNonCoreDataService,
final LoanProductReadPlatformService loanProductReadPlatformService, final LoanProductReadPlatformService loanProductReadPlatformService,
final SavingsProductReadPlatformService savingsProductReadPlatformService, final SavingsProductReadPlatformService savingsProductReadPlatformService, final FromJsonHelper fromApiJsonHelper,
final FromJsonHelper fromApiJsonHelper, final ConfigurationDomainService configurationDomainService) {
final ConfigurationDomainService configurationDomainService) { this.context = context;
this.context = context; this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.fromApiJsonDeserializer = fromApiJsonDeserializer; this.entityDatatableChecksRepository = entityDatatableChecksRepository;
this.entityDatatableChecksRepository = entityDatatableChecksRepository; this.readWriteNonCoreDataService = readWriteNonCoreDataService;
this.readWriteNonCoreDataService = readWriteNonCoreDataService; this.loanProductReadPlatformService = loanProductReadPlatformService;
this.loanProductReadPlatformService = loanProductReadPlatformService; this.savingsProductReadPlatformService = savingsProductReadPlatformService;
this.savingsProductReadPlatformService = savingsProductReadPlatformService; this.fromApiJsonHelper = fromApiJsonHelper;
this.fromApiJsonHelper = fromApiJsonHelper; this.configurationDomainService = configurationDomainService;
this.configurationDomainService = configurationDomainService; }
}
@Transactional @Transactional
@Override @Override
public CommandProcessingResult createCheck(final JsonCommand command) { public CommandProcessingResult createCheck(final JsonCommand command) {
try { try {
this.context.authenticatedUser(); this.context.authenticatedUser();
this.fromApiJsonDeserializer.validateForCreate(command.json()); this.fromApiJsonDeserializer.validateForCreate(command.json());
// check if the datatable is linked to the entity // check if the datatable is linked to the entity
String datatableName = command.stringValueOfParameterNamed("datatableName"); String datatableName = command.stringValueOfParameterNamed("datatableName");
DatatableData datatableData = this.readWriteNonCoreDataService.retrieveDatatable(datatableName); DatatableData datatableData = this.readWriteNonCoreDataService.retrieveDatatable(datatableName);
if (datatableData == null) { if (datatableData == null) { throw new DatatableNotFoundException(datatableName); }
throw new DatatableNotFoundException(datatableName);
}
final String entity = command.stringValueOfParameterNamed("entity"); final String entity = command.stringValueOfParameterNamed("entity");
final String foreignKeyColumnName = EntityTables.getForeignKeyColumnNameOnDatatable(entity); final String foreignKeyColumnName = EntityTables.getForeignKeyColumnNameOnDatatable(entity);
final boolean columnExist = datatableData.hasColumn(foreignKeyColumnName); final boolean columnExist = datatableData.hasColumn(foreignKeyColumnName);
logger.info(datatableData.getRegisteredTableName() + "has column " + foreignKeyColumnName + " ? " logger.info(datatableData.getRegisteredTableName() + "has column " + foreignKeyColumnName + " ? " + columnExist);
+ columnExist);
if (!columnExist) { if (!columnExist) { throw new EntityDatatableCheckNotSupportedException(datatableData.getRegisteredTableName(), entity); }
throw new EntityDatatableCheckNotSupportedException(datatableData.getRegisteredTableName(), entity);
}
final Long productId = command.longValueOfParameterNamed("productId"); final Long productId = command.longValueOfParameterNamed("productId");
final Long status = command.longValueOfParameterNamed("status"); final Long status = command.longValueOfParameterNamed("status");
List<EntityDatatableChecks> entityDatatableCheck = null;
if (productId == null) {
entityDatatableCheck = this.entityDatatableChecksRepository.findByEntityStatusAndDatatableIdAndNoProduct(entity, status,
datatableName);
if (!entityDatatableCheck.isEmpty()) { throw new EntityDatatableCheckAlreadyExistsException(entity, status, datatableName); }
} else {
if (entity.equals("m_loan")) {
// if invalid loan product id, throws exception
this.loanProductReadPlatformService.retrieveLoanProduct(productId);
} else if (entity.equals("m_savings_account")) {
// if invalid savings product id, throws exception
this.savingsProductReadPlatformService.retrieveOne(productId);
} else {
throw new EntityDatatableCheckNotSupportedException(entity, productId);
}
entityDatatableCheck = this.entityDatatableChecksRepository.findByEntityStatusAndDatatableIdAndProductId(entity, status,
datatableName, productId);
if (!entityDatatableCheck.isEmpty()) { throw new EntityDatatableCheckAlreadyExistsException(entity, status, datatableName,
productId); }
}
List<EntityDatatableChecks> entityDatatableCheck = null; final EntityDatatableChecks check = EntityDatatableChecks.fromJson(command);
if (productId == null) {
entityDatatableCheck = this.entityDatatableChecksRepository
.findByEntityStatusAndDatatableIdAndNoProduct(entity, status, datatableName);
if (!entityDatatableCheck.isEmpty()) {
throw new EntityDatatableCheckAlreadyExistsException(entity, status, datatableName);
}
} else {
if (entity.equals("m_loan")) {
// if invalid loan product id, throws exception
this.loanProductReadPlatformService.retrieveLoanProduct(productId);
} else if (entity.equals("m_savings_account")) {
// if invalid savings product id, throws exception
this.savingsProductReadPlatformService.retrieveOne(productId);
} else {
throw new EntityDatatableCheckNotSupportedException(entity, productId);
}
entityDatatableCheck = this.entityDatatableChecksRepository
.findByEntityStatusAndDatatableIdAndProductId(entity, status, datatableName, productId);
if (!entityDatatableCheck.isEmpty()) {
throw new EntityDatatableCheckAlreadyExistsException(entity, status, datatableName, productId);
}
}
final EntityDatatableChecks check = EntityDatatableChecks.fromJson(command); this.entityDatatableChecksRepository.saveAndFlush(check);
this.entityDatatableChecksRepository.saveAndFlush(check); return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(check.getId()) //
.build();
} catch (final DataAccessException e) {
handleReportDataIntegrityIssues(command, e.getMostSpecificCause(), e);
return CommandProcessingResult.empty();
} catch (final PersistenceException dve) {
Throwable throwable = ExceptionUtils.getRootCause(dve.getCause());
handleReportDataIntegrityIssues(command, throwable, dve);
return CommandProcessingResult.empty();
}
}
return new CommandProcessingResultBuilder() // @Override
.withCommandId(command.commandId()) // public void runTheCheck(final Long entityId, final String entityName, final Long statusCode, String foreignKeyColumn) {
.withEntityId(check.getId()) // final List<EntityDatatableChecks> tableRequiredBeforeClientActivation = entityDatatableChecksRepository.findByEntityAndStatus(
.build(); entityName, statusCode);
} catch (final DataAccessException e) {
handleReportDataIntegrityIssues(command, e.getMostSpecificCause(), e);
return CommandProcessingResult.empty();
}catch (final PersistenceException dve) {
Throwable throwable = ExceptionUtils.getRootCause(dve.getCause()) ;
handleReportDataIntegrityIssues(command, throwable, dve);
return CommandProcessingResult.empty();
}
}
public void runTheCheck(final Long entityId, final String entityName, final Long statusCode, if (tableRequiredBeforeClientActivation != null) {
String foreignKeyColumn) { List<String> reqDatatables = new ArrayList<>();
final List<EntityDatatableChecks> tableRequiredBeforeClientActivation = entityDatatableChecksRepository for (EntityDatatableChecks t : tableRequiredBeforeClientActivation) {
.findByEntityAndStatus(entityName, statusCode);
if (tableRequiredBeforeClientActivation != null) { final String datatableName = t.getDatatableName();
List<String> reqDatatables = new ArrayList<>(); final Long countEntries = readWriteNonCoreDataService.countDatatableEntries(datatableName, entityId, foreignKeyColumn);
for (EntityDatatableChecks t : tableRequiredBeforeClientActivation) {
final String datatableName = t.getDatatableName(); logger.info("The are " + countEntries + " entries in the table " + datatableName);
final Long countEntries = readWriteNonCoreDataService.countDatatableEntries(datatableName, entityId, if (countEntries.intValue() == 0) {
foreignKeyColumn); reqDatatables.add(datatableName);
}
}
if (reqDatatables.size() > 0) { throw new DatatableEntryRequiredException(reqDatatables.toString()); }
}
logger.info("The are " + countEntries + " entries in the table " + datatableName); }
if (countEntries.intValue() == 0) {
reqDatatables.add(datatableName);
}
}
if(reqDatatables.size() > 0){
throw new DatatabaleEntryRequiredException(reqDatatables.toString());
}
}
} @Override
public void runTheCheckForProduct(final Long entityId, final String entityName, final Long statusCode, String foreignKeyColumn,
long productId) {
List<EntityDatatableChecks> tableRequiredBeforAction = entityDatatableChecksRepository.findByEntityStatusAndProduct(entityName,
statusCode, productId);
public void runTheCheckForProduct(final Long entityId, final String entityName, final Long statusCode, if (tableRequiredBeforAction == null || tableRequiredBeforAction.size() < 1) {
String foreignKeyColumn, long productId) { tableRequiredBeforAction = entityDatatableChecksRepository.findByEntityStatusAndNoProduct(entityName, statusCode);
List<EntityDatatableChecks> tableRequiredBeforAction = entityDatatableChecksRepository }
.findByEntityStatusAndProduct(entityName, statusCode, productId); if (tableRequiredBeforAction != null) {
List<String> reqDatatables = new ArrayList<>();
for (EntityDatatableChecks t : tableRequiredBeforAction) {
if (tableRequiredBeforAction == null || tableRequiredBeforAction.size() < 1) { final String datatableName = t.getDatatableName();
tableRequiredBeforAction = entityDatatableChecksRepository.findByEntityStatusAndNoProduct(entityName, final Long countEntries = readWriteNonCoreDataService.countDatatableEntries(datatableName, entityId, foreignKeyColumn);
statusCode);
}
if (tableRequiredBeforAction != null) {
List<String> reqDatatables = new ArrayList<>();
for (EntityDatatableChecks t : tableRequiredBeforAction) {
final String datatableName = t.getDatatableName(); logger.info("The are " + countEntries + " entries in the table " + datatableName);
final Long countEntries = readWriteNonCoreDataService.countDatatableEntries(datatableName, entityId, if (countEntries.intValue() == 0) {
foreignKeyColumn); reqDatatables.add(datatableName);
}
}
if (reqDatatables.size() > 0) { throw new DatatableEntryRequiredException(reqDatatables.toString()); }
}
logger.info("The are " + countEntries + " entries in the table " + datatableName); }
if (countEntries.intValue() == 0) {
reqDatatables.add(datatableName);
}
}
if(reqDatatables.size() > 0){
throw new DatatabaleEntryRequiredException(reqDatatables.toString());
}
}
} @Transactional
@Override
public boolean saveDatatables(final Long status, final String entity, final Long entityId, final Long productId,
final JsonArray datatableDatas) {
final AppUser user = this.context.authenticatedUser();
boolean isMakerCheckerEnabled = false;
if (datatableDatas != null && datatableDatas.size() > 0) {
for (JsonElement element : datatableDatas) {
final String datatableName = this.fromApiJsonHelper.extractStringNamed("registeredTableName", element);
final JsonObject datatableData = this.fromApiJsonHelper.extractJsonObjectNamed("data", element);
@Transactional if (datatableName == null || datatableData == null) {
@Override final ApiParameterError error = ApiParameterError.generalError(
public boolean saveDatatables(final Long status, final String entity, final Long entityId, "registeredTableName.and.data.parameters.must.be.present.in.each.list.items.in.datatables",
final Long productId, final JsonArray datatableDatas) { "registeredTableName and data parameters must be present in each list items in datatables");
final AppUser user = this.context.authenticatedUser(); List<ApiParameterError> errors = new ArrayList<>();
boolean isMakerCheckerEnabled = false; errors.add(error);
if(datatableDatas != null && datatableDatas.size() > 0){ throw new PlatformApiDataValidationException(errors);
for(JsonElement element : datatableDatas){ }
final String datatableName = this.fromApiJsonHelper.extractStringNamed("registeredTableName",element); final String taskPermissionName = "CREATE_" + datatableName;
final JsonObject datatableData = this.fromApiJsonHelper.extractJsonObjectNamed("data", element); user.validateHasPermissionTo(taskPermissionName);
if (this.configurationDomainService.isMakerCheckerEnabledForTask(taskPermissionName)) {
isMakerCheckerEnabled = true;
}
try {
this.readWriteNonCoreDataService.createNewDatatableEntry(datatableName, entityId, datatableData.toString());
} catch (PlatformApiDataValidationException e) {
List<ApiParameterError> errors = e.getErrors();
for (ApiParameterError error : e.getErrors()) {
error.setParameterName("datatables." + datatableName + "." + error.getParameterName());
}
throw e;
}
}
}
return isMakerCheckerEnabled;
}
if(datatableName == null || datatableData == null){ private List<String> getDatatableNames(Long status, String entity, Long productId) {
final ApiParameterError error = ApiParameterError.generalError("registeredTableName.and.data.parameters.must.be.present.in.each.list.items.in.datatables", List<String> ret = new ArrayList<>();
"registeredTableName and data parameters must be present in each list items in datatables"); List<EntityDatatableChecks> tableRequiredBeforeAction = null;
List<ApiParameterError> errors = new ArrayList<>(); if (productId != null) {
errors.add(error); tableRequiredBeforeAction = this.entityDatatableChecksRepository.findByEntityStatusAndProduct(entity, status, productId);
throw new PlatformApiDataValidationException(errors); }
}
final String taskPermissionName = "CREATE_" + datatableName;
user.validateHasPermissionTo(taskPermissionName);
if(this.configurationDomainService.isMakerCheckerEnabledForTask(taskPermissionName)){
isMakerCheckerEnabled = true;
}
try{
this.readWriteNonCoreDataService.createNewDatatableEntry(datatableName, entityId, datatableData.toString());
} catch(PlatformApiDataValidationException e){
List<ApiParameterError> errors = e.getErrors();
for(ApiParameterError error : e.getErrors()){
error.setParameterName("datatables."+datatableName+"."+error.getParameterName());
}
throw e;
}
}
}
return isMakerCheckerEnabled;
}
private List<String> getDatatableNames(Long status, String entity, Long productId) { if (tableRequiredBeforeAction == null || tableRequiredBeforeAction.size() < 1) {
List<String> ret = new ArrayList<>(); tableRequiredBeforeAction = this.entityDatatableChecksRepository.findByEntityStatusAndNoProduct(entity, status);
List<EntityDatatableChecks> tableRequiredBeforeAction = null; }
if(productId != null){ if (tableRequiredBeforeAction != null && tableRequiredBeforeAction.size() > 0) {
tableRequiredBeforeAction = this.entityDatatableChecksRepository for (EntityDatatableChecks t : tableRequiredBeforeAction) {
.findByEntityStatusAndProduct(entity, status, productId); ret.add(t.getDatatableName());
} }
}
return ret;
}
if (tableRequiredBeforeAction == null || tableRequiredBeforeAction.size() < 1) { @Transactional
tableRequiredBeforeAction = this.entityDatatableChecksRepository.findByEntityStatusAndNoProduct(entity, @Override
status); public CommandProcessingResult deleteCheck(final Long entityDatatableCheckId) {
}
if (tableRequiredBeforeAction != null && tableRequiredBeforeAction.size() > 0) {
for (EntityDatatableChecks t : tableRequiredBeforeAction) {
ret.add(t.getDatatableName());
}
}
return ret;
}
@Transactional final EntityDatatableChecks check = this.entityDatatableChecksRepository.findOne(entityDatatableCheckId);
@Override if (check == null) { throw new EntityDatatableChecksNotFoundException(entityDatatableCheckId); }
public CommandProcessingResult deleteCheck(final Long entityDatatableCheckId) {
final EntityDatatableChecks check = this.entityDatatableChecksRepository.findOne(entityDatatableCheckId); this.entityDatatableChecksRepository.delete(check);
if (check == null) {
throw new EntityDatatableChecksNotFoundException(entityDatatableCheckId);
}
this.entityDatatableChecksRepository.delete(check); return new CommandProcessingResultBuilder() //
.withEntityId(entityDatatableCheckId) //
.build();
}
return new CommandProcessingResultBuilder() // /*
.withEntityId(entityDatatableCheckId) // * Guaranteed to throw an exception no matter what the data integrity issue
.build(); * is.
} */
private void handleReportDataIntegrityIssues(final JsonCommand command, final Throwable realCause, final Exception dae) {
/* if (realCause.getMessage().contains("FOREIGN KEY (`x_registered_table_name`)")) {
* Guaranteed to throw an exception no matter what the data integrity issue final String datatableName = command.stringValueOfParameterNamed("datatableName");
* is. throw new PlatformDataIntegrityException("error.msg.entityDatatableCheck.foreign.key.constraint", "datatable with name '"
*/ + datatableName + "' do not exist", "datatableName", datatableName);
private void handleReportDataIntegrityIssues(final JsonCommand command, final Throwable realCause, final Exception dae) { }
if (realCause.getMessage().contains("FOREIGN KEY (`x_registered_table_name`)")) { if (realCause.getMessage().contains("unique_entity_check")) {
final String datatableName = command.stringValueOfParameterNamed("datatableName"); final String datatableName = command.stringValueOfParameterNamed("datatableName");
throw new PlatformDataIntegrityException("error.msg.entityDatatableCheck.foreign.key.constraint", final long status = command.longValueOfParameterNamed("status");
"datatable with name '" + datatableName + "' do not exist", "datatableName", datatableName); final String entity = command.stringValueOfParameterNamed("entity");
} final long productId = command.longValueOfParameterNamed("productId");
throw new EntityDatatableCheckAlreadyExistsException(entity, status, datatableName, productId);
}
if (realCause.getMessage().contains("unique_entity_check")) { logger.error(dae.getMessage(), dae);
final String datatableName = command.stringValueOfParameterNamed("datatableName"); throw new PlatformDataIntegrityException("error.msg.report.unknown.data.integrity.issue",
final long status = command.longValueOfParameterNamed("status"); "Unknown data integrity issue with resource: " + realCause.getMessage());
final String entity = command.stringValueOfParameterNamed("entity"); }
final long productId = command.longValueOfParameterNamed("productId");
throw new EntityDatatableCheckAlreadyExistsException(entity, status, datatableName, productId);
}
logger.error(dae.getMessage(), dae);
throw new PlatformDataIntegrityException("error.msg.report.unknown.data.integrity.issue",
"Unknown data integrity issue with resource: " + realCause.getMessage());
}
} }
@@ -45,6 +45,7 @@ import org.apache.fineract.infrastructure.core.serialization.JsonParserHelper;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource; import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.infrastructure.dataqueries.api.DataTableApiConstant; import org.apache.fineract.infrastructure.dataqueries.api.DataTableApiConstant;
import org.apache.fineract.infrastructure.dataqueries.data.*; import org.apache.fineract.infrastructure.dataqueries.data.*;
import org.apache.fineract.infrastructure.dataqueries.exception.DatatableEntryRequiredException;
import org.apache.fineract.infrastructure.dataqueries.exception.DatatableNotFoundException; import org.apache.fineract.infrastructure.dataqueries.exception.DatatableNotFoundException;
import org.apache.fineract.infrastructure.dataqueries.exception.DatatableSystemErrorException; import org.apache.fineract.infrastructure.dataqueries.exception.DatatableSystemErrorException;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
@@ -1121,9 +1122,9 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
@Override @Override
public CommandProcessingResult deleteDatatableEntries(final String dataTableName, final Long appTableId) { public CommandProcessingResult deleteDatatableEntries(final String dataTableName, final Long appTableId) {
if (isDatatableAttachedToEntityDatatableCheck(dataTableName)) { throw new DatatableEntryRequiredException(dataTableName, appTableId); }
final String appTable = queryForApplicationTableName(dataTableName); final String appTable = queryForApplicationTableName(dataTableName);
final CommandProcessingResult commandProcessingResult = checkMainResourceExistsWithinScope(appTable, appTableId); final CommandProcessingResult commandProcessingResult = checkMainResourceExistsWithinScope(appTable, appTableId);
final String deleteOneToOneEntrySql = getDeleteEntriesSql(dataTableName, getFKField(appTable), appTableId); final String deleteOneToOneEntrySql = getDeleteEntriesSql(dataTableName, getFKField(appTable), appTableId);
final int rowsDeleted = this.jdbcTemplate.update(deleteOneToOneEntrySql); final int rowsDeleted = this.jdbcTemplate.update(deleteOneToOneEntrySql);
@@ -1135,7 +1136,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
@Transactional @Transactional
@Override @Override
public CommandProcessingResult deleteDatatableEntry(final String dataTableName, final Long appTableId, final Long datatableId) { public CommandProcessingResult deleteDatatableEntry(final String dataTableName, final Long appTableId, final Long datatableId) {
if (isDatatableAttachedToEntityDatatableCheck(dataTableName)) { throw new DatatableEntryRequiredException(dataTableName, appTableId); }
final String appTable = queryForApplicationTableName(dataTableName); final String appTable = queryForApplicationTableName(dataTableName);
final CommandProcessingResult commandProcessingResult = checkMainResourceExistsWithinScope(appTable, appTableId); final CommandProcessingResult commandProcessingResult = checkMainResourceExistsWithinScope(appTable, appTableId);
@@ -1730,4 +1731,13 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
return count; return count;
} }
public boolean isDatatableAttachedToEntityDatatableCheck(final String datatableName) {
StringBuilder builder = new StringBuilder();
builder.append(" SELECT COUNT(edc.`x_registered_table_name`) FROM `x_registered_table` xrt ");
builder.append(" JOIN m_entity_datatable_check edc ON edc.`x_registered_table_name` = xrt.`registered_table_name`");
builder.append(" WHERE edc.`x_registered_table_name` = '" + datatableName + "'");
final Long count = this.jdbcTemplate.queryForObject(builder.toString(), Long.class);
return (count > 0) ? true : false;
}
} }
@@ -74,6 +74,10 @@ public class ClientRepositoryWrapper {
public void delete(final Client client) { public void delete(final Client client) {
this.repository.delete(client); this.repository.delete(client);
} }
public void flush() {
this.repository.flush();
}
public Client getActiveClientInUserScope(Long clientId) { public Client getActiveClientInUserScope(Long clientId) {
final Client client = this.findOneWithNotFoundDetection(clientId); final Client client = this.findOneWithNotFoundDetection(clientId);
@@ -18,7 +18,11 @@
*/ */
package org.apache.fineract.portfolio.client.service; package org.apache.fineract.portfolio.client.service;
import java.util.*; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.persistence.PersistenceException; import javax.persistence.PersistenceException;
@@ -50,8 +54,18 @@ import org.apache.fineract.organisation.staff.domain.StaffRepositoryWrapper;
import org.apache.fineract.portfolio.address.service.AddressWritePlatformService; import org.apache.fineract.portfolio.address.service.AddressWritePlatformService;
import org.apache.fineract.portfolio.client.api.ClientApiConstants; import org.apache.fineract.portfolio.client.api.ClientApiConstants;
import org.apache.fineract.portfolio.client.data.ClientDataValidator; import org.apache.fineract.portfolio.client.data.ClientDataValidator;
import org.apache.fineract.portfolio.client.domain.*; import org.apache.fineract.portfolio.client.domain.AccountNumberGenerator;
import org.apache.fineract.portfolio.client.exception.*; import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.domain.ClientNonPerson;
import org.apache.fineract.portfolio.client.domain.ClientNonPersonRepositoryWrapper;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.fineract.portfolio.client.domain.ClientStatus;
import org.apache.fineract.portfolio.client.domain.LegalForm;
import org.apache.fineract.portfolio.client.exception.ClientActiveForUpdateException;
import org.apache.fineract.portfolio.client.exception.ClientHasNoStaffException;
import org.apache.fineract.portfolio.client.exception.ClientMustBePendingToBeDeletedException;
import org.apache.fineract.portfolio.client.exception.InvalidClientSavingProductException;
import org.apache.fineract.portfolio.client.exception.InvalidClientStateTransitionException;
import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_ENTITY; import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_ENTITY;
import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS; import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
import org.apache.fineract.portfolio.common.service.BusinessEventNotifierService; import org.apache.fineract.portfolio.common.service.BusinessEventNotifierService;
@@ -151,23 +165,29 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
@Transactional @Transactional
@Override @Override
public CommandProcessingResult deleteClient(final Long clientId) { public CommandProcessingResult deleteClient(final Long clientId) {
try {
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId); if (client.isNotPending()) { throw new ClientMustBePendingToBeDeletedException(clientId); }
final List<Note> relatedNotes = this.noteRepository.findByClientId(clientId);
this.noteRepository.deleteInBatch(relatedNotes);
if (client.isNotPending()) { throw new ClientMustBePendingToBeDeletedException(clientId); } final ClientNonPerson clientNonPerson = this.clientNonPersonRepository.findOneByClientId(clientId);
final List<Note> relatedNotes = this.noteRepository.findByClientId(clientId); if (clientNonPerson != null) this.clientNonPersonRepository.delete(clientNonPerson);
this.noteRepository.deleteInBatch(relatedNotes);
final ClientNonPerson clientNonPerson = this.clientNonPersonRepository.findOneByClientId(clientId); this.clientRepository.delete(client);
if(clientNonPerson != null) this.clientRepository.flush();
this.clientNonPersonRepository.delete(clientNonPerson); return new CommandProcessingResultBuilder() //
.withOfficeId(client.officeId()) //
this.clientRepository.delete(client); .withClientId(clientId) //
return new CommandProcessingResultBuilder() // .withEntityId(clientId) //
.withOfficeId(client.officeId()) // .build();
.withClientId(clientId) // } catch (DataIntegrityViolationException dve) {
.withEntityId(clientId) // Throwable throwable = ExceptionUtils.getRootCause(dve.getCause()) ;
.build(); logger.error(throwable.getMessage());
throw new PlatformDataIntegrityException("error.msg.client.unknown.data.integrity.issue",
"Unknown data integrity issue with resource.");
}
} }
/* /*
@@ -270,9 +290,11 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
final Client newClient = Client.createNew(currentUser, clientOffice, clientParentGroup, staff, savingsProductId, gender, final Client newClient = Client.createNew(currentUser, clientOffice, clientParentGroup, staff, savingsProductId, gender,
clientType, clientClassification, legalFormValue, command); clientType, clientClassification, legalFormValue, command);
this.clientRepository.save(newClient);
boolean rollbackTransaction = false; boolean rollbackTransaction = false;
if (newClient.isActive()) { if (newClient.isActive()) {
validateParentGroupRulesBeforeClientActivation(newClient); validateParentGroupRulesBeforeClientActivation(newClient);
runEntityDatatableCheck(newClient.getId());
final CommandWrapper commandWrapper = new CommandWrapperBuilder().activateClient(null).build(); final CommandWrapper commandWrapper = new CommandWrapperBuilder().activateClient(null).build();
rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, currentUser); rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, currentUser);
} }
@@ -533,8 +555,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale); final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
final LocalDate activationDate = command.localDateValueOfParameterNamed("activationDate"); final LocalDate activationDate = command.localDateValueOfParameterNamed("activationDate");
entityDatatableChecksWritePlatformService.runTheCheck(clientId, EntityTables.CLIENT.getName(), runEntityDatatableCheck(clientId);
StatusEnum.ACTIVATE.getCode().longValue(), EntityTables.CLIENT.getForeignKeyColumnNameOnDatatable());
final AppUser currentUser = this.context.authenticatedUser(); final AppUser currentUser = this.context.authenticatedUser();
client.activate(currentUser, fmt, activationDate); client.activate(currentUser, fmt, activationDate);
@@ -766,6 +787,11 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
} }
} }
private void runEntityDatatableCheck(final Long clientId) {
entityDatatableChecksWritePlatformService.runTheCheck(clientId, EntityTables.CLIENT.getName(), StatusEnum.ACTIVATE.getCode()
.longValue(), EntityTables.CLIENT.getForeignKeyColumnNameOnDatatable());
}
@Override @Override
public CommandProcessingResult rejectClient(final Long entityId, final JsonCommand command) { public CommandProcessingResult rejectClient(final Long entityId, final JsonCommand command) {
final AppUser currentUser = this.context.authenticatedUser(); final AppUser currentUser = this.context.authenticatedUser();
@@ -62,4 +62,8 @@ public class GroupRepositoryWrapper {
public void delete(final Group entity) { public void delete(final Group entity) {
this.repository.delete(entity); this.repository.delete(entity);
} }
public void flush() {
this.repository.flush();
}
} }
@@ -174,6 +174,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
boolean rollbackTransaction = false; boolean rollbackTransaction = false;
if (newGroup.isActive()) { if (newGroup.isActive()) {
this.groupRepository.save(newGroup);
// validate Group creation rules for Group // validate Group creation rules for Group
if (newGroup.isGroup()) { if (newGroup.isGroup()) {
validateGroupRulesBeforeActivation(newGroup); validateGroupRulesBeforeActivation(newGroup);
@@ -295,9 +296,6 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
validateOfficeOpeningDateisAfterGroupOrCenterOpeningDate(group.getOffice(), group.getGroupLevel(), activationDate); validateOfficeOpeningDateisAfterGroupOrCenterOpeningDate(group.getOffice(), group.getGroupLevel(), activationDate);
entityDatatableChecksWritePlatformService.runTheCheck(groupId, EntityTables.GROUP.getName(),
StatusEnum.ACTIVATE.getCode().longValue(), EntityTables.GROUP.getForeignKeyColumnNameOnDatatable());
group.activate(currentUser, activationDate); group.activate(currentUser, activationDate);
this.groupRepository.saveAndFlush(group); this.groupRepository.saveAndFlush(group);
@@ -323,6 +321,8 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
Integer maxClients = configurationDomainService.retrieveMaxAllowedClientsInGroup(); Integer maxClients = configurationDomainService.retrieveMaxAllowedClientsInGroup();
boolean isGroupClientCountValid = group.isGroupsClientCountWithinMinMaxRange(minClients, maxClients); boolean isGroupClientCountValid = group.isGroupsClientCountWithinMinMaxRange(minClients, maxClients);
if (!isGroupClientCountValid) { throw new GroupMemberCountNotInPermissibleRangeException(group.getId(), minClients, maxClients); } if (!isGroupClientCountValid) { throw new GroupMemberCountNotInPermissibleRangeException(group.getId(), minClients, maxClients); }
entityDatatableChecksWritePlatformService.runTheCheck(group.getId(), EntityTables.GROUP.getName(),
StatusEnum.ACTIVATE.getCode().longValue(), EntityTables.GROUP.getForeignKeyColumnNameOnDatatable());
} }
public void validateGroupRulesBeforeClientAssociation(final Group group) { public void validateGroupRulesBeforeClientAssociation(final Group group) {
@@ -549,21 +549,28 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
@Transactional @Transactional
@Override @Override
public CommandProcessingResult deleteGroup(final Long groupId) { public CommandProcessingResult deleteGroup(final Long groupId) {
try {
final Group groupForDelete = this.groupRepository.findOneWithNotFoundDetection(groupId); final Group groupForDelete = this.groupRepository.findOneWithNotFoundDetection(groupId);
if (groupForDelete.isNotPending()) { throw new GroupMustBePendingToBeDeletedException(groupId); } if (groupForDelete.isNotPending()) { throw new GroupMustBePendingToBeDeletedException(groupId); }
final List<Note> relatedNotes = this.noteRepository.findByGroupId(groupId); final List<Note> relatedNotes = this.noteRepository.findByGroupId(groupId);
this.noteRepository.deleteInBatch(relatedNotes); this.noteRepository.deleteInBatch(relatedNotes);
this.groupRepository.delete(groupForDelete); this.groupRepository.delete(groupForDelete);
this.groupRepository.flush();
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withOfficeId(groupForDelete.getId()) // .withOfficeId(groupForDelete.getId()) //
.withGroupId(groupForDelete.officeId()) // .withGroupId(groupForDelete.officeId()) //
.withEntityId(groupForDelete.getId()) // .withEntityId(groupForDelete.getId()) //
.build(); .build();
} catch (DataIntegrityViolationException dve) {
Throwable throwable = ExceptionUtils.getRootCause(dve.getCause());
logger.error(throwable.getMessage());
throw new PlatformDataIntegrityException("error.msg.group.unknown.data.integrity.issue",
"Unknown data integrity issue with resource.");
}
} }
@Override @Override
@@ -268,7 +268,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final Date rescheduledRepaymentDate = command.DateValueOfParameterNamed("adjustRepaymentDate"); final Date rescheduledRepaymentDate = command.DateValueOfParameterNamed("adjustRepaymentDate");
entityDatatableChecksWritePlatformService.runTheCheckForProduct(loanId, EntityTables.LOAN.getName(), entityDatatableChecksWritePlatformService.runTheCheckForProduct(loanId, EntityTables.LOAN.getName(),
StatusEnum.ACTIVATE.getCode().longValue(), EntityTables.LOAN.getForeignKeyColumnNameOnDatatable(), loan.productId()); StatusEnum.DISBURSE.getCode().longValue(), EntityTables.LOAN.getForeignKeyColumnNameOnDatatable(), loan.productId());
// check for product mix validations // check for product mix validations
checkForProductMixRestrictions(loan); checkForProductMixRestrictions(loan);