blob: f799f211199d77ebf442a195fef30ad2780face0 [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.collateral.service;
import java.util.Map;
import org.apache.fineract.infrastructure.codes.domain.CodeValue;
import org.apache.fineract.infrastructure.codes.domain.CodeValueRepositoryWrapper;
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.PlatformDataIntegrityException;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.collateral.api.CollateralApiConstants;
import org.apache.fineract.portfolio.collateral.api.CollateralApiConstants.COLLATERAL_JSON_INPUT_PARAMS;
import org.apache.fineract.portfolio.collateral.command.CollateralCommand;
import org.apache.fineract.portfolio.collateral.domain.LoanCollateral;
import org.apache.fineract.portfolio.collateral.domain.LoanCollateralRepository;
import org.apache.fineract.portfolio.collateral.exception.CollateralCannotBeCreatedException;
import org.apache.fineract.portfolio.collateral.exception.CollateralCannotBeDeletedException;
import org.apache.fineract.portfolio.collateral.exception.CollateralCannotBeUpdatedException;
import org.apache.fineract.portfolio.collateral.exception.CollateralNotFoundException;
import org.apache.fineract.portfolio.collateral.exception.CollateralCannotBeCreatedException.LOAN_COLLATERAL_CANNOT_BE_CREATED_REASON;
import org.apache.fineract.portfolio.collateral.exception.CollateralCannotBeDeletedException.LOAN_COLLATERAL_CANNOT_BE_DELETED_REASON;
import org.apache.fineract.portfolio.collateral.exception.CollateralCannotBeUpdatedException.LOAN_COLLATERAL_CANNOT_BE_UPDATED_REASON;
import org.apache.fineract.portfolio.collateral.serialization.CollateralCommandFromApiJsonDeserializer;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class CollateralWritePlatformServiceJpaRepositoryImpl implements CollateralWritePlatformService {
private final static Logger logger = LoggerFactory.getLogger(CollateralWritePlatformServiceJpaRepositoryImpl.class);
private final PlatformSecurityContext context;
private final LoanRepository loanRepository;
private final LoanCollateralRepository collateralRepository;
private final CodeValueRepositoryWrapper codeValueRepository;
private final CollateralCommandFromApiJsonDeserializer collateralCommandFromApiJsonDeserializer;
@Autowired
public CollateralWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final LoanRepository loanRepository,
final LoanCollateralRepository collateralRepository, final CodeValueRepositoryWrapper codeValueRepository,
final CollateralCommandFromApiJsonDeserializer collateralCommandFromApiJsonDeserializer) {
this.context = context;
this.loanRepository = loanRepository;
this.collateralRepository = collateralRepository;
this.codeValueRepository = codeValueRepository;
this.collateralCommandFromApiJsonDeserializer = collateralCommandFromApiJsonDeserializer;
}
@Transactional
@Override
public CommandProcessingResult addCollateral(final Long loanId, final JsonCommand command) {
this.context.authenticatedUser();
final CollateralCommand collateralCommand = this.collateralCommandFromApiJsonDeserializer.commandFromApiJson(command.json());
collateralCommand.validateForCreate();
try {
final Loan loan = this.loanRepository.findOne(loanId);
if (loan == null) { throw new LoanNotFoundException(loanId); }
final CodeValue collateralType = this.codeValueRepository.findOneByCodeNameAndIdWithNotFoundDetection(
CollateralApiConstants.COLLATERAL_CODE_NAME, collateralCommand.getCollateralTypeId());
final LoanCollateral collateral = LoanCollateral.fromJson(loan, collateralType, command);
/**
* Collaterals may be added only when the loan associated with them
* are yet to be approved
**/
if (!loan.status().isSubmittedAndPendingApproval()) { throw new CollateralCannotBeCreatedException(
LOAN_COLLATERAL_CANNOT_BE_CREATED_REASON.LOAN_NOT_IN_SUBMITTED_AND_PENDING_APPROVAL_STAGE, loan.getId()); }
this.collateralRepository.save(collateral);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withLoanId(loan.getId())//
.withEntityId(collateral.getId()) //
.build();
} catch (final DataIntegrityViolationException dve) {
handleCollateralDataIntegrityViolation(dve);
return CommandProcessingResult.empty();
}
}
@Transactional
@Override
public CommandProcessingResult updateCollateral(final Long loanId, final Long collateralId, final JsonCommand command) {
this.context.authenticatedUser();
final CollateralCommand collateralCommand = this.collateralCommandFromApiJsonDeserializer.commandFromApiJson(command.json());
collateralCommand.validateForUpdate();
final Long collateralTypeId = collateralCommand.getCollateralTypeId();
try {
final Loan loan = this.loanRepository.findOne(loanId);
if (loan == null) { throw new LoanNotFoundException(loanId); }
CodeValue collateralType = null;
final LoanCollateral collateralForUpdate = this.collateralRepository.findOne(collateralId);
if (collateralForUpdate == null) { throw new CollateralNotFoundException(loanId, collateralId); }
final Map<String, Object> changes = collateralForUpdate.update(command);
if (changes.containsKey(COLLATERAL_JSON_INPUT_PARAMS.COLLATERAL_TYPE_ID.getValue())) {
collateralType = this.codeValueRepository.findOneByCodeNameAndIdWithNotFoundDetection(
CollateralApiConstants.COLLATERAL_CODE_NAME, collateralTypeId);
collateralForUpdate.setCollateralType(collateralType);
}
/**
* Collaterals may be updated only when the loan associated with
* them are yet to be approved
**/
if (!loan.status().isSubmittedAndPendingApproval()) { throw new CollateralCannotBeUpdatedException(
LOAN_COLLATERAL_CANNOT_BE_UPDATED_REASON.LOAN_NOT_IN_SUBMITTED_AND_PENDING_APPROVAL_STAGE, loan.getId()); }
if (!changes.isEmpty()) {
this.collateralRepository.saveAndFlush(collateralForUpdate);
}
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withLoanId(command.getLoanId())//
.withEntityId(collateralId) //
.with(changes) //
.build();
} catch (final DataIntegrityViolationException dve) {
handleCollateralDataIntegrityViolation(dve);
return new CommandProcessingResult(Long.valueOf(-1));
}
}
@Transactional
@Override
public CommandProcessingResult deleteCollateral(final Long loanId, final Long collateralId, final Long commandId) {
final Loan loan = this.loanRepository.findOne(loanId);
if (loan == null) { throw new LoanNotFoundException(loanId); }
final LoanCollateral collateral = this.collateralRepository.findByLoanIdAndId(loanId, collateralId);
if (collateral == null) { throw new CollateralNotFoundException(loanId, collateralId); }
/**
* Collaterals may be deleted only when the loan associated with them
* are yet to be approved
**/
if (!loan.status().isSubmittedAndPendingApproval()) { throw new CollateralCannotBeDeletedException(
LOAN_COLLATERAL_CANNOT_BE_DELETED_REASON.LOAN_NOT_IN_SUBMITTED_AND_PENDING_APPROVAL_STAGE, loanId, collateralId); }
loan.getCollateral().remove(collateral);
this.collateralRepository.delete(collateral);
return new CommandProcessingResultBuilder().withCommandId(commandId).withLoanId(loanId).withEntityId(collateralId).build();
}
private void handleCollateralDataIntegrityViolation(final DataIntegrityViolationException dve) {
logAsErrorUnexpectedDataIntegrityException(dve);
throw new PlatformDataIntegrityException("error.msg.collateral.unknown.data.integrity.issue",
"Unknown data integrity issue with resource.");
}
private void logAsErrorUnexpectedDataIntegrityException(final DataIntegrityViolationException dve) {
logger.error(dve.getMessage(), dve);
}
}