blob: 11d82bcf3dfd274f7923dff30632d211d191e3e9 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.client.service;
import jakarta.persistence.PersistenceException;
import java.util.Map;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.fineract.infrastructure.codes.domain.CodeValue;
import org.apache.fineract.infrastructure.codes.domain.CodeValueRepositoryWrapper;
import org.apache.fineract.infrastructure.codes.exception.CodeValueNotFoundException;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
import org.apache.fineract.infrastructure.core.exception.ErrorHandler;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.client.command.ClientIdentifierCommand;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.domain.ClientIdentifier;
import org.apache.fineract.portfolio.client.domain.ClientIdentifierRepository;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.fineract.portfolio.client.exception.ClientIdentifierNotFoundException;
import org.apache.fineract.portfolio.client.exception.DuplicateClientIdentifierException;
import org.apache.fineract.portfolio.client.serialization.ClientIdentifierCommandFromApiJsonDeserializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class ClientIdentifierWritePlatformServiceJpaRepositoryImpl implements ClientIdentifierWritePlatformService {
private static final Logger LOG = LoggerFactory.getLogger(ClientIdentifierWritePlatformServiceJpaRepositoryImpl.class);
private final PlatformSecurityContext context;
private final ClientRepositoryWrapper clientRepository;
private final ClientIdentifierRepository clientIdentifierRepository;
private final CodeValueRepositoryWrapper codeValueRepository;
private final ClientIdentifierCommandFromApiJsonDeserializer clientIdentifierCommandFromApiJsonDeserializer;
@Autowired
public ClientIdentifierWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
final ClientRepositoryWrapper clientRepository, final ClientIdentifierRepository clientIdentifierRepository,
final CodeValueRepositoryWrapper codeValueRepository,
final ClientIdentifierCommandFromApiJsonDeserializer clientIdentifierCommandFromApiJsonDeserializer) {
this.context = context;
this.clientRepository = clientRepository;
this.clientIdentifierRepository = clientIdentifierRepository;
this.codeValueRepository = codeValueRepository;
this.clientIdentifierCommandFromApiJsonDeserializer = clientIdentifierCommandFromApiJsonDeserializer;
}
@Transactional
@Override
public CommandProcessingResult addClientIdentifier(final Long clientId, final JsonCommand command) {
this.context.authenticatedUser();
final ClientIdentifierCommand clientIdentifierCommand = this.clientIdentifierCommandFromApiJsonDeserializer
.commandFromApiJson(command.json());
clientIdentifierCommand.validateForCreate();
final String documentKey = clientIdentifierCommand.getDocumentKey();
String documentTypeLabel = null;
Long documentTypeId = null;
try {
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
final CodeValue documentType = this.codeValueRepository
.findOneWithNotFoundDetection(clientIdentifierCommand.getDocumentTypeId());
documentTypeId = documentType.getId();
documentTypeLabel = documentType.getLabel();
final ClientIdentifier clientIdentifier = ClientIdentifier.fromJson(client, documentType, command);
this.clientIdentifierRepository.saveAndFlush(clientIdentifier);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withOfficeId(client.officeId()) //
.withClientId(clientId) //
.withEntityId(clientIdentifier.getId()) //
.build();
} catch (final JpaSystemException | DataIntegrityViolationException dve) {
handleClientIdentifierDataIntegrityViolation(documentTypeLabel, documentTypeId, documentKey, dve.getMostSpecificCause(), dve);
return CommandProcessingResult.empty();
} catch (final PersistenceException dve) {
Throwable throwable = ExceptionUtils.getRootCause(dve.getCause());
handleClientIdentifierDataIntegrityViolation(documentTypeLabel, documentTypeId, documentKey, throwable, dve);
return CommandProcessingResult.empty();
}
}
@Transactional
@Override
public CommandProcessingResult updateClientIdentifier(final Long clientId, final Long identifierId, final JsonCommand command) {
this.context.authenticatedUser();
final ClientIdentifierCommand clientIdentifierCommand = this.clientIdentifierCommandFromApiJsonDeserializer
.commandFromApiJson(command.json());
clientIdentifierCommand.validateForUpdate();
String documentTypeLabel = null;
String documentKey = null;
Long documentTypeId = clientIdentifierCommand.getDocumentTypeId();
try {
CodeValue documentType = null;
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
final ClientIdentifier clientIdentifierForUpdate = this.clientIdentifierRepository.findById(identifierId)
.orElseThrow(() -> new ClientIdentifierNotFoundException(identifierId));
final Map<String, Object> changes = clientIdentifierForUpdate.update(command);
if (changes.containsKey("documentTypeId")) {
documentType = this.codeValueRepository.findOneWithNotFoundDetection(documentTypeId);
if (documentType == null) {
throw new CodeValueNotFoundException(documentTypeId);
}
documentTypeId = documentType.getId();
documentTypeLabel = documentType.getLabel();
clientIdentifierForUpdate.update(documentType);
}
if (changes.containsKey("documentTypeId") && changes.containsKey("documentKey")) {
documentTypeId = clientIdentifierCommand.getDocumentTypeId();
documentKey = clientIdentifierCommand.getDocumentKey();
} else if (changes.containsKey("documentTypeId") && !changes.containsKey("documentKey")) {
documentTypeId = clientIdentifierCommand.getDocumentTypeId();
documentKey = clientIdentifierForUpdate.documentKey();
} else if (!changes.containsKey("documentTypeId") && changes.containsKey("documentKey")) {
documentTypeId = clientIdentifierForUpdate.documentTypeId();
documentKey = clientIdentifierForUpdate.documentKey();
}
if (!changes.isEmpty()) {
this.clientIdentifierRepository.saveAndFlush(clientIdentifierForUpdate);
}
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withOfficeId(client.officeId()) //
.withClientId(clientId) //
.withEntityId(identifierId) //
.with(changes) //
.build();
} catch (final JpaSystemException | DataIntegrityViolationException dve) {
handleClientIdentifierDataIntegrityViolation(documentTypeLabel, documentTypeId, documentKey, dve.getMostSpecificCause(), dve);
return CommandProcessingResult.resourceResult(-1L);
} catch (final PersistenceException dve) {
Throwable throwable = ExceptionUtils.getRootCause(dve.getCause());
handleClientIdentifierDataIntegrityViolation(documentTypeLabel, documentTypeId, documentKey, throwable, dve);
return CommandProcessingResult.empty();
}
}
@Transactional
@Override
public CommandProcessingResult deleteClientIdentifier(final Long clientId, final Long identifierId, final Long commandId) {
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
final ClientIdentifier clientIdentifier = this.clientIdentifierRepository.findById(identifierId)
.orElseThrow(() -> new ClientIdentifierNotFoundException(identifierId));
this.clientIdentifierRepository.delete(clientIdentifier);
return new CommandProcessingResultBuilder() //
.withCommandId(commandId) //
.withOfficeId(client.officeId()) //
.withClientId(clientId) //
.withEntityId(identifierId) //
.build();
}
private void handleClientIdentifierDataIntegrityViolation(final String documentTypeLabel, final Long documentTypeId,
final String documentKey, final Throwable cause, final Exception dve) {
if (cause.getMessage().contains("unique_active_client_identifier")) {
throw new DuplicateClientIdentifierException(documentTypeLabel);
} else if (cause.getMessage().contains("unique_identifier_key")) {
throw new DuplicateClientIdentifierException(documentTypeId, documentTypeLabel, documentKey);
}
logAsErrorUnexpectedDataIntegrityException(dve);
throw ErrorHandler.getMappable(dve, "error.msg.clientIdentifier.unknown.data.integrity.issue",
"Unknown data integrity issue with resource.");
}
private void logAsErrorUnexpectedDataIntegrityException(final Exception dve) {
LOG.error("Error occured.", dve);
}
}