MIFOSX-60 added loan charges api methods.
This commit is contained in:
@@ -24,6 +24,7 @@ import org.apache.commons.lang.StringUtils;
|
||||
import org.mifosng.platform.api.commands.AdjustLoanTransactionCommand;
|
||||
import org.mifosng.platform.api.commands.CalculateLoanScheduleCommand;
|
||||
import org.mifosng.platform.api.commands.LoanApplicationCommand;
|
||||
import org.mifosng.platform.api.commands.LoanChargeCommand;
|
||||
import org.mifosng.platform.api.commands.LoanStateTransitionCommand;
|
||||
import org.mifosng.platform.api.commands.LoanTransactionCommand;
|
||||
import org.mifosng.platform.api.commands.UndoStateTransitionCommand;
|
||||
@@ -481,4 +482,49 @@ public class LoansApiResource {
|
||||
|
||||
return Response.ok().entity(identifier).build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{loanId}/charges")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response addLoanCharge(
|
||||
@PathParam("loanId") final Long loanId,
|
||||
final String jsonRequestBody){
|
||||
|
||||
LoanChargeCommand command = this.apiDataConversionService.convertJsonToLoanChargeCommand(null, loanId, jsonRequestBody);
|
||||
|
||||
EntityIdentifier identifier = this.loanWritePlatformService.addLoanCharge(command);
|
||||
|
||||
return Response.ok().entity(identifier).build();
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{loanId}/charges/{chargeId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response updateLoanCharge(
|
||||
@PathParam("loanId") final Long loanId,
|
||||
@PathParam("chargeId") final Long loanChargeId,
|
||||
final String jsonRequestBody){
|
||||
|
||||
LoanChargeCommand command = this.apiDataConversionService.convertJsonToLoanChargeCommand(loanChargeId, loanId, jsonRequestBody);
|
||||
|
||||
EntityIdentifier identifier = this.loanWritePlatformService.updateLoanCharge(command);
|
||||
|
||||
return Response.ok().entity(identifier).build();
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{loanId}/charges/{chargeId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response deleteLoanCharge(
|
||||
@PathParam("loanId") final Long loanId,
|
||||
@PathParam("chargeId") final Long loanChargeId){
|
||||
|
||||
EntityIdentifier identifier = this.loanWritePlatformService.deleteLoanCharge(loanId, loanChargeId);
|
||||
|
||||
return Response.ok().entity(identifier).build();
|
||||
}
|
||||
|
||||
}
|
||||
+7
-2
@@ -7,6 +7,7 @@ public class LoanChargeCommand {
|
||||
|
||||
private final Long id;
|
||||
private final Long chargeId;
|
||||
private final Long loanId;
|
||||
private final BigDecimal amount;
|
||||
|
||||
private final Integer chargeTimeType;
|
||||
@@ -14,11 +15,11 @@ public class LoanChargeCommand {
|
||||
|
||||
private final Set<String> modifiedParameters;
|
||||
|
||||
public LoanChargeCommand(final Set<String> modifiedParameters, final Long id, final Long chargeId,
|
||||
final BigDecimal amount, final Integer chargeTimeType, final Integer chargeCalculationType) {
|
||||
public LoanChargeCommand(Set<String> modifiedParameters, Long id, Long loanId, Long chargeId, BigDecimal amount, Integer chargeTimeType, Integer chargeCalculationType) {
|
||||
this.modifiedParameters = modifiedParameters;
|
||||
this.id = id;
|
||||
this.chargeId = chargeId;
|
||||
this.loanId = loanId;
|
||||
this.amount = amount;
|
||||
this.chargeTimeType = chargeTimeType;
|
||||
this.chargeCalculationType = chargeCalculationType;
|
||||
@@ -32,6 +33,10 @@ public class LoanChargeCommand {
|
||||
return chargeId;
|
||||
}
|
||||
|
||||
public Long getLoanId() {
|
||||
return loanId;
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
+3
@@ -11,6 +11,7 @@ import org.mifosng.platform.api.commands.DepositStateTransitionApprovalCommand;
|
||||
import org.mifosng.platform.api.commands.DepositStateTransitionCommand;
|
||||
import org.mifosng.platform.api.commands.FundCommand;
|
||||
import org.mifosng.platform.api.commands.GroupCommand;
|
||||
import org.mifosng.platform.api.commands.LoanChargeCommand;
|
||||
import org.mifosng.platform.api.commands.LoanProductCommand;
|
||||
import org.mifosng.platform.api.commands.LoanStateTransitionCommand;
|
||||
import org.mifosng.platform.api.commands.LoanTransactionCommand;
|
||||
@@ -49,6 +50,8 @@ public interface ApiDataConversionService {
|
||||
|
||||
LoanApplicationCommand convertJsonToLoanApplicationCommand(Long resourceIdentifier, String jsonRequestBody);
|
||||
|
||||
LoanChargeCommand convertJsonToLoanChargeCommand(Long loanChargeId, Long loanId, String jsonRequestBody);
|
||||
|
||||
LoanStateTransitionCommand convertJsonToLoanStateTransitionCommand(Long resourceIdentifier, String jsonRequestBody);
|
||||
|
||||
LoanTransactionCommand convertJsonToLoanTransactionCommand(Long resourceIdentifier, String jsonRequestBody);
|
||||
|
||||
+29
-3
@@ -506,7 +506,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
|
||||
Integer chargeTimeType = extractIntegerParameter("chargeTimeType", chargeRequestMap, chargeModifiedParameters);
|
||||
Integer chargeCalculationType = extractIntegerParameter("chargeCalculationType", chargeRequestMap, chargeModifiedParameters);
|
||||
|
||||
charges[i] = new LoanChargeCommand(chargeModifiedParameters, null, chargeId, amount,
|
||||
charges[i] = new LoanChargeCommand(chargeModifiedParameters, null, null,chargeId, amount,
|
||||
chargeTimeType, chargeCalculationType);
|
||||
}
|
||||
}
|
||||
@@ -521,8 +521,34 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
|
||||
loanTermFrequency, loanTermFrequencyType,
|
||||
inArrearsToleranceValue, charges,loanOfficerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@Override
|
||||
public LoanChargeCommand convertJsonToLoanChargeCommand(Long loanChargeId, Long loanId, String json) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
|
||||
Type typeOfMap = new TypeToken<Map<String, String>>(){}.getType();
|
||||
Map<String, String> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
||||
|
||||
Set<String> supportedParams = new HashSet<String>(
|
||||
Arrays.asList("chargeId", "amount", "chargeTimeType", "chargeCalculationType", "locale")
|
||||
);
|
||||
|
||||
checkForUnsupportedParameters(requestMap, supportedParams);
|
||||
|
||||
Set<String> modifiedParameters = new HashSet<String>();
|
||||
|
||||
Long chargeId = extractLongParameter("chargeId", requestMap, modifiedParameters);
|
||||
BigDecimal amount = extractBigDecimalParameter("amount", requestMap, modifiedParameters);
|
||||
Integer chargeTimeType = extractIntegerParameter("chargeTimeType", requestMap, modifiedParameters);
|
||||
Integer chargeCalculationType = extractIntegerParameter("chargeCalculationType", requestMap, modifiedParameters);
|
||||
|
||||
return new LoanChargeCommand(modifiedParameters, loanChargeId, loanId, chargeId, amount,
|
||||
chargeTimeType, chargeCalculationType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoanStateTransitionCommand convertJsonToLoanStateTransitionCommand(final Long resourceIdentifier, final String json) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
throw new InvalidJsonException();
|
||||
|
||||
@@ -577,6 +577,10 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
doPostLoanTransactionChecks(loanTransaction, loanLifecycleStateMachine);
|
||||
}
|
||||
|
||||
public void updateTotalChargesDueAtDisbursement(){
|
||||
this.totalChargesDueAtDisbursement = deriveSumTotalOfChargesDueAtDisbursement();
|
||||
}
|
||||
|
||||
public void makeRepayment(final LoanTransaction loanTransaction, final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
||||
handleRepaymentTransaction(loanTransaction, loanLifecycleStateMachine, false);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,11 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
|
||||
@Column(name = "charge_calculation_enum")
|
||||
private Integer chargeCalculation;
|
||||
|
||||
|
||||
public static LoanCharge createNew(final Loan loan, final Charge chargeDefinition, final LoanChargeCommand command) {
|
||||
return new LoanCharge(loan, chargeDefinition, command);
|
||||
}
|
||||
|
||||
public static LoanCharge createNew(final Charge chargeDefinition, final LoanChargeCommand command) {
|
||||
return new LoanCharge(null, chargeDefinition, command);
|
||||
}
|
||||
@@ -90,6 +94,22 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
this.loan = loan;
|
||||
}
|
||||
|
||||
public void update(final LoanChargeCommand command){
|
||||
|
||||
if (command.isAmountChanged()) {
|
||||
this.amount = command.getAmount();
|
||||
}
|
||||
|
||||
if (command.isChargeTimeTypeChanged()){
|
||||
this.chargeTime = ChargeTimeType.fromInt(command.getChargeTimeType()).getValue();
|
||||
}
|
||||
|
||||
if (command.isChargeCalculationTypeChanged()){
|
||||
this.chargeCalculation = ChargeCalculationType.fromInt(command.getChargeCalculationType()).getValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean isDueAtDisbursement() {
|
||||
return ChargeTimeType.fromInt(this.chargeTime).equals(ChargeTimeType.DISBURSEMENT);
|
||||
}
|
||||
@@ -122,6 +142,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
|
||||
public LoanChargeCommand toData() {
|
||||
Set<String> modifiedParameters = new HashSet<String>();
|
||||
return new LoanChargeCommand(modifiedParameters, this.getId(), this.charge.getId(), this.amount, this.chargeTime, this.chargeCalculation);
|
||||
return new LoanChargeCommand(modifiedParameters, this.getId(), this.loan.getId(), this.charge.getId(),
|
||||
this.amount, this.chargeTime, this.chargeCalculation);
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package org.mifosng.platform.loan.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface LoanChargeRepository extends JpaRepository<LoanCharge, Long>, JpaSpecificationExecutor<LoanCharge> {
|
||||
// no added behaviour
|
||||
}
|
||||
+1
-1
@@ -58,7 +58,7 @@ public class LoanApplicationCommandValidator {
|
||||
for (LoanChargeCommand loanChargeCommand : this.command.getCharges()){
|
||||
try {
|
||||
LoanChargeCommandValidator validator = new LoanChargeCommandValidator(loanChargeCommand);
|
||||
validator.validate();
|
||||
validator.validateForCreate();
|
||||
} catch (PlatformApiDataValidationException e) {
|
||||
dataValidationErrors.addAll(e.getErrors());
|
||||
}
|
||||
|
||||
+15
-1
@@ -17,7 +17,7 @@ public class LoanChargeCommandValidator {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public void validate(){
|
||||
public void validateForCreate(){
|
||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
|
||||
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charge");
|
||||
@@ -31,4 +31,18 @@ public class LoanChargeCommandValidator {
|
||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
public void validateForUpdate(){
|
||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
|
||||
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charge");
|
||||
|
||||
baseDataValidator.reset().parameter("amount").value(command.getAmount()).ignoreIfNull().positiveAmount();
|
||||
baseDataValidator.reset().parameter("chargeTimeType").value(command.getChargeTimeType()).ignoreIfNull().inMinMaxRange(1, 1);
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(command.getChargeCalculationType()).ignoreIfNull().inMinMaxRange(1, 4);
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -1,6 +1,7 @@
|
||||
package org.mifosng.platform.loan.service;
|
||||
|
||||
import org.mifosng.platform.api.commands.AdjustLoanTransactionCommand;
|
||||
import org.mifosng.platform.api.commands.LoanChargeCommand;
|
||||
import org.mifosng.platform.api.commands.LoanStateTransitionCommand;
|
||||
import org.mifosng.platform.api.commands.LoanTransactionCommand;
|
||||
import org.mifosng.platform.api.commands.LoanApplicationCommand;
|
||||
@@ -45,4 +46,13 @@ public interface LoanWritePlatformService {
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE')")
|
||||
EntityIdentifier waiveLoanAmount(LoanTransactionCommand command);
|
||||
|
||||
@PreAuthorize(value = "hasRole('ORGANISATION_ADMINISTRATION_SUPER_USER_ROLE')")
|
||||
EntityIdentifier addLoanCharge(LoanChargeCommand command);
|
||||
|
||||
@PreAuthorize(value = "hasRole('ORGANISATION_ADMINISTRATION_SUPER_USER_ROLE')")
|
||||
EntityIdentifier updateLoanCharge(LoanChargeCommand command);
|
||||
|
||||
@PreAuthorize(value = "hasRole('ORGANISATION_ADMINISTRATION_SUPER_USER_ROLE')")
|
||||
EntityIdentifier deleteLoanCharge(final Long loanId, final Long loanChargeId);
|
||||
}
|
||||
+97
-1
@@ -18,12 +18,17 @@ import org.mifosng.platform.api.commands.LoanTransactionCommand;
|
||||
import org.mifosng.platform.api.commands.UndoStateTransitionCommand;
|
||||
import org.mifosng.platform.api.data.EntityIdentifier;
|
||||
import org.mifosng.platform.api.data.LoanSchedulePeriodData;
|
||||
import org.mifosng.platform.charge.domain.Charge;
|
||||
import org.mifosng.platform.charge.domain.ChargeRepository;
|
||||
import org.mifosng.platform.client.domain.Client;
|
||||
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.currency.domain.Money;
|
||||
import org.mifosng.platform.exceptions.ChargeIsNotActiveException;
|
||||
import org.mifosng.platform.exceptions.ChargeNotFoundException;
|
||||
import org.mifosng.platform.exceptions.ClientNotFoundException;
|
||||
import org.mifosng.platform.exceptions.InvalidCurrencyException;
|
||||
import org.mifosng.platform.exceptions.LoanNotFoundException;
|
||||
import org.mifosng.platform.exceptions.LoanNotInSubmittedAndPendingApprovalStateCannotBeDeleted;
|
||||
import org.mifosng.platform.exceptions.LoanProductNotFoundException;
|
||||
@@ -33,6 +38,7 @@ import org.mifosng.platform.fund.domain.Fund;
|
||||
import org.mifosng.platform.loan.domain.DefaultLoanLifecycleStateMachine;
|
||||
import org.mifosng.platform.loan.domain.Loan;
|
||||
import org.mifosng.platform.loan.domain.LoanCharge;
|
||||
import org.mifosng.platform.loan.domain.LoanChargeRepository;
|
||||
import org.mifosng.platform.loan.domain.LoanLifecycleStateMachine;
|
||||
import org.mifosng.platform.loan.domain.LoanProduct;
|
||||
import org.mifosng.platform.loan.domain.LoanProductRepository;
|
||||
@@ -62,12 +68,15 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
private final LoanAssembler loanAssembler;
|
||||
private final ClientRepository clientRepository;
|
||||
private final LoanProductRepository loanProductRepository;
|
||||
private final ChargeRepository chargeRepository;
|
||||
private final LoanChargeRepository loanChargeRepository;
|
||||
|
||||
@Autowired
|
||||
public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final LoanAssembler loanAssembler,
|
||||
final LoanRepository loanRepository, final LoanTransactionRepository loanTransactionRepository,
|
||||
final NoteRepository noteRepository, final CalculationPlatformService calculationPlatformService,
|
||||
final ClientRepository clientRepository, final LoanProductRepository loanProductRepository) {
|
||||
final ClientRepository clientRepository, final LoanProductRepository loanProductRepository,
|
||||
final ChargeRepository chargeRepository, final LoanChargeRepository loanChargeRepository) {
|
||||
this.context = context;
|
||||
this.loanAssembler = loanAssembler;
|
||||
this.loanRepository = loanRepository;
|
||||
@@ -76,6 +85,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.calculationPlatformService = calculationPlatformService;
|
||||
this.clientRepository = clientRepository;
|
||||
this.loanProductRepository = loanProductRepository;
|
||||
this.chargeRepository = chargeRepository;
|
||||
this.loanChargeRepository = loanChargeRepository;
|
||||
}
|
||||
|
||||
private boolean isBeforeToday(final LocalDate date) {
|
||||
@@ -533,4 +544,89 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
return new EntityIdentifier(loan.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityIdentifier addLoanCharge(LoanChargeCommand command) {
|
||||
this.context.authenticatedUser();
|
||||
|
||||
LoanChargeCommandValidator validator = new LoanChargeCommandValidator(command);
|
||||
validator.validateForCreate();
|
||||
|
||||
Loan loan = this.loanRepository.findOne(command.getLoanId());
|
||||
if (loan == null) {
|
||||
throw new LoanNotFoundException(command.getLoanId());
|
||||
}
|
||||
|
||||
Charge chargeDefinition = this.chargeRepository.findOne(command.getChargeId());
|
||||
if (chargeDefinition == null) {
|
||||
throw new ChargeNotFoundException(command.getChargeId());
|
||||
}
|
||||
|
||||
LoanCharge loanCharge = LoanCharge.createNew(loan, chargeDefinition, command);
|
||||
|
||||
if (!chargeDefinition.isActive()) {
|
||||
throw new ChargeIsNotActiveException(chargeDefinition.getId());
|
||||
}
|
||||
|
||||
if (!loan.getCurrency().getCode().equals(chargeDefinition.getCurrencyCode())){
|
||||
String errorMessage = "Charge and Loan must have the same currency.";
|
||||
throw new InvalidCurrencyException("charge", "attach.to.loan", errorMessage);
|
||||
}
|
||||
|
||||
this.loanChargeRepository.saveAndFlush(loanCharge);
|
||||
|
||||
loan.getCharges().add(loanCharge);
|
||||
loan.updateTotalChargesDueAtDisbursement();
|
||||
|
||||
this.loanRepository.saveAndFlush(loan);
|
||||
|
||||
return new EntityIdentifier(loanCharge.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityIdentifier updateLoanCharge(LoanChargeCommand command) {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
LoanChargeCommandValidator validator = new LoanChargeCommandValidator(command);
|
||||
validator.validateForUpdate();
|
||||
|
||||
Loan loan = this.loanRepository.findOne(command.getLoanId());
|
||||
if (loan == null) {
|
||||
throw new LoanNotFoundException(command.getLoanId());
|
||||
}
|
||||
|
||||
for (LoanCharge loanCharge : loan.getCharges()){
|
||||
if (loanCharge.getId().equals(command.getId())){
|
||||
loanCharge.update(command);
|
||||
loan.updateTotalChargesDueAtDisbursement();
|
||||
this.loanRepository.saveAndFlush(loan);
|
||||
return new EntityIdentifier(loanCharge.getId());
|
||||
}
|
||||
}
|
||||
|
||||
throw new ChargeNotFoundException(command.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityIdentifier deleteLoanCharge(Long loanId, Long loanChargeId) {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
Loan loan = this.loanRepository.findOne(loanId);
|
||||
if (loan == null) {
|
||||
throw new LoanNotFoundException(loanId);
|
||||
}
|
||||
|
||||
for (LoanCharge loanCharge : loan.getCharges()){
|
||||
if (loanCharge.getId().equals(loanChargeId)){
|
||||
loan.getCharges().remove(loanCharge);
|
||||
loan.updateTotalChargesDueAtDisbursement();
|
||||
this.loanRepository.saveAndFlush(loan);
|
||||
return new EntityIdentifier(loanCharge.getId());
|
||||
}
|
||||
}
|
||||
|
||||
throw new ChargeNotFoundException(loanChargeId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user