refactor ApplicationConstants usage, refactor usage of code and code values for customer identifiers.
This commit is contained in:
+21
-31
@@ -1,8 +1,6 @@
|
||||
package org.mifosng.platform.api;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
@@ -21,6 +19,7 @@ import javax.ws.rs.core.UriInfo;
|
||||
import org.mifosng.platform.api.commands.ClientIdentifierCommand;
|
||||
import org.mifosng.platform.api.data.ClientData;
|
||||
import org.mifosng.platform.api.data.ClientIdentifierData;
|
||||
import org.mifosng.platform.api.data.CodeValueData;
|
||||
import org.mifosng.platform.api.data.EntityIdentifier;
|
||||
import org.mifosng.platform.api.infrastructure.PortfolioApiDataConversionService;
|
||||
import org.mifosng.platform.api.infrastructure.PortfolioApiJsonSerializerService;
|
||||
@@ -28,6 +27,7 @@ import org.mifosng.platform.client.service.ClientReadPlatformService;
|
||||
import org.mifosng.platform.client.service.ClientWritePlatformService;
|
||||
import org.mifosng.platform.exceptions.DuplicateClientIdentifierException;
|
||||
import org.mifosng.platform.infrastructure.api.ApiParameterHelper;
|
||||
import org.mifosng.platform.organisation.service.CodeValueReadPlatformService;
|
||||
import org.mifosng.platform.security.PlatformSecurityContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
@@ -40,6 +40,9 @@ public class ClientIdentifiersApiResource {
|
||||
|
||||
@Autowired
|
||||
private ClientReadPlatformService clientReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
private CodeValueReadPlatformService codeValueReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
private ClientWritePlatformService clientWritePlatformService;
|
||||
@@ -50,33 +53,26 @@ public class ClientIdentifiersApiResource {
|
||||
@Autowired
|
||||
private PortfolioApiJsonSerializerService apiJsonSerializerService;
|
||||
|
||||
private static final Set<String> typicalResponseParameters = new HashSet<String>(
|
||||
Arrays.asList("id", "clientId", "documentTypeId", "description",
|
||||
"documentKey", "documentTypeName"));
|
||||
@Autowired
|
||||
private PlatformSecurityContext context;
|
||||
|
||||
private final String entityType = "CLIENTIDENTIFIER";
|
||||
@Autowired
|
||||
private PlatformSecurityContext context;
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveAllClientIdentifiers(@Context final UriInfo uriInfo,
|
||||
public String retrieveAllClientIdentifiers(
|
||||
@Context final UriInfo uriInfo,
|
||||
@PathParam("clientId") final Long clientId) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(entityType);
|
||||
|
||||
Set<String> responseParameters = ApiParameterHelper
|
||||
final Set<String> responseParameters = ApiParameterHelper
|
||||
.extractFieldsForResponseIfProvided(uriInfo
|
||||
.getQueryParameters());
|
||||
if (responseParameters.isEmpty()) {
|
||||
responseParameters.addAll(typicalResponseParameters);
|
||||
}
|
||||
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo
|
||||
.getQueryParameters());
|
||||
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
|
||||
|
||||
Collection<ClientIdentifierData> clientIdentifiers = this.clientReadPlatformService
|
||||
.retrieveClientIdentifiers(clientId);
|
||||
final Collection<ClientIdentifierData> clientIdentifiers = this.clientReadPlatformService.retrieveClientIdentifiers(clientId);
|
||||
|
||||
return this.apiJsonSerializerService
|
||||
.serializeClientIdentifierDataToJson(prettyPrint,
|
||||
@@ -91,16 +87,13 @@ public class ClientIdentifiersApiResource {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(entityType);
|
||||
|
||||
Set<String> responseParameters = ApiParameterHelper
|
||||
final Set<String> responseParameters = ApiParameterHelper
|
||||
.extractFieldsForResponseIfProvided(uriInfo
|
||||
.getQueryParameters());
|
||||
responseParameters.addAll(typicalResponseParameters);
|
||||
responseParameters.add("allowedDocumentTypes");
|
||||
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo
|
||||
.getQueryParameters());
|
||||
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
|
||||
|
||||
ClientIdentifierData clientIdentifierData = this.clientReadPlatformService
|
||||
.retrieveNewClientIdentifierDetails();
|
||||
Collection<CodeValueData> codeValues = codeValueReadPlatformService.retrieveCustomIdentifierCodeValues();
|
||||
ClientIdentifierData clientIdentifierData = ClientIdentifierData.template(codeValues);
|
||||
|
||||
return this.apiJsonSerializerService
|
||||
.serializeClientIdentifierDataToJson(prettyPrint,
|
||||
@@ -144,18 +137,15 @@ public class ClientIdentifiersApiResource {
|
||||
context.authenticatedUser().validateHasReadPermission(entityType);
|
||||
|
||||
final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
|
||||
if (responseParameters.isEmpty()) {
|
||||
responseParameters.addAll(typicalResponseParameters);
|
||||
}
|
||||
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
|
||||
final boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
|
||||
|
||||
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
|
||||
boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
|
||||
ClientIdentifierData clientIdentifierData = this.clientReadPlatformService.retrieveClientIdentifier(clientId, clientIdentifierId);
|
||||
if (template) {
|
||||
responseParameters.add("allowedDocumentTypes");
|
||||
final Collection<CodeValueData> codeValues = codeValueReadPlatformService.retrieveCustomIdentifierCodeValues();
|
||||
clientIdentifierData = ClientIdentifierData.template(clientIdentifierData, codeValues);
|
||||
}
|
||||
|
||||
final ClientIdentifierData clientIdentifierData = this.clientReadPlatformService.retrieveClientIdentifier(clientId, clientIdentifierId);
|
||||
|
||||
return this.apiJsonSerializerService
|
||||
.serializeClientIdentifierDataToJson(prettyPrint,
|
||||
responseParameters, clientIdentifierData);
|
||||
|
||||
@@ -32,15 +32,14 @@ import org.mifosng.platform.api.data.CommandSourceData;
|
||||
import org.mifosng.platform.api.data.EntityIdentifier;
|
||||
import org.mifosng.platform.api.data.NoteData;
|
||||
import org.mifosng.platform.api.data.OfficeLookup;
|
||||
import org.mifosng.platform.api.infrastructure.ApiConstants;
|
||||
import org.mifosng.platform.api.infrastructure.PortfolioApiDataConversionService;
|
||||
import org.mifosng.platform.api.infrastructure.PortfolioApiJsonSerializerService;
|
||||
import org.mifosng.platform.client.service.ClientReadPlatformService;
|
||||
import org.mifosng.platform.client.service.ClientWritePlatformService;
|
||||
import org.mifosng.platform.common.ApplicationConstants;
|
||||
import org.mifosng.platform.common.Base64EncodedImage;
|
||||
import org.mifosng.platform.common.FileUtils;
|
||||
import org.mifosng.platform.exceptions.ClientNotFoundException;
|
||||
import org.mifosng.platform.exceptions.ImageNotFoundException;
|
||||
import org.mifosng.platform.infrastructure.Base64EncodedImage;
|
||||
import org.mifosng.platform.infrastructure.FileUtils;
|
||||
import org.mifosng.platform.infrastructure.api.ApiParameterHelper;
|
||||
import org.mifosng.platform.makerchecker.service.PortfolioCommandSourceWritePlatformService;
|
||||
import org.mifosng.platform.makerchecker.service.PortfolioCommandsReadPlatformService;
|
||||
@@ -348,13 +347,8 @@ public class ClientsApiResource {
|
||||
return Response.ok().entity(identifier).build();
|
||||
}
|
||||
|
||||
/** Upload images through multi-part form upload
|
||||
* @param clientId
|
||||
* @param fileSize
|
||||
* @param inputStream
|
||||
* @param fileDetails
|
||||
* @param bodyPart
|
||||
* @return
|
||||
/**
|
||||
* Upload images through multi-part form upload
|
||||
*/
|
||||
@POST
|
||||
@Path("{clientId}/image")
|
||||
@@ -374,7 +368,7 @@ public class ClientsApiResource {
|
||||
FileUtils.validateImageMimeType(bodyPart.getMediaType().toString());
|
||||
FileUtils.validateFileSizeWithinPermissibleRange(fileSize,
|
||||
fileDetails.getFileName(),
|
||||
ApplicationConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
|
||||
ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
|
||||
|
||||
logger.debug(bodyPart.getMediaType().toString());
|
||||
|
||||
@@ -382,16 +376,12 @@ public class ClientsApiResource {
|
||||
.saveOrUpdateClientImage(clientId, fileDetails.getFileName(),
|
||||
inputStream);
|
||||
|
||||
// return identifier of the client whose image was updated
|
||||
return Response.ok().entity(entityIdentifier).build();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** Upload image as a Data URL (essentially a base64 encoded stream)
|
||||
* @param clientId
|
||||
* @param jsonRequestBody
|
||||
* @return
|
||||
/**
|
||||
* Upload image as a Data URL (essentially a base64 encoded stream)
|
||||
*/
|
||||
@POST
|
||||
@Path("{clientId}/image")
|
||||
@@ -407,14 +397,11 @@ public class ClientsApiResource {
|
||||
EntityIdentifier entityIdentifier = this.clientWritePlatformService
|
||||
.saveOrUpdateClientImage(clientId, base64EncodedImage);
|
||||
|
||||
// return identifier of the client whose image was updated
|
||||
return Response.ok().entity(entityIdentifier).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a base 64 encoded client image
|
||||
* @param clientId
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Path("{clientId}/image")
|
||||
@@ -426,28 +413,17 @@ public class ClientsApiResource {
|
||||
context.authenticatedUser().validateHasReadPermission("CLIENTIMAGE");
|
||||
|
||||
final ClientData clientData = this.clientReadPlatformService.retrieveIndividualClient(clientId);
|
||||
//validate if client does not exist or image key is null
|
||||
if(clientData == null){
|
||||
throw new ClientNotFoundException(clientId);
|
||||
}
|
||||
else if(clientData.imageKeyDoesNotExist()){
|
||||
throw new ImageNotFoundException(ApplicationConstants.IMAGE_MANAGEMENT_ENTITY.CLIENTS, clientId);
|
||||
|
||||
if (clientData.imageKeyDoesNotExist()) {
|
||||
throw new ImageNotFoundException("clients", clientId);
|
||||
}
|
||||
return Response.ok().entity(Base64.encodeFromFile(clientData.imageKey())).build();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** This method is added only for consistency with other URL patterns
|
||||
* and for maintaining consistency of usage of the HTTP "verb"
|
||||
* at the client side
|
||||
*
|
||||
* @param clientId
|
||||
* @param fileSize
|
||||
* @param inputStream
|
||||
* @param fileDetails
|
||||
* @param bodyPart
|
||||
* @return
|
||||
/**
|
||||
* This method is added only for consistency with other URL patterns
|
||||
* and for maintaining consistency of usage of the HTTP "verb"
|
||||
* at the client side
|
||||
*/
|
||||
@PUT
|
||||
@Path("{clientId}/image")
|
||||
@@ -479,9 +455,6 @@ public class ClientsApiResource {
|
||||
* at the client side
|
||||
*
|
||||
* Upload image as a Data URL (essentially a base64 encoded stream)
|
||||
* @param clientId
|
||||
* @param jsonRequestBody
|
||||
* @return
|
||||
*/
|
||||
@PUT
|
||||
@Path("{clientId}/image")
|
||||
|
||||
+4
-4
@@ -25,11 +25,11 @@ import javax.ws.rs.core.UriInfo;
|
||||
import org.mifosng.platform.api.commands.DocumentCommand;
|
||||
import org.mifosng.platform.api.data.DocumentData;
|
||||
import org.mifosng.platform.api.data.EntityIdentifier;
|
||||
import org.mifosng.platform.api.infrastructure.ApiConstants;
|
||||
import org.mifosng.platform.api.infrastructure.PortfolioApiJsonSerializerService;
|
||||
import org.mifosng.platform.common.ApplicationConstants;
|
||||
import org.mifosng.platform.common.FileUtils;
|
||||
import org.mifosng.platform.documentmanagement.service.DocumentReadPlatformService;
|
||||
import org.mifosng.platform.documentmanagement.service.DocumentWritePlatformService;
|
||||
import org.mifosng.platform.infrastructure.FileUtils;
|
||||
import org.mifosng.platform.infrastructure.api.ApiParameterHelper;
|
||||
import org.mifosng.platform.security.PlatformSecurityContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -116,7 +116,7 @@ public class DocumentManagementApiResource {
|
||||
@FormDataParam("name") String name,
|
||||
@FormDataParam("description") String description) {
|
||||
|
||||
FileUtils.validateFileSizeWithinPermissibleRange(fileSize, name, ApplicationConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
|
||||
FileUtils.validateFileSizeWithinPermissibleRange(fileSize, name, ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
|
||||
|
||||
/**
|
||||
* TODO: also need to have a backup and stop reading from stream after
|
||||
@@ -163,7 +163,7 @@ public class DocumentManagementApiResource {
|
||||
@FormDataParam("name") String name,
|
||||
@FormDataParam("description") String description) {
|
||||
|
||||
FileUtils.validateFileSizeWithinPermissibleRange(fileSize, name, ApplicationConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
|
||||
FileUtils.validateFileSizeWithinPermissibleRange(fileSize, name, ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
|
||||
|
||||
Set<String> modifiedParams = new HashSet<String>();
|
||||
modifiedParams.add("name");
|
||||
|
||||
+34
-52
@@ -1,73 +1,55 @@
|
||||
package org.mifosng.platform.api.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Immutable data object represent client identity data.
|
||||
*/
|
||||
public class ClientIdentifierData {
|
||||
|
||||
private final Long id;
|
||||
private final Long clientId;
|
||||
private final Long documentTypeId;
|
||||
private final String documentTypeName;
|
||||
|
||||
private final String documentKey;
|
||||
private final String description;
|
||||
private List<CodeValueData> allowedDocumentTypes = new ArrayList<CodeValueData>();
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<CodeValueData> allowedDocumentTypes;
|
||||
|
||||
public static ClientIdentifierData singleItem(
|
||||
final Long id,
|
||||
final Long clientId,
|
||||
final Long documentTypeId,
|
||||
final String documentKey,
|
||||
final String description,
|
||||
final String documentTypeName) {
|
||||
return new ClientIdentifierData(id, clientId, documentTypeId, documentKey, description, documentTypeName, null);
|
||||
}
|
||||
|
||||
public static ClientIdentifierData template(final Collection<CodeValueData> codeValues) {
|
||||
return new ClientIdentifierData(null, null, null, null, null, null, codeValues);
|
||||
}
|
||||
|
||||
public static ClientIdentifierData template(
|
||||
final ClientIdentifierData data,
|
||||
final Collection<CodeValueData> codeValues) {
|
||||
return new ClientIdentifierData(data.id, data.clientId, data.documentTypeId, data.documentKey, data.description, data.documentTypeName, codeValues);
|
||||
}
|
||||
|
||||
public ClientIdentifierData(final Long id, final Long clientId,
|
||||
final Long documentTypeId, final String documentKey,
|
||||
final String description, final String documentTypeName) {
|
||||
public ClientIdentifierData(
|
||||
final Long id,
|
||||
final Long clientId,
|
||||
final Long documentTypeId,
|
||||
final String documentKey,
|
||||
final String description,
|
||||
final String documentTypeName,
|
||||
final Collection<CodeValueData> allowedDocumentTypes) {
|
||||
this.id = id;
|
||||
this.clientId = clientId;
|
||||
this.documentTypeId = documentTypeId;
|
||||
this.documentKey = documentKey;
|
||||
this.description = description;
|
||||
this.documentTypeName = documentTypeName;
|
||||
}
|
||||
|
||||
public ClientIdentifierData(final Long clientId, final Long documentTypeId,
|
||||
final String documentKey, final String description,
|
||||
final String documentTypeName,
|
||||
List<CodeValueData> allowedDocumentTypes) {
|
||||
this.id = null;
|
||||
this.clientId = clientId;
|
||||
this.documentTypeId = documentTypeId;
|
||||
this.documentKey = documentKey;
|
||||
this.description = description;
|
||||
this.documentTypeName = documentTypeName;
|
||||
this.allowedDocumentTypes = allowedDocumentTypes;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Long getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public Long getDocumentTypeId() {
|
||||
return documentTypeId;
|
||||
}
|
||||
|
||||
public String getDocumentKey() {
|
||||
return documentKey;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public List<CodeValueData> getAllowedDocumentTypes() {
|
||||
return allowedDocumentTypes;
|
||||
}
|
||||
|
||||
public void setAllowedDocumentTypes(List<CodeValueData> allowedDocumentTypes) {
|
||||
this.allowedDocumentTypes = allowedDocumentTypes;
|
||||
}
|
||||
|
||||
public String getDocumentTypeName() {
|
||||
return documentTypeName;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,35 +1,17 @@
|
||||
package org.mifosng.platform.api.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
/**
|
||||
* Immutable data object representing a code.
|
||||
*/
|
||||
public class CodeData {
|
||||
|
||||
public class CodeData implements Serializable {
|
||||
@SuppressWarnings("unused")
|
||||
private final Long id;
|
||||
@SuppressWarnings("unused")
|
||||
private final String name;
|
||||
|
||||
private Long id;
|
||||
private String codeName;
|
||||
|
||||
public CodeData() {
|
||||
//
|
||||
}
|
||||
|
||||
public CodeData(final Long id, final String codeName) {
|
||||
public CodeData(final Long id, final String name) {
|
||||
this.id = id;
|
||||
this.codeName = codeName;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getCodeName() {
|
||||
return codeName;
|
||||
}
|
||||
|
||||
public void setName(String codeName) {
|
||||
this.codeName = codeName;
|
||||
}
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package org.mifosng.platform.api.infrastructure;
|
||||
|
||||
public class ApiConstants {
|
||||
|
||||
// TODO:Vishwas Need to move these settings to the Database
|
||||
public static final Integer MAX_FILE_UPLOAD_SIZE_IN_MB = 5;
|
||||
|
||||
// TODO:Vishwas Need to move these settings to the Database
|
||||
public static final Integer MAX_IMAGE_UPLOAD_SIZE_IN_MB = 1;
|
||||
}
|
||||
-2
@@ -33,7 +33,5 @@ public interface ClientReadPlatformService {
|
||||
|
||||
ClientIdentifierData retrieveClientIdentifier(Long clientId,Long clientIdentifierId);
|
||||
|
||||
ClientIdentifierData retrieveNewClientIdentifierDetails();
|
||||
|
||||
ClientData retrieveClientByIdentifier(Long identifierTypeId, String identifierKey);
|
||||
}
|
||||
+15
-40
@@ -15,18 +15,15 @@ import org.mifosng.platform.api.data.ClientAccountSummaryData;
|
||||
import org.mifosng.platform.api.data.ClientData;
|
||||
import org.mifosng.platform.api.data.ClientIdentifierData;
|
||||
import org.mifosng.platform.api.data.ClientLookup;
|
||||
import org.mifosng.platform.api.data.CodeValueData;
|
||||
import org.mifosng.platform.api.data.EnumOptionData;
|
||||
import org.mifosng.platform.api.data.NoteData;
|
||||
import org.mifosng.platform.api.data.OfficeLookup;
|
||||
import org.mifosng.platform.client.domain.NoteEnumerations;
|
||||
import org.mifosng.platform.common.ApplicationConstants;
|
||||
import org.mifosng.platform.exceptions.ClientIdentifierNotFoundException;
|
||||
import org.mifosng.platform.exceptions.ClientNotFoundException;
|
||||
import org.mifosng.platform.exceptions.NoteNotFoundException;
|
||||
import org.mifosng.platform.infrastructure.JdbcSupport;
|
||||
import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource;
|
||||
import org.mifosng.platform.organisation.service.CodeValueReadPlatformService;
|
||||
import org.mifosng.platform.organisation.service.OfficeReadPlatformService;
|
||||
import org.mifosng.platform.security.PlatformSecurityContext;
|
||||
import org.mifosng.platform.user.domain.AppUser;
|
||||
@@ -44,22 +41,18 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
private final PlatformSecurityContext context;
|
||||
private final OfficeReadPlatformService officeReadPlatformService;
|
||||
private final AppUserReadPlatformService appUserReadPlatformService;
|
||||
private final CodeValueReadPlatformService codeValuePlatformService;
|
||||
|
||||
@Autowired
|
||||
public ClientReadPlatformServiceImpl(final PlatformSecurityContext context,
|
||||
final TenantAwareRoutingDataSource dataSource,
|
||||
final OfficeReadPlatformService officeReadPlatformService,
|
||||
final AppUserReadPlatformService appUserReadPlatformService,
|
||||
final CodeValueReadPlatformService codeValuePlatformService) {
|
||||
final AppUserReadPlatformService appUserReadPlatformService) {
|
||||
this.context = context;
|
||||
this.officeReadPlatformService = officeReadPlatformService;
|
||||
this.appUserReadPlatformService = appUserReadPlatformService;
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
this.codeValuePlatformService = codeValuePlatformService;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<ClientData> retrieveAllIndividualClients(final String extraCriteria) {
|
||||
|
||||
@@ -445,8 +438,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ClientIdentifierData> retrieveClientIdentifiers(
|
||||
Long clientId) {
|
||||
public Collection<ClientIdentifierData> retrieveClientIdentifiers(final Long clientId) {
|
||||
|
||||
AppUser currentUser = context.authenticatedUser();
|
||||
String hierarchy = currentUser.getOffice().getHierarchy();
|
||||
@@ -458,13 +450,13 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
|
||||
sql += " order by ci.id";
|
||||
|
||||
return this.jdbcTemplate.query(sql, rm, new Object[] { clientId,
|
||||
hierarchySearchString });
|
||||
return this.jdbcTemplate.query(sql, rm, new Object[] { clientId, hierarchySearchString });
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientIdentifierData retrieveClientIdentifier(Long clientId,
|
||||
Long clientIdentifierId) {
|
||||
public ClientIdentifierData retrieveClientIdentifier(
|
||||
final Long clientId,
|
||||
final Long clientIdentifierId) {
|
||||
try {
|
||||
AppUser currentUser = context.authenticatedUser();
|
||||
String hierarchy = currentUser.getOffice().getHierarchy();
|
||||
@@ -476,14 +468,10 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
|
||||
sql += " and ci.id = ?";
|
||||
|
||||
ClientIdentifierData clientIdentifierData = this.jdbcTemplate
|
||||
final ClientIdentifierData clientIdentifierData = this.jdbcTemplate
|
||||
.queryForObject(sql, rm, new Object[] { clientId,
|
||||
hierarchySearchString, clientIdentifierId });
|
||||
|
||||
clientIdentifierData
|
||||
.setAllowedDocumentTypes(new ArrayList<CodeValueData>(
|
||||
codeValuePlatformService
|
||||
.retrieveAllCodeValues(ApplicationConstants.CLIENT_IDENTITY_CODE_ID)));
|
||||
return clientIdentifierData;
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
throw new ClientIdentifierNotFoundException(clientIdentifierId);
|
||||
@@ -491,19 +479,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientIdentifierData retrieveNewClientIdentifierDetails() {
|
||||
|
||||
context.authenticatedUser();
|
||||
|
||||
List<CodeValueData> codeValueDatas = new ArrayList<CodeValueData>(
|
||||
codeValuePlatformService.retrieveAllCodeValues(ApplicationConstants.CLIENT_IDENTITY_CODE_ID));
|
||||
|
||||
return new ClientIdentifierData(null,null,null,null,null,codeValueDatas);
|
||||
}
|
||||
|
||||
private static final class ClientIdentityMapper implements
|
||||
RowMapper<ClientIdentifierData> {
|
||||
private static final class ClientIdentityMapper implements RowMapper<ClientIdentifierData> {
|
||||
|
||||
public ClientIdentityMapper() {
|
||||
}
|
||||
@@ -522,15 +498,14 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
@SuppressWarnings("unused") final int rowNum)
|
||||
throws SQLException {
|
||||
|
||||
Long id = JdbcSupport.getLong(rs, "id");
|
||||
Long clientId = JdbcSupport.getLong(rs, "clientId");
|
||||
Long documentTypeId = JdbcSupport.getLong(rs, "documentTypeId");
|
||||
String documentKey = rs.getString("documentKey");
|
||||
String description = rs.getString("description");
|
||||
String documentTypeName = rs.getString("documentType");
|
||||
final Long id = JdbcSupport.getLong(rs, "id");
|
||||
final Long clientId = JdbcSupport.getLong(rs, "clientId");
|
||||
final Long documentTypeId = JdbcSupport.getLong(rs, "documentTypeId");
|
||||
final String documentKey = rs.getString("documentKey");
|
||||
final String description = rs.getString("description");
|
||||
final String documentTypeName = rs.getString("documentType");
|
||||
|
||||
return new ClientIdentifierData(id, clientId, documentTypeId,
|
||||
documentKey, description,documentTypeName);
|
||||
return ClientIdentifierData.singleItem(id, clientId, documentTypeId,documentKey, description,documentTypeName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import org.mifosng.platform.api.commands.ClientCommand;
|
||||
import org.mifosng.platform.api.commands.ClientIdentifierCommand;
|
||||
import org.mifosng.platform.api.commands.NoteCommand;
|
||||
import org.mifosng.platform.api.data.EntityIdentifier;
|
||||
import org.mifosng.platform.common.Base64EncodedImage;
|
||||
import org.mifosng.platform.infrastructure.Base64EncodedImage;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
public interface ClientWritePlatformService {
|
||||
|
||||
+14
-38
@@ -15,9 +15,6 @@ import org.mifosng.platform.client.domain.ClientIdentifierRepository;
|
||||
import org.mifosng.platform.client.domain.ClientRepository;
|
||||
import org.mifosng.platform.client.domain.Note;
|
||||
import org.mifosng.platform.client.domain.NoteRepository;
|
||||
import org.mifosng.platform.common.ApplicationConstants;
|
||||
import org.mifosng.platform.common.Base64EncodedImage;
|
||||
import org.mifosng.platform.common.FileUtils;
|
||||
import org.mifosng.platform.exceptions.ClientIdentifierNotFoundException;
|
||||
import org.mifosng.platform.exceptions.ClientNotFoundException;
|
||||
import org.mifosng.platform.exceptions.CodeValueNotFoundException;
|
||||
@@ -26,6 +23,8 @@ import org.mifosng.platform.exceptions.DuplicateClientIdentifierException;
|
||||
import org.mifosng.platform.exceptions.NoteNotFoundException;
|
||||
import org.mifosng.platform.exceptions.OfficeNotFoundException;
|
||||
import org.mifosng.platform.exceptions.PlatformDataIntegrityException;
|
||||
import org.mifosng.platform.infrastructure.Base64EncodedImage;
|
||||
import org.mifosng.platform.infrastructure.FileUtils;
|
||||
import org.mifosng.platform.organisation.domain.CodeValue;
|
||||
import org.mifosng.platform.organisation.domain.CodeValueRepository;
|
||||
import org.mifosng.platform.organisation.domain.Office;
|
||||
@@ -50,7 +49,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
private final NoteRepository noteRepository;
|
||||
private final CodeValueRepository codeValueRepository;
|
||||
|
||||
// FIXME - kw - this value is hardcoded for now but will be retrieved from coinfiguration
|
||||
// FIXME - kw - this value is hardcoded for now but will be retrieved from configuration
|
||||
private boolean makerCheckerEnabledForTask = false;
|
||||
|
||||
@Autowired
|
||||
@@ -366,29 +365,27 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public EntityIdentifier deleteClientImage(Long clientId) {
|
||||
public EntityIdentifier deleteClientImage(final Long clientId) {
|
||||
|
||||
final Client client = this.clientRepository.findOne(clientId);
|
||||
if (client == null || client.isDeleted()) {
|
||||
throw new ClientNotFoundException(clientId);
|
||||
}
|
||||
|
||||
// delete image from the file system
|
||||
if (StringUtils.isNotEmpty(client.getImageKey())) {
|
||||
FileUtils.deleteImage(
|
||||
ApplicationConstants.IMAGE_MANAGEMENT_ENTITY.CLIENTS,
|
||||
clientId, client.getImageKey());
|
||||
FileUtils.deleteClientImage(clientId, client.getImageKey());
|
||||
}
|
||||
return updateClientImage(clientId, client, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityIdentifier saveOrUpdateClientImage(Long clientId,
|
||||
Base64EncodedImage encodedImage) {
|
||||
public EntityIdentifier saveOrUpdateClientImage(final Long clientId, final Base64EncodedImage encodedImage) {
|
||||
try {
|
||||
final Client client = this.clientRepository.findOne(clientId);
|
||||
String imageUploadLocation = setupForClientImageUpdate(clientId,
|
||||
client);
|
||||
final String imageUploadLocation = setupForClientImageUpdate(clientId, client);
|
||||
|
||||
String imageLocation = FileUtils.saveToFileSystem(encodedImage, imageUploadLocation, "image");
|
||||
final String imageLocation = FileUtils.saveToFileSystem(encodedImage, imageUploadLocation, "image");
|
||||
|
||||
return updateClientImage(clientId, client, imageLocation);
|
||||
} catch (IOException ioe) {
|
||||
@@ -397,25 +394,15 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clientId
|
||||
* @param client
|
||||
* @return
|
||||
*/
|
||||
private String setupForClientImageUpdate(Long clientId, final Client client) {
|
||||
private String setupForClientImageUpdate(final Long clientId, final Client client) {
|
||||
if (client == null || client.isDeleted()) {
|
||||
throw new ClientNotFoundException(clientId);
|
||||
}
|
||||
|
||||
String imageUploadLocation = FileUtils
|
||||
.generateImageParentDirectory(
|
||||
ApplicationConstants.IMAGE_MANAGEMENT_ENTITY.CLIENTS,
|
||||
clientId);
|
||||
final String imageUploadLocation = FileUtils.generateClientImageParentDirectory(clientId);
|
||||
// delete previous image from the file system
|
||||
if (StringUtils.isNotEmpty(client.getImageKey())) {
|
||||
FileUtils.deleteImage(
|
||||
ApplicationConstants.IMAGE_MANAGEMENT_ENTITY.CLIENTS,
|
||||
clientId, client.getImageKey());
|
||||
FileUtils.deleteClientImage(clientId, client.getImageKey());
|
||||
}
|
||||
|
||||
/** Recursively create the directory if it does not exist **/
|
||||
@@ -425,21 +412,10 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
return imageUploadLocation;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param clientId
|
||||
* @param client
|
||||
* @param imageLocation
|
||||
* @return
|
||||
*/
|
||||
private EntityIdentifier updateClientImage(Long clientId,
|
||||
final Client client, String imageLocation) {
|
||||
private EntityIdentifier updateClientImage(final Long clientId, final Client client, final String imageLocation) {
|
||||
client.setImageKey(imageLocation);
|
||||
this.clientRepository.save(client);
|
||||
|
||||
return new EntityIdentifier(clientId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package org.mifosng.platform.common;
|
||||
|
||||
/**
|
||||
* @deprecated - KW - in general would like to avoid the whole throw it in common approach and dont want to see
|
||||
* - this file attract more application constants.
|
||||
*/
|
||||
@Deprecated
|
||||
public class ApplicationConstants {
|
||||
|
||||
/**
|
||||
* The intention of m_code table usage is not to use the id but the unique name of the code.
|
||||
*
|
||||
* This will stop reserved magic numbers spreading through application for one and it
|
||||
* more natural to use the code name like you would use a table name in a query.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Long CLIENT_IDENTITY_CODE_ID = 9L;
|
||||
|
||||
// TODO:Vishwas Need to move these settings to the Database
|
||||
public static final Integer MAX_FILE_UPLOAD_SIZE_IN_MB = 5;
|
||||
|
||||
// TODO:Vishwas Need to move these settings to the Database
|
||||
public static final Integer MAX_IMAGE_UPLOAD_SIZE_IN_MB = 1;
|
||||
|
||||
/*** Entities for document Management **/
|
||||
public static enum DOCUMENT_MANAGEMENT_ENTITY {
|
||||
CLIENTS, CLIENT_IDENTIFIERS, STAFF, LOANS, SAVINGS;
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
/*** Entities for image Management **/
|
||||
public static enum IMAGE_MANAGEMENT_ENTITY {
|
||||
CLIENTS, STAFF;
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+13
-19
@@ -6,14 +6,13 @@ import java.io.InputStream;
|
||||
|
||||
import org.mifosng.platform.api.commands.DocumentCommand;
|
||||
import org.mifosng.platform.api.data.EntityIdentifier;
|
||||
import org.mifosng.platform.common.ApplicationConstants;
|
||||
import org.mifosng.platform.common.FileUtils;
|
||||
import org.mifosng.platform.documentmanagement.domain.Document;
|
||||
import org.mifosng.platform.documentmanagement.domain.DocumentRepository;
|
||||
import org.mifosng.platform.exceptions.DocumentManagementException;
|
||||
import org.mifosng.platform.exceptions.DocumentNotFoundException;
|
||||
import org.mifosng.platform.exceptions.InvalidEntityTypeForDocumentManagementException;
|
||||
import org.mifosng.platform.exceptions.PlatformDataIntegrityException;
|
||||
import org.mifosng.platform.infrastructure.FileUtils;
|
||||
import org.mifosng.platform.security.PlatformSecurityContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -28,28 +27,14 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(DocumentWritePlatformServiceJpaRepositoryImpl.class);
|
||||
|
||||
// TODO: Use these services to ensure that the appropriate entities exist,
|
||||
// are active, check data scope for user etc
|
||||
private final PlatformSecurityContext context;
|
||||
// private final ClientRepository clientRepository;
|
||||
// private final OfficeRepository officeRepository;
|
||||
// private final LoanRepository loanRepository;
|
||||
// private final StaffRepository staffRepository;
|
||||
private final DocumentRepository documentRepository;
|
||||
|
||||
@Autowired
|
||||
public DocumentWritePlatformServiceJpaRepositoryImpl(
|
||||
final PlatformSecurityContext context,
|
||||
// final ClientRepository clientRepository,
|
||||
// final OfficeRepository officeRepository,
|
||||
// final LoanRepository loanRepository,
|
||||
// final StaffRepository staffRepository,
|
||||
final DocumentRepository documentRepository) {
|
||||
this.context = context;
|
||||
// this.clientRepository = clientRepository;
|
||||
// this.officeRepository = officeRepository;
|
||||
// this.loanRepository = loanRepository;
|
||||
// this.staffRepository = staffRepository;
|
||||
this.documentRepository = documentRepository;
|
||||
}
|
||||
|
||||
@@ -192,13 +177,22 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkValidEntityType(String entityType) {
|
||||
for (ApplicationConstants.DOCUMENT_MANAGEMENT_ENTITY entities : ApplicationConstants.DOCUMENT_MANAGEMENT_ENTITY
|
||||
.values()) {
|
||||
private static boolean checkValidEntityType(final String entityType) {
|
||||
|
||||
for (DOCUMENT_MANAGEMENT_ENTITY entities : DOCUMENT_MANAGEMENT_ENTITY.values()) {
|
||||
if (entities.name().equalsIgnoreCase(entityType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*** Entities for document Management **/
|
||||
public static enum DOCUMENT_MANAGEMENT_ENTITY {
|
||||
CLIENTS, CLIENT_IDENTIFIERS, STAFF, LOANS, SAVINGS;
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-10
@@ -1,15 +1,10 @@
|
||||
package org.mifosng.platform.exceptions;
|
||||
|
||||
import org.mifosng.platform.common.ApplicationConstants;
|
||||
|
||||
public class ImageNotFoundException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public ImageNotFoundException(
|
||||
ApplicationConstants.IMAGE_MANAGEMENT_ENTITY entityType,
|
||||
Long entityId) {
|
||||
super("error.msg.entity.image.invalid", "Image for entity "
|
||||
+ entityType.toString() + " with Identifier " + entityId
|
||||
+ " does not exist", entityType.toString(), entityId);
|
||||
public ImageNotFoundException(final String resource, final Long resourceId) {
|
||||
super("error.msg.entity.image.invalid", "Image for resource "
|
||||
+ resource + " with Identifier " + resourceId
|
||||
+ " does not exist", resource, resourceId);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Executable → Regular
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.mifosng.platform.common;
|
||||
package org.mifosng.platform.infrastructure;
|
||||
|
||||
public class Base64EncodedImage {
|
||||
|
||||
Executable → Regular
+7
-22
@@ -1,4 +1,4 @@
|
||||
package org.mifosng.platform.common;
|
||||
package org.mifosng.platform.infrastructure;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
@@ -14,7 +14,6 @@ import org.mifosng.platform.exceptions.DocumentManagementException;
|
||||
import org.mifosng.platform.exceptions.ImageDataURLNotValidException;
|
||||
import org.mifosng.platform.exceptions.ImageUploadException;
|
||||
import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
|
||||
import org.mifosng.platform.infrastructure.ThreadLocalContextUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -74,20 +73,14 @@ public class FileUtils {
|
||||
|
||||
/**
|
||||
* Generate directory path for storing new Image
|
||||
*
|
||||
* @param entityType
|
||||
* @param entityId
|
||||
* @return
|
||||
*/
|
||||
public static String generateImageParentDirectory(
|
||||
ApplicationConstants.IMAGE_MANAGEMENT_ENTITY entityType,
|
||||
Long entityId) {
|
||||
public static String generateClientImageParentDirectory(final Long resourceId) {
|
||||
return FileUtils.MIFOSX_BASE_DIR
|
||||
+ File.separator
|
||||
+ ThreadLocalContextUtil.getTenant().getName()
|
||||
.replaceAll(" ", "").trim() + File.separator + "images"
|
||||
+ File.separator + entityType.toString() + File.separator
|
||||
+ entityId;
|
||||
+ File.separator + "clients" + File.separator
|
||||
+ resourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,20 +198,12 @@ public class FileUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entityType
|
||||
* @param entityId
|
||||
* @param location
|
||||
*/
|
||||
public static void deleteImage(
|
||||
ApplicationConstants.IMAGE_MANAGEMENT_ENTITY entityType,
|
||||
Long entityId, String location) {
|
||||
public static void deleteClientImage(final Long resourceId, final String location) {
|
||||
File fileToBeDeleted = new File(location);
|
||||
boolean fileDeleted = fileToBeDeleted.delete();
|
||||
if (!fileDeleted) {
|
||||
// no need to throw an Error, simply log a warning
|
||||
logger.warn("Unable to delete image associated with "
|
||||
+ entityType.toString() + " with Id " + entityId);
|
||||
logger.warn("Unable to delete image associated with clients with Id " + resourceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
-2
@@ -4,8 +4,21 @@ import java.util.Collection;
|
||||
|
||||
import org.mifosng.platform.api.data.CodeValueData;
|
||||
|
||||
/**
|
||||
* A service for retrieving code value information based on the code itself.
|
||||
*
|
||||
* There are two types of code information in the platform:
|
||||
* <ol>
|
||||
* <li>System defined codes</li>
|
||||
* <li>User defined codes</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>System defined codes cannot be altered or removed but their code values may be allowed to be added to or removed.</p>
|
||||
*
|
||||
* <p>User defined codes can be changed in any way by application users with system permissions.</p>
|
||||
*/
|
||||
public interface CodeValueReadPlatformService {
|
||||
|
||||
Collection<CodeValueData> retrieveAllCodeValues(Long codeId);
|
||||
|
||||
// system defined code value data
|
||||
Collection<CodeValueData> retrieveCustomIdentifierCodeValues();
|
||||
}
|
||||
+13
-16
@@ -19,41 +19,38 @@ public class CodeValueReadPlatformServiceImpl implements CodeValueReadPlatformSe
|
||||
private final PlatformSecurityContext context;
|
||||
|
||||
@Autowired
|
||||
public CodeValueReadPlatformServiceImpl(final PlatformSecurityContext context,
|
||||
final TenantAwareRoutingDataSource dataSource) {
|
||||
public CodeValueReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource) {
|
||||
this.context = context;
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
private static final class CodeValueDataMapper implements
|
||||
RowMapper<CodeValueData> {
|
||||
private static final class CodeValueDataMapper implements RowMapper<CodeValueData> {
|
||||
|
||||
public String schema() {
|
||||
return " cv.id as id,cv.code_value as value,cv.code_id as codeId, cv.order_position as position"
|
||||
+ " from m_code_value as cv ";
|
||||
return " cv.id as id, cv.code_value as value, cv.code_id as codeId, cv.order_position as position"
|
||||
+ " from m_code_value as cv join m_code c on cv.code_id = c.id ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeValueData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum)
|
||||
throws SQLException {
|
||||
|
||||
Long id = rs.getLong("id");
|
||||
String value = rs.getString("value");
|
||||
Integer position = rs.getInt("position");
|
||||
final Long id = rs.getLong("id");
|
||||
final String value = rs.getString("value");
|
||||
final Integer position = rs.getInt("position");
|
||||
|
||||
return new CodeValueData(id, value, position);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<CodeValueData> retrieveAllCodeValues(final Long codeId) {
|
||||
public Collection<CodeValueData> retrieveCustomIdentifierCodeValues() {
|
||||
|
||||
context.authenticatedUser();
|
||||
|
||||
CodeValueDataMapper rm = new CodeValueDataMapper();
|
||||
String sql = "select " + rm.schema()
|
||||
+ "where cv.code_id = ? order by position";
|
||||
final CodeValueDataMapper rm = new CodeValueDataMapper();
|
||||
final String sql = "select " + rm.schema() + "where c.code_name like ? order by position";
|
||||
|
||||
return this.jdbcTemplate.query(sql, rm, new Object[] { codeId });
|
||||
return this.jdbcTemplate.query(sql, rm, new Object[] {"Customer Identifier"});
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user