support soft delete of clients (includes database upgrade patch)
This commit is contained in:
@@ -196,6 +196,7 @@ CREATE TABLE `admin_appuser_role` (
|
|||||||
-- DDL for portfolio tables
|
-- DDL for portfolio tables
|
||||||
CREATE TABLE `portfolio_client` (
|
CREATE TABLE `portfolio_client` (
|
||||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||||
|
`is_deleted` tinyint(1) NOT NULL DEFAULT 0,
|
||||||
`office_id` bigint(20) NOT NULL,
|
`office_id` bigint(20) NOT NULL,
|
||||||
`external_id` varchar(100) DEFAULT NULL,
|
`external_id` varchar(100) DEFAULT NULL,
|
||||||
`firstname` varchar(50) DEFAULT NULL,
|
`firstname` varchar(50) DEFAULT NULL,
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
-- add soft delete flag for clients
|
||||||
|
|
||||||
|
ALTER TABLE `portfolio_client` ADD COLUMN `is_deleted` tinyint(1) NOT NULL DEFAULT 0;
|
||||||
+11
-11
@@ -708,8 +708,8 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
|
|||||||
throw new InvalidJsonException();
|
throw new InvalidJsonException();
|
||||||
}
|
}
|
||||||
|
|
||||||
Type typeOfMap = new TypeToken<Map<String, Object>>(){}.getType();
|
Type typeOfMap = new TypeToken<Map<String, String>>(){}.getType();
|
||||||
Map<String, Object> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
Map<String, String> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
||||||
|
|
||||||
Set<String> supportedParams = new HashSet<String>(
|
Set<String> supportedParams = new HashSet<String>(
|
||||||
Arrays.asList("username", "firstname", "lastname", "password", "repeatPassword", "email", "officeId", "notSelectedRoles", "roles")
|
Arrays.asList("username", "firstname", "lastname", "password", "repeatPassword", "email", "officeId", "notSelectedRoles", "roles")
|
||||||
@@ -765,8 +765,8 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
|
|||||||
throw new InvalidJsonException();
|
throw new InvalidJsonException();
|
||||||
}
|
}
|
||||||
|
|
||||||
Type typeOfMap = new TypeToken<Map<String, Object>>(){}.getType();
|
Type typeOfMap = new TypeToken<Map<String, String>>(){}.getType();
|
||||||
Map<String, Object> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
Map<String, String> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
||||||
|
|
||||||
Set<String> supportedParams = new HashSet<String>(
|
Set<String> supportedParams = new HashSet<String>(
|
||||||
Arrays.asList("fromOfficeId", "toOfficeId", "transactionDate", "currencyCode", "transactionAmount", "description", "locale", "dateFormat")
|
Arrays.asList("fromOfficeId", "toOfficeId", "transactionDate", "currencyCode", "transactionAmount", "description", "locale", "dateFormat")
|
||||||
@@ -792,8 +792,8 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
|
|||||||
throw new InvalidJsonException();
|
throw new InvalidJsonException();
|
||||||
}
|
}
|
||||||
|
|
||||||
Type typeOfMap = new TypeToken<Map<String, Object>>(){}.getType();
|
Type typeOfMap = new TypeToken<Map<String, String>>(){}.getType();
|
||||||
Map<String, Object> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
Map<String, String> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
||||||
|
|
||||||
Set<String> supportedParams = new HashSet<String>(
|
Set<String> supportedParams = new HashSet<String>(
|
||||||
Arrays.asList("externalId", "firstname", "lastname", "clientOrBusinessName", "officeId", "joiningDate", "dateFormat")
|
Arrays.asList("externalId", "firstname", "lastname", "clientOrBusinessName", "officeId", "joiningDate", "dateFormat")
|
||||||
@@ -863,8 +863,8 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
|
|||||||
throw new InvalidJsonException();
|
throw new InvalidJsonException();
|
||||||
}
|
}
|
||||||
|
|
||||||
Type typeOfMap = new TypeToken<Map<String, Object>>(){}.getType();
|
Type typeOfMap = new TypeToken<Map<String, String>>(){}.getType();
|
||||||
Map<String, Object> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
Map<String, String> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
||||||
|
|
||||||
Set<String> supportedParams = new HashSet<String>(
|
Set<String> supportedParams = new HashSet<String>(
|
||||||
Arrays.asList("clientId", "productId", "externalId", "fundId",
|
Arrays.asList("clientId", "productId", "externalId", "fundId",
|
||||||
@@ -1089,12 +1089,12 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
|
|||||||
return paramValue;
|
return paramValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Long extractLongParameter(final String paramName, final Map<String, ?> requestMap, final Set<String> modifiedParameters) {
|
private Long extractLongParameter(final String paramName, final Map<String, String> requestMap, final Set<String> modifiedParameters) {
|
||||||
Long paramValue = null;
|
Long paramValue = null;
|
||||||
if (requestMap.containsKey(paramName)) {
|
if (requestMap.containsKey(paramName)) {
|
||||||
String valueAsString = (String) requestMap.get(paramName);
|
String valueAsString = requestMap.get(paramName);
|
||||||
if (StringUtils.isNotBlank(valueAsString)) {
|
if (StringUtils.isNotBlank(valueAsString)) {
|
||||||
paramValue = Long.valueOf(valueAsString);
|
paramValue = Long.valueOf(Double.valueOf(valueAsString).longValue());
|
||||||
}
|
}
|
||||||
modifiedParameters.add(paramName);
|
modifiedParameters.add(paramName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ public class Client extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
@Column(name = "external_id", length=100, unique=true)
|
@Column(name = "external_id", length=100, unique=true)
|
||||||
private String externalId;
|
private String externalId;
|
||||||
|
|
||||||
|
@Column(name = "is_deleted", nullable=false)
|
||||||
|
private boolean deleted = false;
|
||||||
|
|
||||||
public static Client newClient(Office clientOffice, String firstname, String lastname, LocalDate joiningDate, String externalId) {
|
public static Client newClient(Office clientOffice, String firstname, String lastname, LocalDate joiningDate, String externalId) {
|
||||||
return new Client(clientOffice, firstname, lastname, joiningDate, externalId);
|
return new Client(clientOffice, firstname, lastname, joiningDate, externalId);
|
||||||
}
|
}
|
||||||
@@ -112,4 +115,18 @@ public class Client extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
this.externalId = externalId.trim();
|
this.externalId = externalId.trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete is a <i>soft delete</i>. Updates flag on client so it wont appear in query/report results.
|
||||||
|
*
|
||||||
|
* Any fields with unique constraints and prepended with id of record.
|
||||||
|
*/
|
||||||
|
public void delete() {
|
||||||
|
this.deleted = true;
|
||||||
|
this.externalId = this.getId() + "_" + this.externalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDeleted() {
|
||||||
|
return deleted;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+11
-2
@@ -74,7 +74,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
|||||||
|
|
||||||
ClientMapper rm = new ClientMapper(offices);
|
ClientMapper rm = new ClientMapper(offices);
|
||||||
|
|
||||||
String sql = "select " + rm.clientSchema() + " where c.office_id in (" + officeIdsList + ") ";
|
String sql = "select " + rm.clientSchema() + " where c.office_id in (" + officeIdsList + ") and c.is_deleted=0";
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(extraCriteria))
|
if (StringUtils.isNotBlank(extraCriteria))
|
||||||
sql += " and " + extraCriteria;
|
sql += " and " + extraCriteria;
|
||||||
@@ -95,7 +95,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
|||||||
officeReadPlatformService.retrieveAllOffices());
|
officeReadPlatformService.retrieveAllOffices());
|
||||||
ClientMapper rm = new ClientMapper(offices);
|
ClientMapper rm = new ClientMapper(offices);
|
||||||
|
|
||||||
String sql = "select " + rm.clientSchema() + " where c.id = ? ";
|
String sql = "select " + rm.clientSchema() + " where c.id = ? and c.is_deleted=0";
|
||||||
|
|
||||||
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] {clientId});
|
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] {clientId});
|
||||||
} catch (EmptyResultDataAccessException e) {
|
} catch (EmptyResultDataAccessException e) {
|
||||||
@@ -166,6 +166,9 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
this.context.authenticatedUser();
|
this.context.authenticatedUser();
|
||||||
|
|
||||||
|
// Check if client exists
|
||||||
|
retrieveIndividualClient(clientId);
|
||||||
|
|
||||||
List<ClientLoanAccountSummaryData> pendingApprovalLoans = new ArrayList<ClientLoanAccountSummaryData>();
|
List<ClientLoanAccountSummaryData> pendingApprovalLoans = new ArrayList<ClientLoanAccountSummaryData>();
|
||||||
List<ClientLoanAccountSummaryData> awaitingDisbursalLoans = new ArrayList<ClientLoanAccountSummaryData>();
|
List<ClientLoanAccountSummaryData> awaitingDisbursalLoans = new ArrayList<ClientLoanAccountSummaryData>();
|
||||||
@@ -241,6 +244,9 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
context.authenticatedUser();
|
context.authenticatedUser();
|
||||||
|
|
||||||
|
// Check if client exists
|
||||||
|
retrieveIndividualClient(clientId);
|
||||||
|
|
||||||
// FIXME - use join on sql query to fetch user information for note
|
// FIXME - use join on sql query to fetch user information for note
|
||||||
// rather than fetching users?
|
// rather than fetching users?
|
||||||
@@ -262,6 +268,9 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
|||||||
public Collection<NoteData> retrieveAllClientNotes(Long clientId) {
|
public Collection<NoteData> retrieveAllClientNotes(Long clientId) {
|
||||||
|
|
||||||
context.authenticatedUser();
|
context.authenticatedUser();
|
||||||
|
|
||||||
|
// Check if client exists
|
||||||
|
retrieveIndividualClient(clientId);
|
||||||
|
|
||||||
// FIXME - use join on sql query to fetch user information for note
|
// FIXME - use join on sql query to fetch user information for note
|
||||||
// rather than fetching users?
|
// rather than fetching users?
|
||||||
|
|||||||
+1
-1
@@ -20,5 +20,5 @@ public interface ClientWritePlatformService {
|
|||||||
EntityIdentifier updateNote(NoteCommand command);
|
EntityIdentifier updateNote(NoteCommand command);
|
||||||
|
|
||||||
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_DELETE_CLIENT_ROLE')")
|
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_DELETE_CLIENT_ROLE')")
|
||||||
void deleteClient(Long clientId);
|
EntityIdentifier deleteClient(Long clientId);
|
||||||
}
|
}
|
||||||
+10
-7
@@ -1,7 +1,5 @@
|
|||||||
package org.mifosng.platform.client.service;
|
package org.mifosng.platform.client.service;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.mifosng.platform.api.commands.ClientCommand;
|
import org.mifosng.platform.api.commands.ClientCommand;
|
||||||
import org.mifosng.platform.api.commands.NoteCommand;
|
import org.mifosng.platform.api.commands.NoteCommand;
|
||||||
@@ -39,12 +37,17 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public void deleteClient(final Long clientId) {
|
public EntityIdentifier deleteClient(final Long clientId) {
|
||||||
|
|
||||||
List<Note> relatedNotes = this.noteRepository.findByClientId(clientId);
|
Client client = this.clientRepository.findOne(clientId);
|
||||||
this.noteRepository.deleteInBatch(relatedNotes);
|
if (client == null || client.isDeleted()) {
|
||||||
|
throw new ClientNotFoundException(clientId);
|
||||||
|
}
|
||||||
|
|
||||||
this.clientRepository.delete(clientId);
|
client.delete();
|
||||||
|
this.clientRepository.save(client);
|
||||||
|
|
||||||
|
return new EntityIdentifier(client.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -101,7 +104,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
|||||||
}
|
}
|
||||||
|
|
||||||
Client clientForUpdate = this.clientRepository.findOne(command.getId());
|
Client clientForUpdate = this.clientRepository.findOne(command.getId());
|
||||||
if (clientForUpdate == null) {
|
if (clientForUpdate == null || clientForUpdate.isDeleted()) {
|
||||||
throw new ClientNotFoundException(command.getId());
|
throw new ClientNotFoundException(command.getId());
|
||||||
}
|
}
|
||||||
clientForUpdate.update(clientOffice, firstname, lastname, command.getExternalId(), command.getJoiningDate());
|
clientForUpdate.update(clientOffice, firstname, lastname, command.getExternalId(), command.getJoiningDate());
|
||||||
|
|||||||
Reference in New Issue
Block a user