From 141108ec8747cb5f3ad359af4d3aa3082f21e8ed Mon Sep 17 00:00:00 2001 From: BLasan Date: Tue, 31 Aug 2021 15:51:21 +0530 Subject: [PATCH] Feat: Collateral Module --- .../service/CommandWrapperBuilder.java | 59 +++ .../bulkimport/constants/LoanConstants.java | 2 + .../importhandler/loan/LoanImportHandler.java | 21 +- .../monetary/domain/ApplicationCurrency.java | 16 + .../data/ClientCollateralManagementData.java | 82 ++++ .../portfolio/client/data/ClientData.java | 34 +- .../portfolio/client/domain/Client.java | 6 + .../ClientReadPlatformServiceImpl.java | 26 +- .../api/CollateralsApiResource.java | 1 - .../api/CollateralsApiResourceSwagger.java | 2 - ...ClientCollateralManagementApiResource.java | 199 ++++++++++ ...ollateralManagementApiResourceSwagger.java | 155 ++++++++ .../api/CollateralManagementApiResource.java | 188 ++++++++++ ...ollateralManagementApiResourceSwagger.java | 159 ++++++++ .../CollateralManagementJsonInputParams.java | 42 +++ .../LoanCollateralManagementApiResources.java | 94 +++++ .../data/ClientCollateralManagementData.java | 84 +++++ .../data/CollateralManagementData.java | 58 +++ .../data/LoanCollateralResponseData.java | 56 +++ .../data/LoanCollateralTemplateData.java | 51 +++ .../data/LoanTransactionData.java | 46 +++ .../domain/ClientCollateralManagement.java | 137 +++++++ .../ClientCollateralManagementRepository.java | 33 ++ ...CollateralManagementRepositoryWrapper.java | 98 +++++ .../domain/CollateralManagementDomain.java | 160 ++++++++ .../CollateralManagementDomainRepository.java | 27 ++ ...CollateralManagementRepositoryWrapper.java | 56 +++ ...entCollateralCannotBeDeletedException.java | 49 +++ .../ClientCollateralNotFoundException.java | 29 ++ .../CollateralCannotBeDeletedException.java | 49 +++ .../CollateralNotFoundException.java | 28 ++ ...ollateralAmountNotSufficientException.java | 31 ++ ...CollateralManagementNotFoundException.java | 29 ++ ...ClientCollateralProductCommandHandler.java | 47 +++ ...CreateCollateralProductCommandHandler.java | 46 +++ ...ClientCollateralProductCommandHandler.java | 47 +++ .../DeleteCollateralProductHandler.java | 46 +++ .../DeleteLoanCollateralManagement.java | 46 +++ ...ClientCollateralProductCommandHandler.java | 47 +++ ...UpdateCollateralProductCommandHandler.java | 47 +++ ...agementCommandFromApiJsonDeserializer.java | 33 ++ ...llateralManagementReadPlatformService.java | 33 ++ ...eralManagementReadPlatformServiceImpl.java | 104 ++++++ ...lateralManagementWritePlatformService.java | 32 ++ ...ralManagementWritePlatformServiceImpl.java | 181 +++++++++ ...llateralManagementReadPlatformService.java | 30 ++ ...eralManagementReadPlatformServiceImpl.java | 61 +++ ...lateralManagementWritePlatformService.java | 31 ++ ...ralManagementWritePlatformServiceImpl.java | 176 +++++++++ .../service/LoanCollateralAssembler.java | 106 ++++++ ...llateralManagementReadPlatformService.java | 32 ++ ...eralManagementReadPlatformServiceImpl.java | 90 +++++ ...lateralManagementWritePlatformService.java | 27 ++ ...ralManagementWritePlatformServiceImpl.java | 60 +++ .../loanaccount/api/LoanApiConstants.java | 1 + .../loanaccount/api/LoansApiResource.java | 31 +- .../loanaccount/data/LoanAccountData.java | 35 +- .../data/LoanCollateralManagementData.java | 60 +++ .../portfolio/loanaccount/domain/Loan.java | 76 ++-- .../domain/LoanAccountDomainService.java | 5 + .../domain/LoanAccountDomainServiceJpa.java | 24 +- .../domain/LoanCollateralManagement.java | 124 +++++++ .../LoanCollateralManagementRepository.java | 32 ++ .../loanaccount/domain/LoanTransaction.java | 7 + .../InvalidAmountOfCollateralQuantity.java | 36 ++ .../exception/InvalidAmountOfCollaterals.java | 35 ++ ...anApplicationCommandFromApiJsonHelper.java | 171 ++++++--- ...WritePlatformServiceJpaRepositoryImpl.java | 71 +++- .../loanaccount/service/LoanAssembler.java | 59 ++- ...WritePlatformServiceJpaRepositoryImpl.java | 80 +++- ...27__add-loan-type-column-to-loan-table.sql | 45 +++ .../core_db/V368__collateral_management.sql | 73 ++++ .../AccountNumberPreferencesTest.java | 30 +- .../integrationtests/AccountTransferTest.java | 24 +- .../AccountingScenarioIntegrationTest.java | 88 ++++- .../AuditIntegrationTest.java | 4 +- .../integrationtests/BatchApiTest.java | 57 ++- .../BatchRequestsIntegrationTest.java | 10 +- .../ClientCollateralIntegrationTest.java | 78 ++++ .../ClientLoanIntegrationTest.java | 350 +++++++++++++++--- .../ClientSavingsIntegrationTest.java | 56 ++- .../fineract/integrationtests/ClientTest.java | 10 +- ...ndoRejectAndWithdrawalIntegrationTest.java | 3 +- .../CollateralProductIntegrationTest.java | 67 ++++ .../ConcurrencyIntegrationTest.java | 26 +- .../GroupLoanIntegrationTest.java | 25 +- .../GroupSavingsIntegrationTest.java | 23 +- .../fineract/integrationtests/GroupTest.java | 28 +- .../LoanApplicationApprovalTest.java | 34 +- .../LoanApplicationUndoLastTrancheTest.java | 22 +- .../LoanDisbursalDateValidationTest.java | 24 +- ...oanDisbursementDetailsIntegrationTest.java | 33 +- ...RepaymentRescheduleAtDisbursementTest.java | 34 +- ...nRescheduleOnDecliningBalanceLoanTest.java | 26 +- .../LoanRescheduleRequestTest.java | 26 +- .../LoanReschedulingWithinCenterTest.java | 45 ++- ...iveInterestAndWriteOffIntegrationTest.java | 24 +- ...anWithdrawnByApplicantIntegrationTest.java | 26 +- ...BetweenDisbursalAndFirstRepaymentTest.java | 34 +- .../fineract/integrationtests/NotesTest.java | 26 +- .../SchedulerJobsTestResults.java | 24 +- .../SkipRepaymentOnMonthFirstTest.java | 25 +- .../loan/LoanImportHandlerTest.java | 16 + .../integrationtests/common/BatchHelper.java | 16 +- .../common/CollateralManagementHelper.java | 159 ++++++++ .../common/ProvisioningIntegrationTest.java | 26 +- .../common/SchedulerJobHelper.java | 4 +- .../loans/LoanApplicationTestBuilder.java | 9 + .../EntityDatatableChecksIntegrationTest.java | 32 +- .../guarantor/GuarantorTest.java | 24 +- ...bleInstallmentsDecliningBalanceHelper.java | 8 +- .../VariableInstallmentsFlatHelper.java | 4 +- .../VariableInstallmentsIntegrationTest.java | 131 ++++++- 113 files changed, 5780 insertions(+), 325 deletions(-) create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientCollateralManagementData.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/ClientCollateralManagementApiResource.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/ClientCollateralManagementApiResourceSwagger.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/CollateralManagementApiResource.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/CollateralManagementApiResourceSwagger.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/CollateralManagementJsonInputParams.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/LoanCollateralManagementApiResources.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/ClientCollateralManagementData.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/CollateralManagementData.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/LoanCollateralResponseData.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/LoanCollateralTemplateData.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/LoanTransactionData.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/ClientCollateralManagement.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/ClientCollateralManagementRepository.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/ClientCollateralManagementRepositoryWrapper.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/CollateralManagementDomain.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/CollateralManagementDomainRepository.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/CollateralManagementRepositoryWrapper.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/ClientCollateralCannotBeDeletedException.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/ClientCollateralNotFoundException.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/CollateralCannotBeDeletedException.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/CollateralNotFoundException.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/LoanCollateralAmountNotSufficientException.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/LoanCollateralManagementNotFoundException.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/AddClientCollateralProductCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/CreateCollateralProductCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/DeleteClientCollateralProductCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/DeleteCollateralProductHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/DeleteLoanCollateralManagement.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/UpdateClientCollateralProductCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/UpdateCollateralProductCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/serialization/CollateralManagementCommandFromApiJsonDeserializer.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementReadPlatformService.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementReadPlatformServiceImpl.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementWritePlatformService.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementWritePlatformServiceImpl.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/CollateralManagementReadPlatformService.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/CollateralManagementReadPlatformServiceImpl.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/CollateralManagementWritePlatformService.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/CollateralManagementWritePlatformServiceImpl.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralAssembler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralManagementReadPlatformService.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralManagementReadPlatformServiceImpl.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralManagementWritePlatformService.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralManagementWritePlatformServiceImpl.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanCollateralManagementData.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCollateralManagement.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCollateralManagementRepository.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/exception/InvalidAmountOfCollateralQuantity.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/exception/InvalidAmountOfCollaterals.java create mode 100644 fineract-provider/src/main/resources/sql/migrations/core_db/V368__collateral_management.sql create mode 100644 integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientCollateralIntegrationTest.java create mode 100644 integration-tests/src/test/java/org/apache/fineract/integrationtests/CollateralProductIntegrationTest.java create mode 100644 integration-tests/src/test/java/org/apache/fineract/integrationtests/common/CollateralManagementHelper.java diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java index 29f6dd64a..09fc225ef 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java +++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java @@ -482,6 +482,14 @@ public class CommandWrapperBuilder { return this; } + public CommandWrapperBuilder createCollateral() { + this.actionName = "CREATE"; + this.entityId = null; + this.entityName = "COLLATERAL_PRODUCT"; + this.href = "/collateral-product"; + return this; + } + public CommandWrapperBuilder updateCharge(final Long chargeId) { this.actionName = "UPDATE"; this.entityName = "CHARGE"; @@ -1814,6 +1822,32 @@ public class CommandWrapperBuilder { return this; } + public CommandWrapperBuilder updateCollateralProduct(final Long collateralId) { + this.actionName = "UPDATE"; + this.entityName = "COLLATERAL_PRODUCT"; + this.entityId = collateralId; + this.href = "/collateral-management/" + collateralId; + return this; + } + + public CommandWrapperBuilder updateClientCollateralProduct(final Long clientId, final Long collateralId) { + this.actionName = "UPDATE"; + this.entityName = "CLIENT_COLLATERAL_PRODUCT"; + this.entityId = collateralId; + this.clientId = clientId; + this.href = "/clients/" + clientId + "/collateral/" + collateralId; + return this; + } + + public CommandWrapperBuilder deleteLoanCollateral(final Long loanId, final Long collateralId) { + this.actionName = "DELETE"; + this.entityName = "LOAN_COLLATERAL_PRODUCT"; + this.entityId = collateralId; + this.loanId = loanId; + this.href = "/loans/" + loanId + "/collateral/" + collateralId; + return this; + } + public CommandWrapperBuilder deleteCollateral(final Long loanId, final Long collateralId) { this.actionName = "DELETE"; this.entityName = "COLLATERAL"; @@ -1823,6 +1857,31 @@ public class CommandWrapperBuilder { return this; } + public CommandWrapperBuilder deleteCollateralProduct(final Long collateralId) { + this.actionName = "DELETE"; + this.entityName = "COLLATERAL_PRODUCT"; + this.entityId = collateralId; + this.href = "/collateral-management/" + collateralId; + return this; + } + + public CommandWrapperBuilder deleteClientCollateralProduct(final Long collateralId, final Long clientId) { + this.actionName = "DELETE"; + this.entityName = "CLIENT_COLLATERAL_PRODUCT"; + this.entityId = collateralId; + this.clientId = clientId; + this.href = "/clients/" + clientId + "/collateral-management/" + collateralId; + return this; + } + + public CommandWrapperBuilder addClientCollateralProduct(final Long clientId) { + this.actionName = "CREATE"; + this.entityName = "CLIENT_COLLATERAL_PRODUCT"; + this.clientId = clientId; + this.href = "/clients/" + clientId + "/collateral-management"; + return this; + } + public CommandWrapperBuilder updateCollectionSheet(final Long groupId) { this.actionName = "UPDATE"; this.entityName = "COLLECTIONSHEET"; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/LoanConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/LoanConstants.java index b1996c4ed..474f5d160 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/LoanConstants.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/LoanConstants.java @@ -71,6 +71,8 @@ public final class LoanConstants { public static final int LOOKUP_CLIENT_EXTERNAL_ID = 44;// AS public static final int LOOKUP_ACTIVATION_DATE_COL = 45;// AT public static final int LINK_ACCOUNT_ID = 46;// AU + public static final int LOAN_COLLATERAL_ID = 47; + public static final int LOAN_COLLATERAL_QUANTITY = 48; public static final String LOAN_TYPE_INDIVIDUAL = "Individual"; public static final String LOAN_TYPE_GROUP = "Group"; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java index 2525331d7..17d4b0b7d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/loan/LoanImportHandler.java @@ -43,7 +43,9 @@ import org.apache.fineract.portfolio.loanaccount.data.DisbursementData; import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData; import org.apache.fineract.portfolio.loanaccount.data.LoanApprovalData; import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData; +import org.apache.fineract.portfolio.loanaccount.data.LoanCollateralManagementData; import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData; +import org.apache.fineract.portfolio.loanaccount.exception.InvalidAmountOfCollateralQuantity; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.Row; @@ -270,6 +272,8 @@ public class LoanImportHandler implements ImportHandler { Long charge1 = ImportHandlerUtils.readAsLong(LoanConstants.CHARGE_ID_1, row); Long charge2 = ImportHandlerUtils.readAsLong(LoanConstants.CHARGE_ID_2, row); + Long collateralId = ImportHandlerUtils.readAsLong(LoanConstants.LOAN_COLLATERAL_ID, row); + Long groupId = ImportHandlerUtils.readAsLong(LoanConstants.GROUP_ID, row); String linkAccountId = ImportHandlerUtils.readAsString(LoanConstants.LINK_ACCOUNT_ID, row); @@ -295,6 +299,19 @@ public class LoanImportHandler implements ImportHandler { ImportHandlerUtils.readAsDate(LoanConstants.CHARGE_DUE_DATE_2, row), null)); } } + + List loanCollateralManagementData = new ArrayList<>(); + + if (collateralId != null) { + if (ImportHandlerUtils.readAsDouble(LoanConstants.LOAN_COLLATERAL_QUANTITY, row) != null) { + loanCollateralManagementData.add(new LoanCollateralManagementData(collateralId, + BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(LoanConstants.LOAN_COLLATERAL_QUANTITY, row)), null, null, + null)); + } else { + throw new InvalidAmountOfCollateralQuantity(null); + } + } + statuses.add(status); if (loanType != null) { if (loanType.equals("individual")) { @@ -305,7 +322,7 @@ public class LoanImportHandler implements ImportHandler { nominalInterestRate, submittedOnDate, amortizationEnumOption, interestMethodEnum, interestCalculationPeriodEnum, arrearsTolerance, repaymentStrategyId, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, firstRepaymentOnDate, row.getRowNum(), externalId, null, charges, linkAccountId, locale, - dateFormat); + dateFormat, loanCollateralManagementData); } else if (loanType.equals("jlg")) { Long clientId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.CLIENT_SHEET_NAME), clientOrGroupName); @@ -314,7 +331,7 @@ public class LoanImportHandler implements ImportHandler { nominalInterestRate, submittedOnDate, amortizationEnumOption, interestMethodEnum, interestCalculationPeriodEnum, arrearsTolerance, repaymentStrategyId, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, firstRepaymentOnDate, row.getRowNum(), externalId, groupId, charges, linkAccountId, locale, - dateFormat); + dateFormat, null); } else { Long groupIdforGroupLoan = ImportHandlerUtils .getIdByName(workbook.getSheet(TemplatePopulateImportConstants.GROUP_SHEET_NAME), clientOrGroupName); diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/monetary/domain/ApplicationCurrency.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/monetary/domain/ApplicationCurrency.java index 1b43bb124..33d4c5741 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/monetary/domain/ApplicationCurrency.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/monetary/domain/ApplicationCurrency.java @@ -18,12 +18,17 @@ */ package org.apache.fineract.organisation.monetary.domain; +import java.util.Collection; +import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.OneToMany; import javax.persistence.Table; import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; import org.apache.fineract.organisation.monetary.data.CurrencyData; import org.apache.fineract.organisation.office.domain.OrganisationCurrency; +import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementDomain; @Entity @Table(name = "m_currency") @@ -47,6 +52,9 @@ public class ApplicationCurrency extends AbstractPersistableCustom { @Column(name = "display_symbol", nullable = true, length = 10) private String displaySymbol; + @OneToMany(mappedBy = "currency", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true) + private Collection collateralManagementData; + protected ApplicationCurrency() { this.code = null; this.name = null; @@ -95,6 +103,10 @@ public class ApplicationCurrency extends AbstractPersistableCustom { return this.displaySymbol; } + public Collection getCollateralManagementData() { + return this.collateralManagementData; + } + public CurrencyData toData() { return new CurrencyData(this.code, this.name, this.decimalPlaces, this.inMultiplesOf, this.displaySymbol, this.nameCode); } @@ -106,4 +118,8 @@ public class ApplicationCurrency extends AbstractPersistableCustom { public OrganisationCurrency toOrganisationCurrency() { return new OrganisationCurrency(this.code, this.name, this.decimalPlaces, this.inMultiplesOf, this.nameCode, this.displaySymbol); } + + public void setCode(final String code) { + this.code = code; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientCollateralManagementData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientCollateralManagementData.java new file mode 100644 index 000000000..635325987 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientCollateralManagementData.java @@ -0,0 +1,82 @@ +/** + * 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.data; + +import java.io.Serializable; +import java.math.BigDecimal; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement; + +public final class ClientCollateralManagementData implements Serializable { + + private final BigDecimal quantity; + + private final Long id; + + private final BigDecimal pctToBase; + + private final BigDecimal unitPrice; + + private final BigDecimal total; + + private final BigDecimal totalCollateral; + + private final String name; + + private ClientCollateralManagementData(final BigDecimal quantity, final Long id, final BigDecimal pctToBase, final BigDecimal unitPrice, + final BigDecimal total, final BigDecimal totalCollateral, final String name) { + this.id = id; + this.pctToBase = pctToBase; + this.total = total; + this.totalCollateral = totalCollateral; + this.unitPrice = unitPrice; + this.quantity = quantity; + this.name = name; + } + + public static ClientCollateralManagementData setCollateralValues(final ClientCollateralManagement clientCollateralManagements, + final BigDecimal total, final BigDecimal totalCollateral) { + return new ClientCollateralManagementData(clientCollateralManagements.getQuantity(), clientCollateralManagements.getId(), + clientCollateralManagements.getCollaterals().getPctToBase(), clientCollateralManagements.getCollaterals().getBasePrice(), + total, totalCollateral, clientCollateralManagements.getCollaterals().getName()); + } + + public BigDecimal getQuantity() { + return this.quantity; + } + + public BigDecimal getTotal() { + return this.total; + } + + public BigDecimal getPctToBase() { + return this.pctToBase; + } + + public BigDecimal getTotalCollateral() { + return this.totalCollateral; + } + + public BigDecimal getUnitPrice() { + return this.unitPrice; + } + + public Long getId() { + return this.id; + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java index 6add75c8c..deb3cd5ef 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java @@ -22,6 +22,7 @@ import java.io.Serializable; import java.time.LocalDate; import java.util.Collection; import java.util.List; +import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.CompareToBuilder; import org.apache.commons.lang3.builder.EqualsBuilder; @@ -32,6 +33,7 @@ import org.apache.fineract.infrastructure.dataqueries.data.DatatableData; import org.apache.fineract.organisation.office.data.OfficeData; import org.apache.fineract.organisation.staff.data.StaffData; import org.apache.fineract.portfolio.address.data.AddressData; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement; import org.apache.fineract.portfolio.group.data.GroupGeneralData; import org.apache.fineract.portfolio.savings.data.SavingsAccountData; import org.apache.fineract.portfolio.savings.data.SavingsProductData; @@ -81,6 +83,7 @@ public final class ClientData implements Comparable, Serializable { private final Long savingsAccountId; private final EnumOptionData legalForm; + private final Set clientCollateralManagements; // associations private final Collection groups; @@ -201,6 +204,7 @@ public final class ClientData implements Comparable, Serializable { this.datatables = null; this.familyMemberOptions = null; this.emailAddress = null; + this.clientCollateralManagements = null; } public Integer getRowIndex() { @@ -258,18 +262,19 @@ public final class ClientData implements Comparable, Serializable { final EnumOptionData legalForm = null; final Boolean isStaff = false; final ClientNonPersonData clientNonPersonDetails = null; + final Set clientCollateralManagements = null; return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname, middlename, lastname, fullname, displayName, externalId, mobileNo, emailAddress, dateOfBirth, gender, joinedDate, imageId, staffId, staffName, officeOptions, groups, staffOptions, narrations, genderOptions, timeline, savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType, clientClassification, clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, clientNonPersonDetails, clientLegalFormOptions, familyMemberOptions, legalForm, address, isAddressEnabled, datatables, - isStaff); + isStaff, clientCollateralManagements); } public static ClientData templateOnTop(final ClientData clientData, final ClientData templateData) { - + final Set clientCollateralManagements = null; return new ClientData(clientData.accountNo, clientData.status, clientData.subStatus, clientData.officeId, clientData.officeName, clientData.transferToOfficeId, clientData.transferToOfficeName, clientData.id, clientData.firstname, clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName, clientData.externalId, clientData.mobileNo, @@ -281,13 +286,13 @@ public final class ClientData implements Comparable, Serializable { templateData.clientClassificationOptions, templateData.clientNonPersonConstitutionOptions, templateData.clientNonPersonMainBusinessLineOptions, clientData.clientNonPersonDetails, templateData.clientLegalFormOptions, templateData.familyMemberOptions, clientData.legalForm, clientData.address, clientData.isAddressEnabled, null, - clientData.isStaff); + clientData.isStaff, clientCollateralManagements); } public static ClientData templateWithSavingAccountOptions(final ClientData clientData, final Collection savingAccountOptions) { - + final Set clientCollateralManagements = null; return new ClientData(clientData.accountNo, clientData.status, clientData.subStatus, clientData.officeId, clientData.officeName, clientData.transferToOfficeId, clientData.transferToOfficeName, clientData.id, clientData.firstname, clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName, clientData.externalId, clientData.mobileNo, @@ -299,11 +304,12 @@ public final class ClientData implements Comparable, Serializable { clientData.clientClassificationOptions, clientData.clientNonPersonConstitutionOptions, clientData.clientNonPersonMainBusinessLineOptions, clientData.clientNonPersonDetails, clientData.clientLegalFormOptions, clientData.familyMemberOptions, clientData.legalForm, clientData.address, clientData.isAddressEnabled, null, - clientData.isStaff); + clientData.isStaff, clientCollateralManagements); } - public static ClientData setParentGroups(final ClientData clientData, final Collection parentGroups) { + public static ClientData setParentGroups(final ClientData clientData, final Collection parentGroups, + final Set clientCollateralManagements) { return new ClientData(clientData.accountNo, clientData.status, clientData.subStatus, clientData.officeId, clientData.officeName, clientData.transferToOfficeId, clientData.transferToOfficeName, clientData.id, clientData.firstname, clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName, clientData.externalId, clientData.mobileNo, @@ -314,7 +320,7 @@ public final class ClientData implements Comparable, Serializable { clientData.clientTypeOptions, clientData.clientClassificationOptions, clientData.clientNonPersonConstitutionOptions, clientData.clientNonPersonMainBusinessLineOptions, clientData.clientNonPersonDetails, clientData.clientLegalFormOptions, clientData.familyMemberOptions, clientData.legalForm, clientData.address, clientData.isAddressEnabled, null, - clientData.isStaff); + clientData.isStaff, clientCollateralManagements); } @@ -356,13 +362,14 @@ public final class ClientData implements Comparable, Serializable { final EnumOptionData legalForm = null; final Boolean isStaff = false; final ClientNonPersonData clientNonPerson = null; + final Set clientCollateralManagements = null; return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname, middlename, lastname, fullname, displayName, externalId, mobileNo, emailAddress, dateOfBirth, gender, activationDate, imageId, staffId, staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline, savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType, clientClassification, clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, clientNonPerson, clientLegalFormOptions, familyMemberOptions, legalForm, null, null, - null, isStaff); + null, isStaff, clientCollateralManagements); } public static ClientData lookup(final Long id, final String displayName, final Long officeId, final String officeName) { @@ -406,13 +413,14 @@ public final class ClientData implements Comparable, Serializable { final EnumOptionData legalForm = null; final Boolean isStaff = false; final ClientNonPersonData clientNonPerson = null; + final Set clientCollateralManagements = null; return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname, middlename, lastname, fullname, displayName, externalId, mobileNo, emailAddress, dateOfBirth, gender, activationDate, imageId, staffId, staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline, savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType, clientClassification, clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, clientNonPerson, clientLegalFormOptions, familyMemberOptions, legalForm, null, null, - null, isStaff); + null, isStaff, clientCollateralManagements); } @@ -443,12 +451,13 @@ public final class ClientData implements Comparable, Serializable { final Collection clientNonPersonMainBusinessLineOptions = null; final List clientLegalFormOptions = null; final ClientFamilyMembersData familyMemberOptions = null; + final Collection clientCollateralManagements = null; return new ClientData(accountNo, status, subStatus, officeId, officeName, transferToOfficeId, transferToOfficeName, id, firstname, middlename, lastname, fullname, displayName, externalId, mobileNo, emailAddress, dateOfBirth, gender, activationDate, imageId, staffId, staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline, savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, null, clientType, clientClassification, clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, - clientNonPerson, clientLegalFormOptions, familyMemberOptions, legalForm, null, null, null, isStaff); + clientNonPerson, clientLegalFormOptions, familyMemberOptions, legalForm, null, null, null, isStaff, null); } @@ -467,7 +476,8 @@ public final class ClientData implements Comparable, Serializable { final Collection clientNonPersonMainBusinessLineOptions, final ClientNonPersonData clientNonPerson, final List clientLegalFormOptions, final ClientFamilyMembersData familyMemberOptions, final EnumOptionData legalForm, final Collection address, final Boolean isAddressEnabled, - final List datatables, final Boolean isStaff) { + final List datatables, final Boolean isStaff, + final Set clientCollateralManagements) { this.accountNo = accountNo; this.status = status; if (status != null) { @@ -533,7 +543,7 @@ public final class ClientData implements Comparable, Serializable { this.address = address; this.isAddressEnabled = isAddressEnabled; this.datatables = datatables; - + this.clientCollateralManagements = clientCollateralManagements; } public Long id() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java index 9bb1eae37..d0e6c8abe 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java @@ -27,6 +27,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; +import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; @@ -34,6 +35,7 @@ import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.Table; import javax.persistence.Temporal; @@ -54,6 +56,7 @@ import org.apache.fineract.infrastructure.security.service.RandomPasswordGenerat import org.apache.fineract.organisation.office.domain.Office; import org.apache.fineract.organisation.staff.domain.Staff; import org.apache.fineract.portfolio.client.api.ClientApiConstants; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement; import org.apache.fineract.portfolio.group.domain.Group; import org.apache.fineract.useradministration.domain.AppUser; @@ -234,6 +237,9 @@ public final class Client extends AbstractPersistableCustom { @Temporal(TemporalType.DATE) private Date proposedTransferDate; + @OneToMany(mappedBy = "client", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + private Set clientCollateralManagements = new HashSet<>(); + public static Client createNew(final AppUser currentUser, final Office clientOffice, final Group clientParentGroup, final Staff staff, final Long savingsProductId, final CodeValue gender, final CodeValue clientType, final CodeValue clientClassification, final Integer legalForm, final JsonCommand command) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java index 76490bb3f..9d58c2602 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java @@ -18,6 +18,7 @@ */ package org.apache.fineract.portfolio.client.service; +import java.math.BigDecimal; import java.sql.ResultSet; import java.sql.SQLException; import java.time.LocalDate; @@ -25,7 +26,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.apache.fineract.infrastructure.codes.data.CodeValueData; import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService; @@ -53,6 +56,7 @@ import org.apache.fineract.organisation.staff.service.StaffReadPlatformService; import org.apache.fineract.portfolio.address.data.AddressData; import org.apache.fineract.portfolio.address.service.AddressReadPlatformService; import org.apache.fineract.portfolio.client.api.ClientApiConstants; +import org.apache.fineract.portfolio.client.data.ClientCollateralManagementData; import org.apache.fineract.portfolio.client.data.ClientData; import org.apache.fineract.portfolio.client.data.ClientFamilyMembersData; import org.apache.fineract.portfolio.client.data.ClientNonPersonData; @@ -61,6 +65,8 @@ import org.apache.fineract.portfolio.client.domain.ClientEnumerations; import org.apache.fineract.portfolio.client.domain.ClientStatus; import org.apache.fineract.portfolio.client.domain.LegalForm; import org.apache.fineract.portfolio.client.exception.ClientNotFoundException; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagementRepositoryWrapper; import org.apache.fineract.portfolio.group.data.GroupGeneralData; import org.apache.fineract.portfolio.savings.data.SavingsProductData; import org.apache.fineract.portfolio.savings.service.SavingsProductReadPlatformService; @@ -93,6 +99,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService private final ConfigurationReadPlatformService configurationReadPlatformService; private final EntityDatatableChecksReadService entityDatatableChecksReadService; private final ColumnValidator columnValidator; + private final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper; @Autowired public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource, @@ -102,7 +109,8 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService final AddressReadPlatformService addressReadPlatformService, final ClientFamilyMembersReadPlatformService clientFamilyMembersReadPlatformService, final ConfigurationReadPlatformService configurationReadPlatformService, - final EntityDatatableChecksReadService entityDatatableChecksReadService, final ColumnValidator columnValidator) { + final EntityDatatableChecksReadService entityDatatableChecksReadService, final ColumnValidator columnValidator, + final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper) { this.context = context; this.officeReadPlatformService = officeReadPlatformService; this.jdbcTemplate = new JdbcTemplate(dataSource); @@ -114,6 +122,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService this.configurationReadPlatformService = configurationReadPlatformService; this.entityDatatableChecksReadService = entityDatatableChecksReadService; this.columnValidator = columnValidator; + this.clientCollateralManagementRepositoryWrapper = clientCollateralManagementRepositoryWrapper; } @Override @@ -313,12 +322,25 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService final ClientData clientData = this.jdbcTemplate.queryForObject(sql, this.clientMapper, new Object[] { hierarchySearchString, hierarchySearchString, clientId }); + // Get client collaterals + final Collection clientCollateralManagements = this.clientCollateralManagementRepositoryWrapper + .getCollateralsPerClient(clientId); + final Set clientCollateralManagementDataSet = new HashSet<>(); + + // Map to client collateral data class + for (ClientCollateralManagement clientCollateralManagement : clientCollateralManagements) { + BigDecimal total = clientCollateralManagement.getTotal(); + BigDecimal totalCollateral = clientCollateralManagement.getTotalCollateral(total); + clientCollateralManagementDataSet + .add(ClientCollateralManagementData.setCollateralValues(clientCollateralManagement, total, totalCollateral)); + } + final String clientGroupsSql = "select " + this.clientGroupsMapper.parentGroupsSchema(); final Collection parentGroups = this.jdbcTemplate.query(clientGroupsSql, this.clientGroupsMapper, new Object[] { clientId }); - return ClientData.setParentGroups(clientData, parentGroups); + return ClientData.setParentGroups(clientData, parentGroups, clientCollateralManagementDataSet); } catch (final EmptyResultDataAccessException e) { throw new ClientNotFoundException(clientId, e); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateral/api/CollateralsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateral/api/CollateralsApiResource.java index 705b6e774..50061f7b2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateral/api/CollateralsApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateral/api/CollateralsApiResource.java @@ -100,7 +100,6 @@ public class CollateralsApiResource { @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CollateralsApiResourceSwagger.GetLoansLoanIdCollateralsTemplateResponse.class))) }) public String newCollateralTemplate(@Context final UriInfo uriInfo, @PathParam("loanId") @Parameter(description = "loanId") final Long loanId) { - this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission); this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateral/api/CollateralsApiResourceSwagger.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateral/api/CollateralsApiResourceSwagger.java index e966aa6ff..e06eb98b3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateral/api/CollateralsApiResourceSwagger.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateral/api/CollateralsApiResourceSwagger.java @@ -85,8 +85,6 @@ final class CollateralsApiResourceSwagger { private PostLoansLoanIdCollateralsResponse() {} - @Schema(example = "1") - public Integer loanId; @Schema(example = "12") public Integer resourceId; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/ClientCollateralManagementApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/ClientCollateralManagementApiResource.java new file mode 100644 index 000000000..27945519b --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/ClientCollateralManagementApiResource.java @@ -0,0 +1,199 @@ +/** + * 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.collateralmanagement.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriInfo; +import org.apache.fineract.commands.domain.CommandWrapper; +import org.apache.fineract.commands.service.CommandWrapperBuilder; +import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService; +import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService; +import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.portfolio.collateralmanagement.data.ClientCollateralManagementData; +import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralTemplateData; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement; +import org.apache.fineract.portfolio.collateralmanagement.service.ClientCollateralManagementReadPlatformService; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Path("/clients/{clientId}/collaterals") +@Component +@Scope("singleton") +@Tag(name = "Client Collateral Management", description = "Client Collateral Management is for managing collateral operations") +public class ClientCollateralManagementApiResource { + + private final DefaultToApiJsonSerializer apiJsonSerializerService; + private final DefaultToApiJsonSerializer apiJsonSerializerDataService; + private final DefaultToApiJsonSerializer apiJsonSerializerForLoanCollateralTemplateService; + private final ApiRequestParameterHelper apiRequestParameterHelper; + private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; + private final PlatformSecurityContext context; + private final CodeValueReadPlatformService codeValueReadPlatformService; + private final ClientCollateralManagementReadPlatformService clientCollateralManagementReadPlatformService; + private static final Set RESPONSE_DATA_PARAMETERS = new HashSet<>( + Arrays.asList("name", "quantity", "total", "totalCollateral", "clientId", "loanTransactionData")); + + public ClientCollateralManagementApiResource(final DefaultToApiJsonSerializer apiJsonSerializerService, + final ApiRequestParameterHelper apiRequestParameterHelper, + final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, final PlatformSecurityContext context, + final CodeValueReadPlatformService codeValueReadPlatformService, + final ClientCollateralManagementReadPlatformService clientCollateralManagementReadPlatformService, + final DefaultToApiJsonSerializer apiJsonSerializerDataService, + final DefaultToApiJsonSerializer apiJsonSerializerForLoanCollateralTemplateService) { + this.apiJsonSerializerService = apiJsonSerializerService; + this.apiRequestParameterHelper = apiRequestParameterHelper; + this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; + this.context = context; + this.codeValueReadPlatformService = codeValueReadPlatformService; + this.clientCollateralManagementReadPlatformService = clientCollateralManagementReadPlatformService; + this.apiJsonSerializerDataService = apiJsonSerializerDataService; + this.apiJsonSerializerForLoanCollateralTemplateService = apiJsonSerializerForLoanCollateralTemplateService; + } + + @GET + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + @Operation(summary = "Get Clients Collateral Products", description = "Get Collateral Product of a Client") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClientCollateralManagementApiResourceSwagger.GetClientCollateralManagementsResponse.class)))) }) + public String getClientCollateral(@PathParam("clientId") @Parameter(description = "clientId") final Long clientId, + @Context final UriInfo uriInfo, @QueryParam("prodId") @Parameter(description = "prodId") final Long prodId) { + + this.context.authenticatedUser() + .validateHasReadPermission(CollateralManagementJsonInputParams.CLIENT_COLLATERAL_PRODUCT_READ_PERMISSION.getValue()); + + List collateralProductList = null; + + collateralProductList = this.clientCollateralManagementReadPlatformService.getClientCollaterals(clientId, prodId); + + return this.apiJsonSerializerDataService.serialize(collateralProductList); + } + + @GET + @Path("{clientCollateralId}") + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + @Operation(summary = "Get Client Collateral Data", description = "Get Client Collateral Data") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ClientCollateralManagementApiResourceSwagger.GetClientCollateralManagementsResponse.class))) }) + public String getClientCollateralData(@PathParam("clientId") @Parameter(description = "clientId") final Long clientId, + @PathParam("clientCollateralId") @Parameter(description = "clientCollateralId") final Long collateralId) { + + this.context.authenticatedUser() + .validateHasReadPermission(CollateralManagementJsonInputParams.CLIENT_COLLATERAL_PRODUCT_READ_PERMISSION.getValue()); + + ClientCollateralManagementData clientCollateralManagementData = this.clientCollateralManagementReadPlatformService + .getClientCollateralManagementData(collateralId); + + return this.apiJsonSerializerDataService.serialize(clientCollateralManagementData); + } + + @GET + @Path("template") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(summary = "Get Client Collateral Template", description = "Get Client Collateral Template") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ClientCollateralManagementApiResourceSwagger.GetLoanCollateralManagementTemplate.class)))) }) + public String getClientCollateralTemplate(@Context final UriInfo uriInfo, + @PathParam("clientId") @Parameter(description = "clientId") final Long clientId) { + List loanCollateralTemplateDataList = this.clientCollateralManagementReadPlatformService + .getLoanCollateralTemplate(clientId); + return this.apiJsonSerializerForLoanCollateralTemplateService.serialize(loanCollateralTemplateDataList); + } + + @POST + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + @Operation(summary = "Add New Collateral For a Client", description = "Add New Collateral For a Client") + @RequestBody(required = true, content = @Content(schema = @Schema(implementation = ClientCollateralManagementApiResourceSwagger.PostClientCollateralRequest.class))) + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ClientCollateralManagementApiResourceSwagger.PostClientCollateralResponse.class))) }) + public String addCollateral(@PathParam("clientId") @Parameter(description = "clientId") final Long clientId, + @Parameter(hidden = true) String apiJsonRequestBody) { + final CommandWrapper commandWrapper = new CommandWrapperBuilder().addClientCollateralProduct(clientId).withJson(apiJsonRequestBody) + .build(); + + final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper); + + return this.apiJsonSerializerService.serialize(commandProcessingResult); + } + + @PUT + @Path("{collateralId}") + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + @Operation(summary = "Update New Collateral of a Client", description = "Update New Collateral of a Client") + @RequestBody(required = true, content = @Content(schema = @Schema(implementation = ClientCollateralManagementApiResourceSwagger.PutClientCollateralRequest.class))) + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ClientCollateralManagementApiResourceSwagger.PutClientCollateralResponse.class))) }) + public String updateCollateral(@PathParam("clientId") @Parameter(description = "clientId") final Long clientId, + @PathParam("collateralId") @Parameter(description = "collateralId") final Long collateralId, + @Parameter(hidden = true) String apiJsonRequestBody) { + + final CommandWrapper commandWrapper = new CommandWrapperBuilder().updateClientCollateralProduct(clientId, collateralId) + .withJson(apiJsonRequestBody).build(); + + final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper); + + return this.apiJsonSerializerService.serialize(commandProcessingResult); + } + + @DELETE + @Path("{collateralId}") + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + @Operation(summary = "Delete Client Collateral", description = "Delete Client Collateral") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ClientCollateralManagementApiResourceSwagger.DeleteClientCollateralResponse.class))) }) + public String deleteCollateral(@PathParam("clientId") @Parameter(description = "clientId") final Long clientId, + @PathParam("collateralId") @Parameter(description = "collateralId") final Long collateralId) { + final CommandWrapper commandWrapper = new CommandWrapperBuilder().deleteClientCollateralProduct(collateralId, clientId).build(); + final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper); + return this.apiJsonSerializerService.serialize(commandProcessingResult); + + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/ClientCollateralManagementApiResourceSwagger.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/ClientCollateralManagementApiResourceSwagger.java new file mode 100644 index 000000000..58501ff92 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/ClientCollateralManagementApiResourceSwagger.java @@ -0,0 +1,155 @@ +/** + * 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.collateralmanagement.api; + +import io.swagger.v3.oas.annotations.media.Schema; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Set; + +final class ClientCollateralManagementApiResourceSwagger { + + private ClientCollateralManagementApiResourceSwagger() {} + + @Schema(description = "GetClientCollateralManagementsResponse") + public static final class GetClientCollateralManagementsResponse { + + private GetClientCollateralManagementsResponse() {} + + static final class GetClientCollateralDataResponse { + + private GetClientCollateralDataResponse() {} + + @Schema(example = "Gold") + public String name; + @Schema(example = "1") + public Long id; + @Schema(example = "10") + public BigDecimal quantity; + @Schema(example = "10000.00") + public BigDecimal total; + @Schema(example = "9000.00") + public BigDecimal totalCollateral; + public GetClientIdResponse client; + public Set transaction; + } + + static final class GetTransactionDataResponse { + + private GetTransactionDataResponse() {} + + @Schema(example = "5000.00") + public BigDecimal lastRepayment; + @Schema(example = "3000.00") + public BigDecimal remainingAmount; + @Schema(example = "1") + public Long loanId; + @Schema(example = "[2021, 6, 19]") + public LocalDateTime lastRepaymentDate; + } + + static final class GetClientIdResponse { + + private GetClientIdResponse() {} + + @Schema(example = "1") + public Long clientId; + } + + } + + @Schema(description = "GetLoanCollateralManagementTemplate") + public static final class GetLoanCollateralManagementTemplate { + + private GetLoanCollateralManagementTemplate() {} + + @Schema(example = "1") + public Long collateralId; + @Schema(example = "10000.00") + public BigDecimal basePrice; + @Schema(example = "40") + public BigDecimal pctToBase; + @Schema(example = "10") + public BigDecimal quantity; + @Schema(example = "Vehicle") + public String name; + + } + + @Schema(description = "PostClientCollateralRequest") + public static final class PostClientCollateralRequest { + + private PostClientCollateralRequest() {} + + @Schema(example = "10") + public BigDecimal quantity; + @Schema(example = "1") + public Long collateralId; + @Schema(example = "en") + public String locale; + + } + + @Schema(description = "PostClientCollateralResponse") + public static final class PostClientCollateralResponse { + + private PostClientCollateralResponse() {} + + @Schema(example = "14") + public Integer resourceId; + @Schema(example = "1") + public Integer clientId; + + } + + @Schema(description = "PutClientCollateralRequest") + public static final class PutClientCollateralRequest { + + private PutClientCollateralRequest() {} + + @Schema(example = "14") + public BigDecimal quantity; + @Schema(example = "en") + public String locale; + + } + + @Schema(description = "PutClientCollateralResponse") + public static final class PutClientCollateralResponse { + + private PutClientCollateralResponse() {} + + @Schema(example = "12") + public Integer resourceId; + @Schema(example = "1") + public Integer clientId; + public PutClientCollateralRequest changes; + } + + @Schema(description = "DeleteClientCollateralResponse") + public static final class DeleteClientCollateralResponse { + + private DeleteClientCollateralResponse() {} + + @Schema(example = "12") + public Integer resourceId; + + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/CollateralManagementApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/CollateralManagementApiResource.java new file mode 100644 index 000000000..c74d58ac2 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/CollateralManagementApiResource.java @@ -0,0 +1,188 @@ +/** + * 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.collateralmanagement.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.Collection; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriInfo; +import org.apache.fineract.commands.domain.CommandWrapper; +import org.apache.fineract.commands.service.CommandWrapperBuilder; +import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService; +import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService; +import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.organisation.monetary.data.CurrencyData; +import org.apache.fineract.organisation.monetary.service.CurrencyReadPlatformService; +import org.apache.fineract.portfolio.collateralmanagement.data.CollateralManagementData; +import org.apache.fineract.portfolio.collateralmanagement.service.ClientCollateralManagementReadPlatformService; +import org.apache.fineract.portfolio.collateralmanagement.service.CollateralManagementReadPlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Path("/collateral-management") +@Component +@Scope("singleton") +@Tag(name = "Collateral Management", description = "Collateral Management is for managing collateral operations") +public class CollateralManagementApiResource { + + private final DefaultToApiJsonSerializer apiJsonSerializerService; + private final DefaultToApiJsonSerializer apiJsonSerializerServiceForCurrency; + private final ApiRequestParameterHelper apiRequestParameterHelper; + private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; + private final PlatformSecurityContext context; + private final CodeValueReadPlatformService codeValueReadPlatformService; + private final CollateralManagementReadPlatformService collateralManagementReadPlatformService; + private final String collateralReadPermission = "COLLATERAL_PRODUCT"; + private final ClientCollateralManagementReadPlatformService clientCollateralManagementReadPlatformService; + private final CurrencyReadPlatformService currencyReadPlatformService; + + @Autowired + public CollateralManagementApiResource(final DefaultToApiJsonSerializer apiJsonSerializerService, + final ApiRequestParameterHelper apiRequestParameterHelper, + final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, final PlatformSecurityContext context, + final CodeValueReadPlatformService codeValueReadPlatformService, + final CollateralManagementReadPlatformService collateralManagementReadPlatformService, + final ClientCollateralManagementReadPlatformService clientCollateralManagementReadPlatformService, + final CurrencyReadPlatformService currencyReadPlatformService, + final DefaultToApiJsonSerializer apiJsonSerializerServiceForCurrency) { + this.apiJsonSerializerService = apiJsonSerializerService; + this.apiRequestParameterHelper = apiRequestParameterHelper; + this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; + this.context = context; + this.codeValueReadPlatformService = codeValueReadPlatformService; + this.collateralManagementReadPlatformService = collateralManagementReadPlatformService; + this.clientCollateralManagementReadPlatformService = clientCollateralManagementReadPlatformService; + this.currencyReadPlatformService = currencyReadPlatformService; + this.apiJsonSerializerServiceForCurrency = apiJsonSerializerServiceForCurrency; + } + + @POST + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(summary = "Create a new collateral", description = "Collateral Creation") + @RequestBody(required = true, content = @Content(schema = @Schema(implementation = CollateralManagementApiResourceSwagger.PostCollateralManagementProductRequest.class))) + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CollateralManagementApiResourceSwagger.PostCollateralManagementProductResponse.class))) }) + public String createCollateral(@Parameter(hidden = true) final String apiRequestBodyAsJson) { + final CommandWrapper commandWrapper = new CommandWrapperBuilder().createCollateral().withJson(apiRequestBodyAsJson).build(); + final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper); + return this.apiJsonSerializerService.serialize(commandProcessingResult); + } + + @GET + @Path("{collateralId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(summary = "Get Collateral", description = "Fetch Collateral") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CollateralManagementApiResourceSwagger.GetCollateralManagementsResponse.class))) }) + public String getCollateral(@PathParam("collateralId") @Parameter(description = "collateralId") final Long collateralId, + @Context final UriInfo uriInfo) { + + this.context.authenticatedUser() + .validateHasReadPermission(CollateralManagementJsonInputParams.COLLATERAL_PRODUCT_READ_PERMISSION.getValue()); + + final CollateralManagementData collateralManagementData = this.collateralManagementReadPlatformService + .getCollateralProduct(collateralId); + + return this.apiJsonSerializerService.serialize(collateralManagementData); + } + + @GET + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(summary = "Get All Collaterals", description = "Fetch all Collateral Products") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = CollateralManagementApiResourceSwagger.GetCollateralManagementsResponse.class)))) }) + public String getAllCollaterals(@Context final UriInfo uriInfo) { + this.context.authenticatedUser() + .validateHasReadPermission(CollateralManagementJsonInputParams.COLLATERAL_PRODUCT_READ_PERMISSION.getValue()); + Collection collateralManagementDataList = this.collateralManagementReadPlatformService + .getAllCollateralProducts(); + return this.apiJsonSerializerService.serialize(collateralManagementDataList); + } + + @GET + @Path("template") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(summary = "Get Collateral Template", description = "Get Collateral Template") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = CollateralManagementApiResourceSwagger.GetCollateralProductTemplate.class)))) }) + public String getCollateralTemplate(@Context final UriInfo uriInfo) { + Collection currencyDataCollection = this.currencyReadPlatformService.retrieveAllPlatformCurrencies(); + return this.apiJsonSerializerServiceForCurrency.serialize(currencyDataCollection); + } + + @PUT + @Path("{collateralId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(summary = "Update Collateral", description = "Update Collateral") + @RequestBody(required = true, content = @Content(schema = @Schema(implementation = CollateralManagementApiResourceSwagger.PutCollateralProductRequest.class))) + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CollateralManagementApiResourceSwagger.PutCollateralProductResponse.class))) }) + public String updateCollateral(@PathParam("collateralId") @Parameter(description = "collateralId") final Long collateralId, + @Parameter(hidden = true) final String jsonBody) { + final CommandWrapper commandWrapper = new CommandWrapperBuilder().updateCollateralProduct(collateralId).withJson(jsonBody).build(); + + final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper); + + return this.apiJsonSerializerService.serialize(commandProcessingResult); + + } + + @DELETE + @Path("{collateralId}") + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + @Operation(summary = "Delete a Collateral", description = "Delete Collateral") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CollateralManagementApiResourceSwagger.DeleteCollateralProductResponse.class))) }) + public String deleteCollateral(@PathParam("collateralId") @Parameter(description = "collateralId") final Long collateralId) { + + final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteCollateralProduct(collateralId).build(); + + final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + + return this.apiJsonSerializerService.serialize(commandProcessingResult); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/CollateralManagementApiResourceSwagger.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/CollateralManagementApiResourceSwagger.java new file mode 100644 index 000000000..1f8ebee43 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/CollateralManagementApiResourceSwagger.java @@ -0,0 +1,159 @@ +/** + * 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.collateralmanagement.api; + +import io.swagger.v3.oas.annotations.media.Schema; +import java.math.BigDecimal; + +final class CollateralManagementApiResourceSwagger { + + private CollateralManagementApiResourceSwagger() {} + + @Schema(description = "GetCollateralManagementsResponse") + public static final class GetCollateralManagementsResponse { + + private GetCollateralManagementsResponse() {} + + static final class GetCollateralTypeResponse { + + private GetCollateralTypeResponse() {} + + @Schema(example = "22kt") + public String quality; + + } + + static final class GetCollateralCurrencyResponse { + + private GetCollateralCurrencyResponse() {} + + @Schema(example = "USD") + public String code; + } + + @Schema(example = "8") + public Long id; + @Schema(example = "Gold") + public String name; + private CollateralManagementApiResourceSwagger.GetCollateralManagementsResponse.GetCollateralTypeResponse quality; + @Schema(example = "20000") + public BigDecimal basePrice; + @Schema(example = "gm") + public String unitType; + @Schema(example = "80") + public BigDecimal pctToBase; + public CollateralManagementApiResourceSwagger.GetCollateralManagementsResponse.GetCollateralCurrencyResponse currency; + } + + @Schema(description = "GetCollateralProductTemplate") + public static final class GetCollateralProductTemplate { + + private GetCollateralProductTemplate() {} + + static final class GetCurrencyData { + + private GetCurrencyData() {} + + @Schema(example = "USD") + public String code; + @Schema(example = "Dollars") + public String name; + @Schema(example = "10") + public int decimalPlaces; + @Schema(example = "2") + public Integer inMultiplesOf; + @Schema(example = "USD") + public String displaySymbol; + @Schema(example = "Dollars") + public String nameCode; + @Schema(example = "Dollars") + public String displayLabel; + + } + + public GetCurrencyData currency; + } + + @Schema(description = "PostCollateralManagementProductRequest") + public static final class PostCollateralManagementProductRequest { + + private PostCollateralManagementProductRequest() {} + + @Schema(example = "22kt") + public String quality; + @Schema(example = "4500") + public BigDecimal basePrice; + @Schema(example = "80") + public BigDecimal pctToBase; + @Schema(example = "gm") + public String unitType; + @Schema(example = "gold") + public String name; + @Schema(example = "USD") + public String currency; + } + + @Schema(description = "PostCollateralManagementProductResponse") + public static final class PostCollateralManagementProductResponse { + + private PostCollateralManagementProductResponse() {} + + @Schema(example = "14") + public Integer resourceId; + } + + @Schema(description = "PutCollateralProductRequest") + public static final class PutCollateralProductRequest { + + private PutCollateralProductRequest() {} + + @Schema(example = "22kt") + public String quality; + @Schema(example = "4500") + public BigDecimal basePrice; + @Schema(example = "80") + public BigDecimal pctToBase; + @Schema(example = "gm") + public String unitType; + @Schema(example = "gold") + public String name; + @Schema(example = "USD") + public String currency; + + } + + @Schema(description = "PutCollateralProductResponse") + public static final class PutCollateralProductResponse { + + private PutCollateralProductResponse() {} + + @Schema(example = "12") + public Integer resourceId; + public CollateralManagementApiResourceSwagger.PutCollateralProductRequest changes; + } + + @Schema(description = "DeleteCollateralProductResponse") + public static final class DeleteCollateralProductResponse { + + private DeleteCollateralProductResponse() {} + + @Schema(example = "12") + public Integer resourceId; + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/CollateralManagementJsonInputParams.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/CollateralManagementJsonInputParams.java new file mode 100644 index 000000000..a564818d7 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/CollateralManagementJsonInputParams.java @@ -0,0 +1,42 @@ +/** + * 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.collateralmanagement.api; + +public enum CollateralManagementJsonInputParams { + + NAME("name"), QUALITY("quality"), BASE_PRICE("basePrice"), UNIT_TYPE("unitType"), PCT_TO_BASE("pctToBase"), CURRENCY( + "currency"), COLLATERAL_PRODUCT_READ_PERMISSION("COLLATERAL_PRODUCT"), CLIENT_COLLATERAL_PRODUCT_READ_PERMISSION( + "CLIENT_COLLATERAL_PRODUCT"), QUANTITY("quantity"), TOTAL_COLLATERAL_VALUE("totalCollateralValue"); + + private final String value; + + CollateralManagementJsonInputParams(final String value) { + this.value = value; + } + + @Override + public String toString() { + return name().replaceAll("_", " "); + } + + public String getValue() { + return this.value; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/LoanCollateralManagementApiResources.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/LoanCollateralManagementApiResources.java new file mode 100644 index 000000000..c3f16af77 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/api/LoanCollateralManagementApiResources.java @@ -0,0 +1,94 @@ +/** + * 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.collateralmanagement.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import org.apache.fineract.commands.domain.CommandWrapper; +import org.apache.fineract.commands.service.CommandWrapperBuilder; +import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService; +import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService; +import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralResponseData; +import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralManagementReadPlatformService; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Path("/loan-collateral-management") +@Component +@Scope("singleton") +@Tag(name = "Loan Collateral Management", description = "Loan Collateral Management is for managing collateral operations") +public class LoanCollateralManagementApiResources { + + private final DefaultToApiJsonSerializer apiJsonSerializerService; + private final ApiRequestParameterHelper apiRequestParameterHelper; + private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; + private final PlatformSecurityContext context; + private final LoanCollateralManagementReadPlatformService loanCollateralManagementReadPlatformService; + private final CodeValueReadPlatformService codeValueReadPlatformService; + + public LoanCollateralManagementApiResources(final DefaultToApiJsonSerializer apiJsonSerializerService, + final ApiRequestParameterHelper apiRequestParameterHelper, + final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, final PlatformSecurityContext context, + final CodeValueReadPlatformService codeValueReadPlatformService, + final LoanCollateralManagementReadPlatformService loanCollateralManagementReadPlatformService) { + this.apiJsonSerializerService = apiJsonSerializerService; + this.apiRequestParameterHelper = apiRequestParameterHelper; + this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; + this.context = context; + this.codeValueReadPlatformService = codeValueReadPlatformService; + this.loanCollateralManagementReadPlatformService = loanCollateralManagementReadPlatformService; + } + + @DELETE + @Path("{id}") + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + @Operation(description = "Delete Loan Collateral", summary = "Delete Loan Collateral") + public String deleteLoanCollateral(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId, + @PathParam("id") @Parameter(description = "loan collateral id") final Long id) { + + final CommandWrapper commandWrapper = new CommandWrapperBuilder().deleteLoanCollateral(loanId, id).build(); + final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper); + return this.apiJsonSerializerService.serialize(commandProcessingResult); + } + + @GET + @Path("{collateralId}") + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + @Operation(description = "Get Loan Collateral Details", summary = "Get Loan Collateral Details") + public String getLoanCollateral(@PathParam("collateralId") @Parameter(description = "collateralId") final Long collateralId) { + final LoanCollateralResponseData loanCollateralResponseData = this.loanCollateralManagementReadPlatformService + .getLoanCollateralResponseData(collateralId); + return this.apiJsonSerializerService.serialize(loanCollateralResponseData); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/ClientCollateralManagementData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/ClientCollateralManagementData.java new file mode 100644 index 000000000..b3e514e8c --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/ClientCollateralManagementData.java @@ -0,0 +1,84 @@ +/** + * 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.collateralmanagement.data; + +import java.math.BigDecimal; +import java.util.List; + +public final class ClientCollateralManagementData { + + private final String name; + + private final BigDecimal quantity; + + private final BigDecimal total; + + private final BigDecimal totalCollateral; + + private final Long clientId; + + private final Long id; + + private final List loanTransactionData; + + private ClientCollateralManagementData(final String name, final BigDecimal quantity, final BigDecimal total, + final BigDecimal totalCollateral, final Long clientId, final List loanTransactionData, final Long id) { + this.clientId = clientId; + this.totalCollateral = totalCollateral; + this.total = total; + this.name = name; + this.quantity = quantity; + this.loanTransactionData = loanTransactionData; + this.id = id; + } + + public static ClientCollateralManagementData instance(final String name, final BigDecimal quantity, final BigDecimal total, + final BigDecimal totalCollateral, final Long clientId, final List loanTransactionData, final Long id) { + return new ClientCollateralManagementData(name, quantity, total, totalCollateral, clientId, loanTransactionData, id); + } + + public String getName() { + return this.name; + } + + public Long getClientId() { + return this.clientId; + } + + public BigDecimal getQuantity() { + return this.quantity; + } + + public BigDecimal getTotal() { + return this.total; + } + + public BigDecimal getTotalCollateral() { + return this.totalCollateral; + } + + public Long getId() { + return this.id; + } + + public List getLoanTransactionData() { + return this.loanTransactionData; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/CollateralManagementData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/CollateralManagementData.java new file mode 100644 index 000000000..05ab639be --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/CollateralManagementData.java @@ -0,0 +1,58 @@ +/** + * 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.collateralmanagement.data; + +import java.math.BigDecimal; +import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementDomain; + +public final class CollateralManagementData { + + private String quality; + + private BigDecimal basePrice; + + private String unitType; + + private BigDecimal pctToBase; + + private String currency; + + private String name; + + private Long id; + + private CollateralManagementData(final String quality, final BigDecimal basePrice, final String unitType, final BigDecimal pctToBase, + final String currency, final String name, final Long id) { + this.basePrice = basePrice; + this.pctToBase = pctToBase; + this.quality = quality; + this.unitType = unitType; + this.currency = currency; + this.name = name; + this.id = id; + } + + public static CollateralManagementData createNew(final CollateralManagementDomain collateralManagementDomain) { + return new CollateralManagementData(collateralManagementDomain.getQuality(), collateralManagementDomain.getBasePrice(), + collateralManagementDomain.getUnitType(), collateralManagementDomain.getPctToBase(), + collateralManagementDomain.getCurrency().getCode(), collateralManagementDomain.getName(), + collateralManagementDomain.getId()); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/LoanCollateralResponseData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/LoanCollateralResponseData.java new file mode 100644 index 000000000..db66ed8d4 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/LoanCollateralResponseData.java @@ -0,0 +1,56 @@ +/** + * 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.collateralmanagement.data; + +import java.math.BigDecimal; +import org.apache.fineract.portfolio.loanaccount.data.LoanCollateralManagementData; +import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement; + +public final class LoanCollateralResponseData { + + private Long collateralId; + + private BigDecimal quantity; + + private BigDecimal total; + + private BigDecimal totalCollateral; + + private Long clientCollateralId; + + private LoanCollateralResponseData(final Long collateralId, final BigDecimal quantity, final BigDecimal total, + final BigDecimal totalCollateral, final Long clientCollateralId) { + this.collateralId = collateralId; + this.quantity = quantity; + this.total = total; + this.totalCollateral = totalCollateral; + this.clientCollateralId = clientCollateralId; + } + + public static LoanCollateralResponseData instanceOf(final LoanCollateralManagement loanCollateralManagement, final BigDecimal total, + final BigDecimal totalCollateral) { + return new LoanCollateralResponseData(loanCollateralManagement.getId(), loanCollateralManagement.getQuantity(), total, + totalCollateral, loanCollateralManagement.getClientCollateralManagement().getId()); + } + + public LoanCollateralManagementData toCommand() { + return new LoanCollateralManagementData(this.clientCollateralId, this.quantity, this.total, this.totalCollateral, + this.collateralId); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/LoanCollateralTemplateData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/LoanCollateralTemplateData.java new file mode 100644 index 000000000..9a99a4fbc --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/LoanCollateralTemplateData.java @@ -0,0 +1,51 @@ +/** + * 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.collateralmanagement.data; + +import java.math.BigDecimal; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement; + +public final class LoanCollateralTemplateData { + + private Long collateralId; + + private BigDecimal basePrice; + + private BigDecimal pctToBase; + + private BigDecimal quantity; + + private String name; + + private LoanCollateralTemplateData(final Long collateralId, final BigDecimal basePrice, final BigDecimal pctToBase, + final BigDecimal quantity, final String name) { + this.quantity = quantity; + this.collateralId = collateralId; + this.basePrice = basePrice; + this.pctToBase = pctToBase; + this.name = name; + } + + public static LoanCollateralTemplateData instanceOf(final ClientCollateralManagement clientCollateralManagement) { + return new LoanCollateralTemplateData(clientCollateralManagement.getId(), + clientCollateralManagement.getCollaterals().getBasePrice(), clientCollateralManagement.getCollaterals().getPctToBase(), + clientCollateralManagement.getQuantity(), clientCollateralManagement.getCollaterals().getName()); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/LoanTransactionData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/LoanTransactionData.java new file mode 100644 index 000000000..82f05f26a --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/data/LoanTransactionData.java @@ -0,0 +1,46 @@ +/** + * 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.collateralmanagement.data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +public final class LoanTransactionData { + + private final BigDecimal lastRepayment; + + private final BigDecimal remainingAmount; + + private final Long loanId; + + private final LocalDateTime lastRepaymentDate; + + private LoanTransactionData(final Long loanId, final LocalDateTime lastRepaymentDate, final BigDecimal remainingAmount, + final BigDecimal lastRepayment) { + this.lastRepayment = lastRepayment; + this.lastRepaymentDate = lastRepaymentDate; + this.remainingAmount = remainingAmount; + this.loanId = loanId; + } + + public static LoanTransactionData instance(final Long loanId, final LocalDateTime lastRepaymentDate, final BigDecimal remainingAmount, + final BigDecimal lastRepayment) { + return new LoanTransactionData(loanId, lastRepaymentDate, remainingAmount, lastRepayment); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/ClientCollateralManagement.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/ClientCollateralManagement.java new file mode 100644 index 000000000..f00abe556 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/ClientCollateralManagement.java @@ -0,0 +1,137 @@ +/** + * 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.collateralmanagement.domain; + +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.apache.fineract.portfolio.client.domain.Client; +import org.apache.fineract.portfolio.collateralmanagement.api.CollateralManagementJsonInputParams; +import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement; + +@Entity +@Table(name = "m_client_collateral_management") +public class ClientCollateralManagement extends AbstractPersistableCustom { + + @Column(name = "quantity", nullable = false, scale = 5, precision = 20) + private BigDecimal quantity; + + @ManyToOne(optional = false) + @JoinColumn(name = "client_id", nullable = false) + private Client client; + + @ManyToOne(optional = false) + @JoinColumn(name = "collateral_id", nullable = false) + private CollateralManagementDomain collateral; + + @OneToMany(cascade = CascadeType.ALL, mappedBy = "clientCollateralManagement", fetch = FetchType.EAGER) + private Set loanCollateralManagementSet = new HashSet<>(); + + public ClientCollateralManagement() { + + } + + public ClientCollateralManagement(final BigDecimal quantity, final Client client) { + this.client = client; + this.quantity = quantity; + } + + public ClientCollateralManagement(final BigDecimal quantity) { + this.quantity = quantity; + } + + private ClientCollateralManagement(final BigDecimal quantity, final Client client, + final CollateralManagementDomain collateralManagementData) { + this.quantity = quantity; + this.client = client; + this.collateral = collateralManagementData; + } + + public ClientCollateralManagement createNew(JsonCommand jsonCommand) { + BigDecimal quantity = jsonCommand.bigDecimalValueOfParameterNamed("quantity"); + return new ClientCollateralManagement(quantity); + } + + public static ClientCollateralManagement createNew(final BigDecimal quantity, final Client client, + final CollateralManagementDomain collateral) { + return new ClientCollateralManagement(quantity, client, collateral); + } + + public Map update(JsonCommand command) { + final Map changes = new LinkedHashMap<>(3); + final String quantity = CollateralManagementJsonInputParams.QUANTITY.getValue(); + if (command.isChangeInBigDecimalParameterNamed(quantity, this.quantity)) { + final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(quantity); + this.quantity = newValue; + changes.put(quantity, this.quantity); + } + return changes; + } + + public BigDecimal getTotal() { + if (BigDecimal.ZERO.compareTo(this.quantity) == 0) { + return BigDecimal.ZERO; + } + return this.quantity.multiply(getCollaterals().getBasePrice()); + } + + public BigDecimal getTotalCollateral(BigDecimal total) { + if (BigDecimal.ZERO.compareTo(total) == 0) { + return BigDecimal.ZERO; + } + return total.multiply(getCollaterals().getPctToBase().divide(BigDecimal.valueOf(100))); + } + + public void updateQuantity(BigDecimal quantity) { + this.quantity = quantity; + } + + public void updateQuantityAfterLoanClosed(BigDecimal quantity) { + this.quantity = this.quantity.add(quantity); + } + + public BigDecimal getQuantity() { + return this.quantity; + } + + public Client getClient() { + return this.client; + } + + public CollateralManagementDomain getCollaterals() { + return this.collateral; + } + + public Set getLoanCollateralManagementSet() { + return this.loanCollateralManagementSet; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/ClientCollateralManagementRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/ClientCollateralManagementRepository.java new file mode 100644 index 000000000..44cb416a3 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/ClientCollateralManagementRepository.java @@ -0,0 +1,33 @@ +/** + * 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.collateralmanagement.domain; + +import java.util.List; +import org.apache.fineract.portfolio.client.domain.Client; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface ClientCollateralManagementRepository + extends JpaRepository, JpaSpecificationExecutor { + + @Query("select clientCollateral from ClientCollateralManagement clientCollateral where clientCollateral.client=:client") + List findByClientId(@Param("client") Client client); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/ClientCollateralManagementRepositoryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/ClientCollateralManagementRepositoryWrapper.java new file mode 100644 index 000000000..1eeef8659 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/ClientCollateralManagementRepositoryWrapper.java @@ -0,0 +1,98 @@ +/** + * 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.collateralmanagement.domain; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import org.apache.fineract.portfolio.client.domain.Client; +import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper; +import org.apache.fineract.portfolio.collateralmanagement.data.ClientCollateralManagementData; +import org.apache.fineract.portfolio.collateralmanagement.exception.ClientCollateralNotFoundException; +import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct; +import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository; +import org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ClientCollateralManagementRepositoryWrapper { + + private final ClientCollateralManagementRepository clientCollateralManagementRepository; + private final ClientRepositoryWrapper clientRepositoryWrapper; + private final LoanProductRepository loanProductRepository; + + @Autowired + public ClientCollateralManagementRepositoryWrapper(final ClientCollateralManagementRepository clientCollateralManagementRepository, + final ClientRepositoryWrapper clientRepositoryWrapper, final LoanProductRepository loanProductRepository) { + this.clientCollateralManagementRepository = clientCollateralManagementRepository; + this.clientRepositoryWrapper = clientRepositoryWrapper; + this.loanProductRepository = loanProductRepository; + } + + public List getCollateralsPerClient(final Long clientId) { + final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId); + return this.clientCollateralManagementRepository.findByClientId(client); + } + + public List getClientCollateralData(final Long clientId, final Long prodId) { + final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId); + String currency = null; + if (prodId != null) { + final LoanProduct loanProduct = this.loanProductRepository.findById(prodId) + .orElseThrow(() -> new LoanProductNotFoundException(prodId)); + currency = loanProduct.getCurrency().getCode(); + } + List clientCollateralManagements = this.clientCollateralManagementRepository.findByClientId(client); + List clientCollateralManagementDataSet = new ArrayList<>(); + for (ClientCollateralManagement clientCollateralManagement : clientCollateralManagements) { + BigDecimal quantity = clientCollateralManagement.getQuantity(); + BigDecimal total = clientCollateralManagement.getTotal(); + BigDecimal totalCollateralValue = clientCollateralManagement.getTotalCollateral(total); + if (prodId != null && clientCollateralManagement.getCollaterals().getCurrency().getCode().equals(currency)) { + clientCollateralManagementDataSet + .add(ClientCollateralManagementData.instance(clientCollateralManagement.getCollaterals().getName(), quantity, total, + totalCollateralValue, clientId, null, clientCollateralManagement.getId())); + } + } + + return clientCollateralManagementDataSet; + } + + public ClientCollateralManagement getCollateral(final Long collateralId) { + return this.clientCollateralManagementRepository.findById(collateralId) + .orElseThrow(() -> new ClientCollateralNotFoundException(collateralId)); + } + + public ClientCollateralManagement updateClientCollateralProduct(final ClientCollateralManagement clientCollateralManagement) { + return this.clientCollateralManagementRepository.saveAndFlush(clientCollateralManagement); + } + + public void deleteClientCollateralProduct(final Long collateralId) { + this.clientCollateralManagementRepository.deleteById(collateralId); + } + + public void save(ClientCollateralManagement clientCollateralManagement) { + this.clientCollateralManagementRepository.save(clientCollateralManagement); + } + + public void saveAndFlush(ClientCollateralManagement clientCollateralManagement) { + this.clientCollateralManagementRepository.saveAndFlush(clientCollateralManagement); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/CollateralManagementDomain.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/CollateralManagementDomain.java new file mode 100644 index 000000000..addb1814d --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/CollateralManagementDomain.java @@ -0,0 +1,160 @@ +/** + * 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.collateralmanagement.domain; + +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import org.apache.commons.lang3.StringUtils; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency; +import org.apache.fineract.portfolio.collateralmanagement.api.CollateralManagementJsonInputParams; + +@Entity +@Table(name = "m_collateral_management") +public class CollateralManagementDomain extends AbstractPersistableCustom { + + @Column(name = "name", length = 20, columnDefinition = " ") + private String name; + + @Column(name = "quality", nullable = false, length = 40) + private String quality; + + @Column(name = "base_price", nullable = false, scale = 5, precision = 20) + private BigDecimal basePrice; + + @Column(name = "unit_type", nullable = false, length = 10) + private String unitType; + + @Column(name = "pct_to_base", nullable = false, scale = 5, precision = 20) + private BigDecimal pctToBase; + + @ManyToOne + @JoinColumn(name = "currency") + private ApplicationCurrency currency; + + @OneToMany(mappedBy = "collateral", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + private Set clientCollateralManagements = new HashSet<>(); + + public CollateralManagementDomain() { + + } + + private CollateralManagementDomain(final String quality, final BigDecimal basePrice, final String unitType, final BigDecimal pctToBase, + final ApplicationCurrency currency, final String name) { + this.basePrice = basePrice; + this.currency = currency; + this.pctToBase = pctToBase; + this.unitType = unitType; + this.quality = quality; + this.name = name; + } + + public static CollateralManagementDomain createNew(JsonCommand jsonCommand, final ApplicationCurrency applicationCurrency) { + String quality = jsonCommand.stringValueOfParameterNamed("quality"); + BigDecimal basePrice = jsonCommand.bigDecimalValueOfParameterNamed("basePrice"); + BigDecimal pctToBase = jsonCommand.bigDecimalValueOfParameterNamedDefaultToNullIfZero("pctToBase"); + String unitType = jsonCommand.stringValueOfParameterNamed("unitType"); + String name = jsonCommand.stringValueOfParameterNamed("name"); + return new CollateralManagementDomain(quality, basePrice, unitType, pctToBase, applicationCurrency, name); + } + + public Map update(final JsonCommand command, final ApplicationCurrency applicationCurrency) { + final Map changes = new LinkedHashMap<>(5); + final String nameParamName = CollateralManagementJsonInputParams.NAME.getValue(); + + if (command.isChangeInStringParameterNamed(nameParamName, this.name)) { + final String newValue = command.stringValueOfParameterNamed(nameParamName); + this.name = StringUtils.defaultIfEmpty(newValue, null); + changes.put(nameParamName, this.name); + } + + final String qualityParamName = CollateralManagementJsonInputParams.QUALITY.getValue(); + if (command.isChangeInStringParameterNamed(qualityParamName, this.quality)) { + final String newValue = command.stringValueOfParameterNamed(qualityParamName); + this.quality = newValue; + changes.put(qualityParamName, this.quality); + } + + final String unitTypeParamName = CollateralManagementJsonInputParams.UNIT_TYPE.getValue(); + if (command.isChangeInStringParameterNamed(unitTypeParamName, this.unitType)) { + final String newValue = command.stringValueOfParameterNamed(unitTypeParamName); + this.unitType = newValue; + changes.put(unitTypeParamName, this.unitType); + } + + this.currency = applicationCurrency; + + final String basePriceParamName = CollateralManagementJsonInputParams.BASE_PRICE.getValue(); + if (command.isChangeInBigDecimalParameterNamed(basePriceParamName, this.basePrice)) { + final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(basePriceParamName); + this.basePrice = newValue; + changes.put(basePriceParamName, this.basePrice); + } + + final String pctToBaseParamName = CollateralManagementJsonInputParams.PCT_TO_BASE.getValue(); + if (command.isChangeInBigDecimalParameterNamed(pctToBaseParamName, this.pctToBase)) { + final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(pctToBaseParamName); + this.pctToBase = newValue; + changes.put(pctToBaseParamName, this.pctToBase); + } + + return changes; + } + + public String getQuality() { + return this.quality; + } + + public String getUnitType() { + return this.unitType; + } + + public ApplicationCurrency getCurrency() { + return this.currency; + } + + public BigDecimal getBasePrice() { + return this.basePrice; + } + + public BigDecimal getPctToBase() { + return this.pctToBase; + } + + public String getName() { + return this.name; + } + + public Set getClientCollateralManagements() { + return this.clientCollateralManagements; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/CollateralManagementDomainRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/CollateralManagementDomainRepository.java new file mode 100644 index 000000000..a0ca0f253 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/CollateralManagementDomainRepository.java @@ -0,0 +1,27 @@ +/** + * 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.collateralmanagement.domain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +public interface CollateralManagementDomainRepository + extends JpaRepository, JpaSpecificationExecutor { + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/CollateralManagementRepositoryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/CollateralManagementRepositoryWrapper.java new file mode 100644 index 000000000..e899ddd3a --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/domain/CollateralManagementRepositoryWrapper.java @@ -0,0 +1,56 @@ +/** + * 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.collateralmanagement.domain; + +import java.util.List; +import org.apache.fineract.portfolio.collateral.exception.CollateralNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class CollateralManagementRepositoryWrapper { + + private final CollateralManagementDomainRepository collateralManagementDomainRepository; + + @Autowired + public CollateralManagementRepositoryWrapper(final CollateralManagementDomainRepository collateralManagementDomainRepository) { + this.collateralManagementDomainRepository = collateralManagementDomainRepository; + } + + public CollateralManagementDomain create(CollateralManagementDomain collateralData) { + return this.collateralManagementDomainRepository.save(collateralData); + } + + public CollateralManagementDomain getCollateral(Long collateralId) { + return this.collateralManagementDomainRepository.findById(collateralId) + .orElseThrow(() -> new CollateralNotFoundException(collateralId)); + } + + public List getAllCollaterals() { + return this.collateralManagementDomainRepository.findAll(); + } + + public CollateralManagementDomain update(CollateralManagementDomain collateralManagementData) { + return this.collateralManagementDomainRepository.saveAndFlush(collateralManagementData); + } + + public void delete(final Long collateralId) { + this.collateralManagementDomainRepository.deleteById(collateralId); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/ClientCollateralCannotBeDeletedException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/ClientCollateralCannotBeDeletedException.java new file mode 100644 index 000000000..c49ac3f91 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/ClientCollateralCannotBeDeletedException.java @@ -0,0 +1,49 @@ +/** + * 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.collateralmanagement.exception; + +import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException; + +public class ClientCollateralCannotBeDeletedException extends AbstractPlatformDomainRuleException { + + /*** enum of reasons of why Collateral cannot be waived **/ + public enum ClientCollateralCannotBeDeletedReason { + + CLIENT_COLLATERAL_IS_ALREADY_ATTACHED; + + public String errorMessage() { + if (name().equalsIgnoreCase("CLIENT_COLLATERAL_IS_ALREADY_ATTACHED")) { + return "This client collateral cannot be deleted as this is associated with one or more loan collaterals"; + } + return name(); + } + + public String errorCode() { + if (name().equalsIgnoreCase("CLIENT_COLLATERAL_IS_ALREADY_ATTACHED")) { + return "error.msg.client.collateral.is.already.associated.with.loan.collateral"; + } + return name().toString(); + } + } + + public ClientCollateralCannotBeDeletedException(final ClientCollateralCannotBeDeletedReason reason, final Long loanCollateralId) { + super(reason.errorCode(), reason.errorMessage(), loanCollateralId); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/ClientCollateralNotFoundException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/ClientCollateralNotFoundException.java new file mode 100644 index 000000000..4eb41e08c --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/ClientCollateralNotFoundException.java @@ -0,0 +1,29 @@ +/** + * 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.collateralmanagement.exception; + +import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException; + +public class ClientCollateralNotFoundException extends AbstractPlatformResourceNotFoundException { + + public ClientCollateralNotFoundException(final Long id) { + super("error.msg.client.collateral.id.invalid", "Collateral with identifier " + id + " does not exist", id); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/CollateralCannotBeDeletedException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/CollateralCannotBeDeletedException.java new file mode 100644 index 000000000..d0e7e284b --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/CollateralCannotBeDeletedException.java @@ -0,0 +1,49 @@ +/** + * 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.collateralmanagement.exception; + +import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException; + +public class CollateralCannotBeDeletedException extends AbstractPlatformDomainRuleException { + + /*** enum of reasons of why Collateral cannot be waived **/ + public enum CollateralCannotBeDeletedReason { + + COLLATERAL_IS_ALREADY_ATTACHED; + + public String errorMessage() { + if (name().equalsIgnoreCase("COLLATERAL_IS_ALREADY_ATTACHED")) { + return "This collateral cannot be deleted as this is associated with one or more client collaterals"; + } + return name(); + } + + public String errorCode() { + if (name().equalsIgnoreCase("COLLATERAL_IS_ALREADY_ATTACHED")) { + return "error.msg.collateral.is.already.associated.with.client.collateral"; + } + return name(); + } + } + + public CollateralCannotBeDeletedException(final CollateralCannotBeDeletedReason reason, final Long loanCollateralId) { + super(reason.errorCode(), reason.errorMessage(), loanCollateralId); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/CollateralNotFoundException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/CollateralNotFoundException.java new file mode 100644 index 000000000..88f72bf7d --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/CollateralNotFoundException.java @@ -0,0 +1,28 @@ +/** + * 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.collateralmanagement.exception; + +import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException; + +public class CollateralNotFoundException extends AbstractPlatformResourceNotFoundException { + + public CollateralNotFoundException(final Long id) { + super("error.msg.collateral.id.invalid", "Collateral with identifier " + id + " does not exist", id); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/LoanCollateralAmountNotSufficientException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/LoanCollateralAmountNotSufficientException.java new file mode 100644 index 000000000..aae670800 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/LoanCollateralAmountNotSufficientException.java @@ -0,0 +1,31 @@ +/** + * 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.collateralmanagement.exception; + +import java.math.BigDecimal; +import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException; + +public class LoanCollateralAmountNotSufficientException extends AbstractPlatformDomainRuleException { + + public LoanCollateralAmountNotSufficientException(final BigDecimal amount) { + super("error.msg.loan.disbursement.amount.not.sufficient", + "The disbursement amount `" + amount + "`" + "` is invalid or insufficient to disburse the loan.", new Object[] { amount }); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/LoanCollateralManagementNotFoundException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/LoanCollateralManagementNotFoundException.java new file mode 100644 index 000000000..192de0070 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/exception/LoanCollateralManagementNotFoundException.java @@ -0,0 +1,29 @@ +/** + * 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.collateralmanagement.exception; + +import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException; + +public class LoanCollateralManagementNotFoundException extends AbstractPlatformResourceNotFoundException { + + public LoanCollateralManagementNotFoundException(final Long id) { + super("error.msg.loan.collateral.id.invalid", "Loan Collateral with identifier " + id + " does not exist", id); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/AddClientCollateralProductCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/AddClientCollateralProductCommandHandler.java new file mode 100644 index 000000000..315b391e3 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/AddClientCollateralProductCommandHandler.java @@ -0,0 +1,47 @@ +/** + * 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.collateralmanagement.handler; + +import javax.transaction.Transactional; +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.collateralmanagement.service.ClientCollateralManagementWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +@CommandType(entity = "CLIENT_COLLATERAL_PRODUCT", action = "CREATE") +public class AddClientCollateralProductCommandHandler implements NewCommandSourceHandler { + + private final ClientCollateralManagementWritePlatformService clientCollateralManagementWritePlatformService; + + @Autowired + public AddClientCollateralProductCommandHandler( + final ClientCollateralManagementWritePlatformService clientCollateralManagementWritePlatformService) { + this.clientCollateralManagementWritePlatformService = clientCollateralManagementWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand jsonCommand) { + return this.clientCollateralManagementWritePlatformService.addClientCollateralProduct(jsonCommand); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/CreateCollateralProductCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/CreateCollateralProductCommandHandler.java new file mode 100644 index 000000000..c9309109f --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/CreateCollateralProductCommandHandler.java @@ -0,0 +1,46 @@ +/** + * 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.collateralmanagement.handler; + +import javax.transaction.Transactional; +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.collateralmanagement.service.CollateralManagementWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +@CommandType(entity = "COLLATERAL_PRODUCT", action = "CREATE") +public class CreateCollateralProductCommandHandler implements NewCommandSourceHandler { + + private final CollateralManagementWritePlatformService collateralManagementWritePlatformService; + + @Autowired + public CreateCollateralProductCommandHandler(final CollateralManagementWritePlatformService collateralManagementWritePlatformService) { + this.collateralManagementWritePlatformService = collateralManagementWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand jsonCommand) { + return this.collateralManagementWritePlatformService.createCollateral(jsonCommand); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/DeleteClientCollateralProductCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/DeleteClientCollateralProductCommandHandler.java new file mode 100644 index 000000000..01d083bec --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/DeleteClientCollateralProductCommandHandler.java @@ -0,0 +1,47 @@ +/** + * 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.collateralmanagement.handler; + +import javax.transaction.Transactional; +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.collateralmanagement.service.ClientCollateralManagementWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +@CommandType(entity = "CLIENT_COLLATERAL_PRODUCT", action = "DELETE") +public class DeleteClientCollateralProductCommandHandler implements NewCommandSourceHandler { + + private final ClientCollateralManagementWritePlatformService clientCollateralManagementWritePlatformService; + + @Autowired + public DeleteClientCollateralProductCommandHandler( + final ClientCollateralManagementWritePlatformService clientCollateralManagementWritePlatformService) { + this.clientCollateralManagementWritePlatformService = clientCollateralManagementWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(JsonCommand command) { + return this.clientCollateralManagementWritePlatformService.deleteClientCollateralProduct(command.entityId()); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/DeleteCollateralProductHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/DeleteCollateralProductHandler.java new file mode 100644 index 000000000..c4cf1c012 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/DeleteCollateralProductHandler.java @@ -0,0 +1,46 @@ +/** + * 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.collateralmanagement.handler; + +import javax.transaction.Transactional; +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.collateralmanagement.service.CollateralManagementWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +@CommandType(entity = "COLLATERAL_PRODUCT", action = "DELETE") +public class DeleteCollateralProductHandler implements NewCommandSourceHandler { + + private final CollateralManagementWritePlatformService collateralManagementWritePlatformService; + + @Autowired + public DeleteCollateralProductHandler(final CollateralManagementWritePlatformService collateralManagementWritePlatformService) { + this.collateralManagementWritePlatformService = collateralManagementWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(JsonCommand command) { + return this.collateralManagementWritePlatformService.deleteCollateral(command.entityId()); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/DeleteLoanCollateralManagement.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/DeleteLoanCollateralManagement.java new file mode 100644 index 000000000..355011530 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/DeleteLoanCollateralManagement.java @@ -0,0 +1,46 @@ +/** + * 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.collateralmanagement.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralManagementWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "LOAN_COLLATERAL_PRODUCT", action = "DELETE") +public class DeleteLoanCollateralManagement implements NewCommandSourceHandler { + + private final LoanCollateralManagementWritePlatformService loanCollateralManagementWritePlatformService; + + @Autowired + public DeleteLoanCollateralManagement(final LoanCollateralManagementWritePlatformService loanCollateralManagement) { + this.loanCollateralManagementWritePlatformService = loanCollateralManagement; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand jsonCommand) { + return this.loanCollateralManagementWritePlatformService.deleteLoanCollateral(jsonCommand); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/UpdateClientCollateralProductCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/UpdateClientCollateralProductCommandHandler.java new file mode 100644 index 000000000..e95d1152c --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/UpdateClientCollateralProductCommandHandler.java @@ -0,0 +1,47 @@ +/** + * 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.collateralmanagement.handler; + +import javax.transaction.Transactional; +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.collateralmanagement.service.ClientCollateralManagementWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +@CommandType(entity = "CLIENT_COLLATERAL_PRODUCT", action = "UPDATE") +public class UpdateClientCollateralProductCommandHandler implements NewCommandSourceHandler { + + private final ClientCollateralManagementWritePlatformService clientCollateralManagementWritePlatformService; + + @Autowired + public UpdateClientCollateralProductCommandHandler( + final ClientCollateralManagementWritePlatformService clientCollateralManagementWritePlatformService) { + this.clientCollateralManagementWritePlatformService = clientCollateralManagementWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand jsonCommand) { + return this.clientCollateralManagementWritePlatformService.updateClientCollateralProduct(jsonCommand); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/UpdateCollateralProductCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/UpdateCollateralProductCommandHandler.java new file mode 100644 index 000000000..79f61f1ba --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/handler/UpdateCollateralProductCommandHandler.java @@ -0,0 +1,47 @@ +/** + * 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.collateralmanagement.handler; + +import javax.transaction.Transactional; +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.collateralmanagement.service.CollateralManagementWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +@CommandType(entity = "COLLATERAL_PRODUCT", action = "UPDATE") +public class UpdateCollateralProductCommandHandler implements NewCommandSourceHandler { + + private final CollateralManagementWritePlatformService collateralManagementWritePlatformService; + + @Autowired + public UpdateCollateralProductCommandHandler(final CollateralManagementWritePlatformService collateralManagementWritePlatformService) { + this.collateralManagementWritePlatformService = collateralManagementWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.collateralManagementWritePlatformService.updateCollateral(command.entityId(), command); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/serialization/CollateralManagementCommandFromApiJsonDeserializer.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/serialization/CollateralManagementCommandFromApiJsonDeserializer.java new file mode 100644 index 000000000..2bf2cd42f --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/serialization/CollateralManagementCommandFromApiJsonDeserializer.java @@ -0,0 +1,33 @@ +/** + * 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.collateralmanagement.serialization; + +import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.springframework.beans.factory.annotation.Autowired; + +public class CollateralManagementCommandFromApiJsonDeserializer { + + private final FromJsonHelper fromApiJsonHelper; + + @Autowired + public CollateralManagementCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) { + this.fromApiJsonHelper = fromApiJsonHelper; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementReadPlatformService.java new file mode 100644 index 000000000..4ab0d9fff --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementReadPlatformService.java @@ -0,0 +1,33 @@ +/** + * 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.collateralmanagement.service; + +import java.util.List; +import org.apache.fineract.portfolio.collateralmanagement.data.ClientCollateralManagementData; +import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralTemplateData; + +public interface ClientCollateralManagementReadPlatformService { + + ClientCollateralManagementData getClientCollateralManagementData(Long collateralId); + + List getClientCollaterals(Long clientId, Long prodId); + + List getLoanCollateralTemplate(Long clientId); + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementReadPlatformServiceImpl.java new file mode 100644 index 000000000..0286cc19a --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementReadPlatformServiceImpl.java @@ -0,0 +1,104 @@ +/** + * 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.collateralmanagement.service; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.portfolio.collateralmanagement.data.ClientCollateralManagementData; +import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralTemplateData; +import org.apache.fineract.portfolio.collateralmanagement.data.LoanTransactionData; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagementRepositoryWrapper; +import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement; +import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction; +import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository; +import org.apache.fineract.portfolio.loanaccount.exception.LoanTransactionNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ClientCollateralManagementReadPlatformServiceImpl implements ClientCollateralManagementReadPlatformService { + + private final PlatformSecurityContext context; + private final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper; + private final LoanTransactionRepository loanTransactionRepository; + + @Autowired + public ClientCollateralManagementReadPlatformServiceImpl(final PlatformSecurityContext context, + final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper, + final LoanTransactionRepository loanTransactionRepository) { + this.context = context; + this.clientCollateralManagementRepositoryWrapper = clientCollateralManagementRepositoryWrapper; + this.loanTransactionRepository = loanTransactionRepository; + } + + @Override + public List getClientCollaterals(final Long clientId, final Long prodId) { + return this.clientCollateralManagementRepositoryWrapper.getClientCollateralData(clientId, prodId); + } + + @Override + public List getLoanCollateralTemplate(Long clientId) { + this.context.authenticatedUser(); + Collection clientCollateralManagements = this.clientCollateralManagementRepositoryWrapper + .getCollateralsPerClient(clientId); + List loanCollateralTemplateDataList = new ArrayList<>(); + for (ClientCollateralManagement clientCollateralManagement : clientCollateralManagements) { + loanCollateralTemplateDataList.add(LoanCollateralTemplateData.instanceOf(clientCollateralManagement)); + } + return loanCollateralTemplateDataList; + } + + @Override + public ClientCollateralManagementData getClientCollateralManagementData(final Long collateralId) { + final ClientCollateralManagement clientCollateralManagement = this.clientCollateralManagementRepositoryWrapper + .getCollateral(collateralId); + BigDecimal basePrice = clientCollateralManagement.getCollaterals().getBasePrice(); + BigDecimal pctToBase = clientCollateralManagement.getCollaterals().getPctToBase().divide(BigDecimal.valueOf(100)); + BigDecimal total = BigDecimal.ZERO; + BigDecimal totalCollateral = BigDecimal.ZERO; + BigDecimal quantity = clientCollateralManagement.getQuantity(); + if (quantity.compareTo(BigDecimal.ZERO) != 0) { + total = basePrice.multiply(quantity); + totalCollateral = total.multiply(pctToBase); + } + Set loanCollateralManagementSet = clientCollateralManagement.getLoanCollateralManagementSet(); + + List loanTransactionDataList = new ArrayList<>(); + for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagementSet) { + if (loanCollateralManagement.getLoanTransaction() != null) { + Long transactionId = loanCollateralManagement.getLoanTransaction().getId(); + LoanTransaction loanTransaction = this.loanTransactionRepository.findById(transactionId) + .orElseThrow(() -> new LoanTransactionNotFoundException(transactionId)); + LoanTransactionData loanTransactionData = LoanTransactionData.instance(loanTransaction.getLoan().getId(), + loanTransaction.getCreatedDateTime(), loanTransaction.getOutstandingLoanBalance(), + loanTransaction.getPrincipalPortion()); + loanTransactionDataList.add(loanTransactionData); + } + } + + return ClientCollateralManagementData.instance(clientCollateralManagement.getCollaterals().getName(), + clientCollateralManagement.getQuantity(), total, totalCollateral, clientCollateralManagement.getClient().getId(), + loanTransactionDataList, clientCollateralManagement.getId()); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementWritePlatformService.java new file mode 100644 index 000000000..67c361394 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementWritePlatformService.java @@ -0,0 +1,32 @@ +/** + * 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.collateralmanagement.service; + +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; + +public interface ClientCollateralManagementWritePlatformService { + + CommandProcessingResult addClientCollateralProduct(JsonCommand command); + + CommandProcessingResult updateClientCollateralProduct(JsonCommand command); + + CommandProcessingResult deleteClientCollateralProduct(Long collateralId); + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementWritePlatformServiceImpl.java new file mode 100644 index 000000000..477034d94 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/ClientCollateralManagementWritePlatformServiceImpl.java @@ -0,0 +1,181 @@ +/** + * 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.collateralmanagement.service; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.transaction.Transactional; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.ApiParameterError; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; +import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; +import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; +import org.apache.fineract.portfolio.client.domain.Client; +import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagementRepositoryWrapper; +import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementDomain; +import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementRepositoryWrapper; +import org.apache.fineract.portfolio.collateralmanagement.exception.ClientCollateralCannotBeDeletedException; +import org.apache.fineract.portfolio.collateralmanagement.exception.ClientCollateralNotFoundException; +import org.apache.fineract.portfolio.collateralmanagement.exception.CollateralNotFoundException; +import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ClientCollateralManagementWritePlatformServiceImpl implements ClientCollateralManagementWritePlatformService { + + private final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper; + private final CollateralManagementRepositoryWrapper collateralManagementRepositoryWrapper; + private final ClientRepositoryWrapper clientRepositoryWrapper; + + @Autowired + public ClientCollateralManagementWritePlatformServiceImpl( + final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper, + final CollateralManagementRepositoryWrapper collateralManagementRepositoryWrapper, + final ClientRepositoryWrapper clientRepositoryWrapper) { + this.clientCollateralManagementRepositoryWrapper = clientCollateralManagementRepositoryWrapper; + this.collateralManagementRepositoryWrapper = collateralManagementRepositoryWrapper; + this.clientRepositoryWrapper = clientRepositoryWrapper; + } + + @Transactional + @Override + public CommandProcessingResult addClientCollateralProduct(final JsonCommand command) { + + validateForCreation(command); + + Long collateralId = command.longValueOfParameterNamed("collateralId"); + BigDecimal quantity = command.bigDecimalValueOfParameterNamed("quantity"); + + final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(command.getClientId(), false); + + final CollateralManagementDomain collateralManagementData = this.collateralManagementRepositoryWrapper.getCollateral(collateralId); + final ClientCollateralManagement clientCollateralManagement = ClientCollateralManagement.createNew(quantity, client, + collateralManagementData); + this.clientCollateralManagementRepositoryWrapper.save(clientCollateralManagement); + return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withClientId(command.getClientId()) + .withEntityId(clientCollateralManagement.getId()).build(); + } + + private void validateForCreation(final JsonCommand command) { + + String errorCode = "parameter."; + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("client-collateral"); + + if (!command.parameterExists("collateralId")) { + errorCode += "collateralId.not.exists"; + baseDataValidator.reset().parameter("collateralId").failWithCode(errorCode); + } + + if (!command.parameterExists("quantity")) { + errorCode += ".quantity.not.exists"; + baseDataValidator.reset().parameter("quantity").failWithCode(errorCode); + } else { + BigDecimal quantity = command.bigDecimalValueOfParameterNamed("quantity"); + baseDataValidator.reset().parameter("quantity").value(quantity).notNull().positiveAmount(); + } + + if (!dataValidationErrors.isEmpty()) { + throw new PlatformApiDataValidationException(dataValidationErrors); + } + } + + @Transactional + @Override + public CommandProcessingResult updateClientCollateralProduct(final JsonCommand command) { + validateForUpdate(command); + final ClientCollateralManagement collateral = this.clientCollateralManagementRepositoryWrapper.getCollateral(command.entityId()); + final Map changes = collateral.update(command); + this.clientCollateralManagementRepositoryWrapper.updateClientCollateralProduct(collateral); + return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(command.entityId()) + .withClientId(command.getClientId()).with(changes).build(); + } + + private void validateForUpdate(final JsonCommand command) { + final Long clientCollateralId = command.entityId(); + String errorCode = "parameter."; + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("client-collateral"); + BigDecimal quantity = null; + + if (!command.parameterExists("quantity")) { + errorCode += ".quantity.not.exists"; + baseDataValidator.reset().parameter("quantity").failWithCode(errorCode); + } else { + quantity = command.bigDecimalValueOfParameterNamed("quantity"); + baseDataValidator.reset().parameter("quantity").value(quantity).notNull().positiveAmount(); + } + + final ClientCollateralManagement clientCollateralManagement = this.clientCollateralManagementRepositoryWrapper + .getCollateral(clientCollateralId); + + if (clientCollateralManagement == null) { + throw new ClientCollateralNotFoundException(clientCollateralId); + } + + BigDecimal totalQuantity = BigDecimal.ZERO; + if (clientCollateralManagement.getLoanCollateralManagementSet().size() > 0) { + for (LoanCollateralManagement loanCollateralManagement : clientCollateralManagement.getLoanCollateralManagementSet()) { + totalQuantity = totalQuantity.add(loanCollateralManagement.getQuantity()); + } + } + + if (totalQuantity.compareTo(quantity) >= 0) { + baseDataValidator.reset().parameter("quantity").value(quantity).notLessThanMin(totalQuantity); + } + + if (!dataValidationErrors.isEmpty()) { + throw new PlatformApiDataValidationException(dataValidationErrors); + } + + } + + @Transactional + @Override + public CommandProcessingResult deleteClientCollateralProduct(final Long collateralId) { + final ClientCollateralManagement clientCollateralManagement = this.clientCollateralManagementRepositoryWrapper + .getCollateral(collateralId); + validateForDeletion(clientCollateralManagement, collateralId); + this.clientCollateralManagementRepositoryWrapper.deleteClientCollateralProduct(collateralId); + return new CommandProcessingResultBuilder().withEntityId(collateralId).build(); + } + + private void validateForDeletion(final ClientCollateralManagement clientCollateralManagement, final Long clientCollateralId) { + if (clientCollateralManagement == null) { + throw new CollateralNotFoundException(clientCollateralId); + } + + if (clientCollateralManagement.getLoanCollateralManagementSet().size() > 0) { + for (LoanCollateralManagement loanCollateralManagement : clientCollateralManagement.getLoanCollateralManagementSet()) { + if (loanCollateralManagement.getIsReleased() == 0) { + throw new ClientCollateralCannotBeDeletedException( + ClientCollateralCannotBeDeletedException.ClientCollateralCannotBeDeletedReason.CLIENT_COLLATERAL_IS_ALREADY_ATTACHED, + clientCollateralId); + } + } + } + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/CollateralManagementReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/CollateralManagementReadPlatformService.java new file mode 100644 index 000000000..36532c9d2 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/CollateralManagementReadPlatformService.java @@ -0,0 +1,30 @@ +/** + * 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.collateralmanagement.service; + +import java.util.List; +import org.apache.fineract.portfolio.collateralmanagement.data.CollateralManagementData; + +public interface CollateralManagementReadPlatformService { + + CollateralManagementData getCollateralProduct(Long collateralId); + + List getAllCollateralProducts(); + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/CollateralManagementReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/CollateralManagementReadPlatformServiceImpl.java new file mode 100644 index 000000000..2d61ceca9 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/CollateralManagementReadPlatformServiceImpl.java @@ -0,0 +1,61 @@ +/** + * 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.collateralmanagement.service; + +import java.util.ArrayList; +import java.util.List; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.portfolio.collateralmanagement.data.CollateralManagementData; +import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementDomain; +import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementRepositoryWrapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class CollateralManagementReadPlatformServiceImpl implements CollateralManagementReadPlatformService { + + private final PlatformSecurityContext context; + private final CollateralManagementRepositoryWrapper collateralManagementRepositoryWrapper; + + @Autowired + public CollateralManagementReadPlatformServiceImpl(final PlatformSecurityContext context, + final CollateralManagementRepositoryWrapper collateralManagementRepositoryWrapper) { + this.context = context; + this.collateralManagementRepositoryWrapper = collateralManagementRepositoryWrapper; + } + + @Override + public CollateralManagementData getCollateralProduct(Long collateralId) { + final CollateralManagementDomain collateralManagementDomain = this.collateralManagementRepositoryWrapper + .getCollateral(collateralId); + return CollateralManagementData.createNew(collateralManagementDomain); + } + + @Override + public List getAllCollateralProducts() { + final List collateralManagementDomainSet = this.collateralManagementRepositoryWrapper + .getAllCollaterals(); + List collateralManagementDataList = new ArrayList<>(); + for (CollateralManagementDomain collateralManagementDomain : collateralManagementDomainSet) { + collateralManagementDataList.add(CollateralManagementData.createNew(collateralManagementDomain)); + } + return collateralManagementDataList; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/CollateralManagementWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/CollateralManagementWritePlatformService.java new file mode 100644 index 000000000..ca55c622d --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/CollateralManagementWritePlatformService.java @@ -0,0 +1,31 @@ +/** + * 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.collateralmanagement.service; + +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; + +public interface CollateralManagementWritePlatformService { + + CommandProcessingResult createCollateral(JsonCommand command); + + CommandProcessingResult updateCollateral(Long collateralId, JsonCommand command); + + CommandProcessingResult deleteCollateral(Long collateralId); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/CollateralManagementWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/CollateralManagementWritePlatformServiceImpl.java new file mode 100644 index 000000000..fcaca36d2 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/CollateralManagementWritePlatformServiceImpl.java @@ -0,0 +1,176 @@ +/** + * 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.collateralmanagement.service; + +import com.google.gson.JsonElement; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.ApiParameterError; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; +import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; +import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; +import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency; +import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepository; +import org.apache.fineract.portfolio.collateralmanagement.api.CollateralManagementJsonInputParams; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement; +import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementDomain; +import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementRepositoryWrapper; +import org.apache.fineract.portfolio.collateralmanagement.exception.CollateralCannotBeDeletedException; +import org.apache.fineract.portfolio.collateralmanagement.exception.CollateralNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class CollateralManagementWritePlatformServiceImpl implements CollateralManagementWritePlatformService { + + private final CollateralManagementRepositoryWrapper collateralManagementRepositoryWrapper; + private final ApplicationCurrencyRepository applicationCurrencyRepository; + private final FromJsonHelper fromApiJsonHelper; + + @Autowired + public CollateralManagementWritePlatformServiceImpl(final CollateralManagementRepositoryWrapper collateralManagementRepositoryWrapper, + final ApplicationCurrencyRepository applicationCurrencyRepository, final FromJsonHelper fromApiJsonHelper) { + this.collateralManagementRepositoryWrapper = collateralManagementRepositoryWrapper; + this.applicationCurrencyRepository = applicationCurrencyRepository; + this.fromApiJsonHelper = fromApiJsonHelper; + } + + @Transactional + @Override + public CommandProcessingResult createCollateral(final JsonCommand jsonCommand) { + validateForCreation(jsonCommand); + final String currencyParamName = jsonCommand.stringValueOfParameterNamed(CollateralManagementJsonInputParams.CURRENCY.getValue()); + final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneByCode(currencyParamName); + + final CollateralManagementDomain collateral = CollateralManagementDomain.createNew(jsonCommand, applicationCurrency); + this.collateralManagementRepositoryWrapper.create(collateral); + return new CommandProcessingResultBuilder().withCommandId(jsonCommand.commandId()).withEntityId(collateral.getId()).build(); + } + + private void validateForCreation(JsonCommand jsonCommand) { + final JsonElement jsonElement = this.fromApiJsonHelper.parse(jsonCommand.json()); + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("collateral-management"); + + if (!jsonCommand.parameterExists("locale")) { + baseDataValidator.reset().parameter("locale").notNull().failWithCode("locale.not.exists"); + } else { + final String locale = this.fromApiJsonHelper.extractStringNamed("locale", jsonElement); + baseDataValidator.reset().parameter("locale").value(locale).notNull(); + } + + if (!jsonCommand.parameterExists(CollateralManagementJsonInputParams.CURRENCY.getValue())) { + baseDataValidator.reset().parameter(CollateralManagementJsonInputParams.CURRENCY.getValue()).notNull() + .failWithCode("currency.not.exists"); + } else { + final String currency = this.fromApiJsonHelper.extractStringNamed("currency", jsonElement); + baseDataValidator.reset().parameter("currency").value(currency).notNull(); + } + + if (!jsonCommand.parameterExists("quality")) { + baseDataValidator.reset().parameter(CollateralManagementJsonInputParams.QUALITY.getValue()).notNull() + .failWithCode("quality.not.exists"); + } else { + final String quality = this.fromApiJsonHelper.extractStringNamed("quality", jsonElement); + baseDataValidator.reset().parameter("quality").value(quality).notNull(); + } + + if (!jsonCommand.parameterExists("basePrice")) { + baseDataValidator.reset().parameter("basePrice").notNull().notBlank().failWithCode("basePrice.not.exists"); + } else { + final BigDecimal basePrice = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("basePrice", jsonElement); + baseDataValidator.reset().parameter("basePrice").value(basePrice).notNull().positiveAmount(); + } + + if (!jsonCommand.parameterExists("unitType")) { + baseDataValidator.reset().parameter("unitType").notNull().notBlank().failWithCode("unitType.not.exists"); + } else { + final String unitType = this.fromApiJsonHelper.extractStringNamed("unitType", jsonElement); + baseDataValidator.reset().parameter("unitType").value(unitType).notNull(); + } + + if (!jsonCommand.parameterExists("pctToBase")) { + baseDataValidator.reset().parameter("pctToBase").notNull().notBlank().failWithCode("pctToBase.not.exists"); + } else { + final BigDecimal basePrice = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("pctToBase", jsonElement); + baseDataValidator.reset().parameter("pctToBase").value(basePrice).notNull().positiveAmount(); + } + + if (!jsonCommand.parameterExists("name")) { + baseDataValidator.reset().parameter("name").notNull().notBlank().failWithCode("name.not.exists"); + } else { + final String unitType = this.fromApiJsonHelper.extractStringNamed("name", jsonElement); + baseDataValidator.reset().parameter("name").value(unitType).notNull(); + } + + if (!dataValidationErrors.isEmpty()) { + throw new PlatformApiDataValidationException(dataValidationErrors); + } + } + + @Transactional + @Override + public CommandProcessingResult updateCollateral(final Long collateralId, JsonCommand jsonCommand) { + final CollateralManagementDomain collateral = this.collateralManagementRepositoryWrapper.getCollateral(collateralId); + final String currencyParamName = CollateralManagementJsonInputParams.CURRENCY.getValue(); + final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository + .findOneByCode(jsonCommand.stringValueOfParameterNamed(currencyParamName)); + if (jsonCommand.isChangeInStringParameterNamed(currencyParamName, applicationCurrency.getCode())) { + final String newValue = jsonCommand.stringValueOfParameterNamed(currencyParamName); + applicationCurrency.setCode(newValue); + } + final Map changes = collateral.update(jsonCommand, applicationCurrency); + this.collateralManagementRepositoryWrapper.update(collateral); + return new CommandProcessingResultBuilder().withCommandId(jsonCommand.commandId()).withEntityId(jsonCommand.entityId()) + .with(changes).build(); + } + + @Transactional + @Override + public CommandProcessingResult deleteCollateral(final Long collateralId) { + final CollateralManagementDomain collateralManagementDomain = this.collateralManagementRepositoryWrapper + .getCollateral(collateralId); + validateForDeletion(collateralManagementDomain, collateralId); + this.collateralManagementRepositoryWrapper.delete(collateralId); + return new CommandProcessingResultBuilder().withEntityId(collateralId).build(); + } + + private void validateForDeletion(final CollateralManagementDomain collateralManagementDomain, final Long collateralId) { + if (collateralManagementDomain == null) { + throw new CollateralNotFoundException(collateralId); + } + + if (collateralManagementDomain.getClientCollateralManagements().size() > 0) { + for (ClientCollateralManagement clientCollateralManagement : collateralManagementDomain.getClientCollateralManagements()) { + if (clientCollateralManagement.getQuantity().compareTo(BigDecimal.ZERO) > 0) { + throw new CollateralCannotBeDeletedException( + CollateralCannotBeDeletedException.CollateralCannotBeDeletedReason.COLLATERAL_IS_ALREADY_ATTACHED, + collateralId); + } + } + } + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralAssembler.java new file mode 100644 index 000000000..37b6f48a1 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralAssembler.java @@ -0,0 +1,106 @@ +/** + * 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.collateralmanagement.service; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; +import org.apache.fineract.infrastructure.codes.domain.CodeValueRepositoryWrapper; +import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagementRepositoryWrapper; +import org.apache.fineract.portfolio.collateralmanagement.exception.LoanCollateralManagementNotFoundException; +import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement; +import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagementRepository; +import org.apache.fineract.portfolio.loanaccount.exception.InvalidAmountOfCollateralQuantity; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class LoanCollateralAssembler { + + private final FromJsonHelper fromApiJsonHelper; + private final CodeValueRepositoryWrapper codeValueRepository; + private final LoanCollateralManagementRepository loanCollateralRepository; + private final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper; + + @Autowired + public LoanCollateralAssembler(final FromJsonHelper fromApiJsonHelper, final CodeValueRepositoryWrapper codeValueRepository, + final LoanCollateralManagementRepository loanCollateralRepository, + final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper) { + this.fromApiJsonHelper = fromApiJsonHelper; + this.codeValueRepository = codeValueRepository; + this.loanCollateralRepository = loanCollateralRepository; + this.clientCollateralManagementRepositoryWrapper = clientCollateralManagementRepositoryWrapper; + } + + public Set fromParsedJson(final JsonElement element) { + + final Set collateralItems = new HashSet<>(); + + JsonObject jsonObject = element.getAsJsonObject(); + final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(jsonObject); + + if (jsonObject.has("collateral") && jsonObject.get("collateral").isJsonArray()) { + JsonArray collaterals = jsonObject.get("collateral").getAsJsonArray(); + + for (int i = 0; i < collaterals.size(); i++) { + final JsonObject collateralItemElement = collaterals.get(i).getAsJsonObject(); + final Long id = this.fromApiJsonHelper.extractLongNamed("id", collateralItemElement); + final Long collateralId = this.fromApiJsonHelper.extractLongNamed("clientCollateralId", collateralItemElement); + final ClientCollateralManagement clientCollateral = this.clientCollateralManagementRepositoryWrapper + .getCollateral(collateralId); + final BigDecimal quantity = this.fromApiJsonHelper.extractBigDecimalNamed("quantity", collateralItemElement, locale); + BigDecimal updatedClientQuantity = null; + + if (id == null) { + updatedClientQuantity = clientCollateral.getQuantity().subtract(quantity); + if (BigDecimal.ZERO.compareTo(updatedClientQuantity) > 0) { + throw new InvalidAmountOfCollateralQuantity(quantity); + } + clientCollateral.updateQuantity(updatedClientQuantity); + collateralItems.add(LoanCollateralManagement.from(clientCollateral, quantity)); + } else { + LoanCollateralManagement loanCollateralManagement = this.loanCollateralRepository.findById(id) + .orElseThrow(() -> new LoanCollateralManagementNotFoundException(id)); + + if (loanCollateralManagement.getQuantity().compareTo(quantity) != 0) { + updatedClientQuantity = clientCollateral.getQuantity().add(loanCollateralManagement.getQuantity()) + .subtract(quantity); + if (BigDecimal.ZERO.compareTo(updatedClientQuantity) > 0) { + throw new InvalidAmountOfCollateralQuantity(quantity); + } + } else { + updatedClientQuantity = quantity; + } + + clientCollateral.updateQuantity(updatedClientQuantity); + collateralItems + .add(LoanCollateralManagement.fromExisting(clientCollateral, quantity, loanCollateralManagement.getLoanData(), + loanCollateralManagement.getLoanTransaction(), loanCollateralManagement.getId())); + } + } + } + return collateralItems; + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralManagementReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralManagementReadPlatformService.java new file mode 100644 index 000000000..bd5da462f --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralManagementReadPlatformService.java @@ -0,0 +1,32 @@ +/** + * 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.collateralmanagement.service; + +import java.util.List; +import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralResponseData; +import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement; + +public interface LoanCollateralManagementReadPlatformService { + + List getLoanCollaterals(Long loanId); + + LoanCollateralResponseData getLoanCollateralResponseData(Long collateralId); + + List getLoanCollateralResponseDataList(Long loanId); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralManagementReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralManagementReadPlatformServiceImpl.java new file mode 100644 index 000000000..8c3ae4b05 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralManagementReadPlatformServiceImpl.java @@ -0,0 +1,90 @@ +/** + * 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.collateralmanagement.service; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralResponseData; +import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementDomain; +import org.apache.fineract.portfolio.collateralmanagement.exception.LoanCollateralManagementNotFoundException; +import org.apache.fineract.portfolio.loanaccount.domain.Loan; +import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement; +import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagementRepository; +import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository; +import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class LoanCollateralManagementReadPlatformServiceImpl implements LoanCollateralManagementReadPlatformService { + + private final PlatformSecurityContext context; + private LoanCollateralManagementRepository loanCollateralManagementRepository; + private LoanRepository loanRepository; + + @Autowired + public LoanCollateralManagementReadPlatformServiceImpl(final PlatformSecurityContext context, + final LoanCollateralManagementRepository loanCollateralManagementRepository, final LoanRepository loanRepository) { + this.context = context; + this.loanCollateralManagementRepository = loanCollateralManagementRepository; + this.loanRepository = loanRepository; + } + + @Override + public List getLoanCollaterals(Long loanId) { + this.context.authenticatedUser(); + Loan loan = this.loanRepository.findById(loanId).orElseThrow(() -> new LoanNotFoundException(loanId)); + return this.loanCollateralManagementRepository.findByLoan(loan); + } + + @Override + public LoanCollateralResponseData getLoanCollateralResponseData(Long collateralId) { + this.context.authenticatedUser(); + LoanCollateralManagement loanCollateralManagement = this.loanCollateralManagementRepository.findById(collateralId) + .orElseThrow(() -> new LoanCollateralManagementNotFoundException(collateralId)); + final CollateralManagementDomain collateralManagementDomain = loanCollateralManagement.getClientCollateralManagement() + .getCollaterals(); + BigDecimal quantity = loanCollateralManagement.getQuantity(); + BigDecimal total = quantity.multiply(collateralManagementDomain.getBasePrice()); + BigDecimal totalCollateral = total.multiply(collateralManagementDomain.getPctToBase()).divide(BigDecimal.valueOf(100)); + return LoanCollateralResponseData.instanceOf(loanCollateralManagement, total, totalCollateral); + } + + @Override + public List getLoanCollateralResponseDataList(Long loanId) { + this.context.authenticatedUser(); + Loan loan = this.loanRepository.findById(loanId).orElseThrow(() -> new LoanNotFoundException(loanId)); + List loanCollateralResponseDataCollection = new ArrayList<>(); + Set loanCollateralManagements = loan.getLoanCollateralManagements(); + for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagements) { + final CollateralManagementDomain collateralManagementDomain = loanCollateralManagement.getClientCollateralManagement() + .getCollaterals(); + BigDecimal quantity = loanCollateralManagement.getQuantity(); + BigDecimal total = quantity.multiply(collateralManagementDomain.getBasePrice()); + BigDecimal totalCollateral = total.multiply(collateralManagementDomain.getPctToBase()).divide(BigDecimal.valueOf(100)); + loanCollateralResponseDataCollection + .add(LoanCollateralResponseData.instanceOf(loanCollateralManagement, total, totalCollateral)); + } + return loanCollateralResponseDataCollection; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralManagementWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralManagementWritePlatformService.java new file mode 100644 index 000000000..ed5c0a65c --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralManagementWritePlatformService.java @@ -0,0 +1,27 @@ +/** + * 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.collateralmanagement.service; + +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; + +public interface LoanCollateralManagementWritePlatformService { + + CommandProcessingResult deleteLoanCollateral(JsonCommand command); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralManagementWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralManagementWritePlatformServiceImpl.java new file mode 100644 index 000000000..3f53fc76a --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/collateralmanagement/service/LoanCollateralManagementWritePlatformServiceImpl.java @@ -0,0 +1,60 @@ +/** + * 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.collateralmanagement.service; + +import java.math.BigDecimal; +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.portfolio.collateralmanagement.domain.ClientCollateralManagement; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagementRepositoryWrapper; +import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement; +import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagementRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class LoanCollateralManagementWritePlatformServiceImpl implements LoanCollateralManagementWritePlatformService { + + private final LoanCollateralManagementRepository loanCollateralManagementRepository; + private final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper; + + @Autowired + public LoanCollateralManagementWritePlatformServiceImpl(final LoanCollateralManagementRepository loanCollateralManagementRepository, + final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper) { + this.loanCollateralManagementRepository = loanCollateralManagementRepository; + this.clientCollateralManagementRepositoryWrapper = clientCollateralManagementRepositoryWrapper; + } + + @Transactional + @Override + public CommandProcessingResult deleteLoanCollateral(JsonCommand command) { + final Long id = command.entityId(); + final LoanCollateralManagement loanCollateralManagement = this.loanCollateralManagementRepository.findById(id).orElseThrow(); + ClientCollateralManagement clientCollateralManagement = loanCollateralManagement.getClientCollateralManagement(); + BigDecimal loanQuantity = loanCollateralManagement.getQuantity(); + BigDecimal clientQuantity = clientCollateralManagement.getQuantity(); + clientCollateralManagement.updateQuantity(clientQuantity.add(loanQuantity)); + this.clientCollateralManagementRepositoryWrapper.saveAndFlush(clientCollateralManagement); + this.loanCollateralManagementRepository.deleteById(id); + return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(id).withLoanId(command.getLoanId()) + .build(); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java index d118927a2..f23c3bc15 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java @@ -99,6 +99,7 @@ public interface LoanApiConstants { String APPROVED_AMOUNT_IS_LESS_THAN_SUM_OF_TRANCHES = "sum.of.multi.disburse.amounts.must.be.equal.to.or.lesser.than.approved.principal"; String DISBURSEMENT_DATES_NOT_IN_ORDER = "disbursements.should.be.ordered.based.on.their.disbursement.dates"; String DISBURSEMENT_DATE_BEFORE_ERROR = "disbursement.date.of.tranche.cannot.be.before.expected.disbursement.date"; + String LOAN_COLLATERAL_TOTAL_VALUE_SHOULD_BE_SUFFICIENT = "sum.of.multi.collateral.values.must.equal.or.greater.than.principal.amount"; String isFloatingInterestRate = "isFloatingInterestRate"; String interestRateDifferential = "interestRateDifferential"; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java index 596c403af..d6db052e4 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java @@ -98,6 +98,8 @@ import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService; import org.apache.fineract.portfolio.client.data.ClientData; import org.apache.fineract.portfolio.collateral.data.CollateralData; import org.apache.fineract.portfolio.collateral.service.CollateralReadPlatformService; +import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralResponseData; +import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralManagementReadPlatformService; import org.apache.fineract.portfolio.floatingrates.data.InterestRatePeriodData; import org.apache.fineract.portfolio.fund.data.FundData; import org.apache.fineract.portfolio.fund.service.FundReadPlatformService; @@ -108,6 +110,7 @@ import org.apache.fineract.portfolio.loanaccount.data.GlimRepaymentTemplate; import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData; import org.apache.fineract.portfolio.loanaccount.data.LoanApprovalData; import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData; +import org.apache.fineract.portfolio.loanaccount.data.LoanCollateralManagementData; import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData; import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData; import org.apache.fineract.portfolio.loanaccount.data.PaidInAdvanceData; @@ -253,6 +256,7 @@ public class LoansApiResource { private final ConfigurationDomainService configurationDomainService; private final DefaultToApiJsonSerializer glimTemplateToApiJsonSerializer; private final GLIMAccountInfoReadPlatformService glimAccountInfoReadPlatformService; + private final LoanCollateralManagementReadPlatformService loanCollateralManagementReadPlatformService; @Autowired public LoansApiResource(final PlatformSecurityContext context, final LoanReadPlatformService loanReadPlatformService, @@ -278,7 +282,8 @@ public class LoansApiResource { final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService, final RateReadService rateReadService, final ConfigurationDomainService configurationDomainService, final DefaultToApiJsonSerializer glimTemplateToApiJsonSerializer, - final GLIMAccountInfoReadPlatformService glimAccountInfoReadPlatformService) { + final GLIMAccountInfoReadPlatformService glimAccountInfoReadPlatformService, + final LoanCollateralManagementReadPlatformService loanCollateralManagementReadPlatformService) { this.context = context; this.loanReadPlatformService = loanReadPlatformService; this.loanProductReadPlatformService = loanProductReadPlatformService; @@ -310,6 +315,7 @@ public class LoansApiResource { this.configurationDomainService = configurationDomainService; this.glimTemplateToApiJsonSerializer = glimTemplateToApiJsonSerializer; this.glimAccountInfoReadPlatformService = glimAccountInfoReadPlatformService; + this.loanCollateralManagementReadPlatformService = loanCollateralManagementReadPlatformService; } /* @@ -535,6 +541,8 @@ public class LoansApiResource { PortfolioAccountData linkedAccount = null; Collection disbursementData = null; Collection emiAmountVariations = null; + Collection loanCollateralManagements = null; + Collection loanCollateralManagementData = new ArrayList<>(); final Set mandatoryResponseParameters = new HashSet<>(); final Set associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters()); @@ -604,9 +612,12 @@ public class LoansApiResource { if (associationParameters.contains("collateral")) { mandatoryResponseParameters.add("collateral"); - collateral = this.loanCollateralReadPlatformService.retrieveCollaterals(loanId); - if (CollectionUtils.isEmpty(collateral)) { - collateral = null; + loanCollateralManagements = this.loanCollateralManagementReadPlatformService.getLoanCollateralResponseDataList(loanId); + for (LoanCollateralResponseData loanCollateralManagement : loanCollateralManagements) { + loanCollateralManagementData.add(loanCollateralManagement.toCommand()); + } + if (CollectionUtils.isEmpty(loanCollateralManagements)) { + loanCollateralManagements = null; } } @@ -725,12 +736,12 @@ public class LoansApiResource { } final LoanAccountData loanAccount = LoanAccountData.associationsAndTemplate(loanBasicDetails, repaymentSchedule, loanRepayments, - charges, collateral, guarantors, meeting, productOptions, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions, - repaymentFrequencyNthDayTypeOptions, repaymentFrequencyDayOfWeekTypeOptions, repaymentStrategyOptions, - interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, - fundOptions, chargeOptions, chargeTemplate, allowedLoanOfficers, loanPurposeOptions, loanCollateralOptions, calendarOptions, - notes, accountLinkingOptions, linkedAccount, disbursementData, emiAmountVariations, overdueCharges, paidInAdvanceTemplate, - interestRatesPeriods, clientActiveLoanOptions, rates, isRatesEnabled); + charges, loanCollateralManagementData, guarantors, meeting, productOptions, loanTermFrequencyTypeOptions, + repaymentFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions, repaymentFrequencyDayOfWeekTypeOptions, + repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, + interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, allowedLoanOfficers, loanPurposeOptions, + loanCollateralOptions, calendarOptions, notes, accountLinkingOptions, linkedAccount, disbursementData, emiAmountVariations, + overdueCharges, paidInAdvanceTemplate, interestRatesPeriods, clientActiveLoanOptions, rates, isRatesEnabled); final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters(), mandatoryResponseParameters); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java index 462aa9f5a..9279a5262 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java @@ -37,7 +37,6 @@ import org.apache.fineract.portfolio.account.data.PortfolioAccountData; import org.apache.fineract.portfolio.accountdetails.data.LoanAccountSummaryData; import org.apache.fineract.portfolio.calendar.data.CalendarData; import org.apache.fineract.portfolio.charge.data.ChargeData; -import org.apache.fineract.portfolio.collateral.data.CollateralData; import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType; import org.apache.fineract.portfolio.floatingrates.data.InterestRatePeriodData; import org.apache.fineract.portfolio.fund.data.FundData; @@ -135,7 +134,7 @@ public final class LoanAccountData { private final LoanScheduleData repaymentSchedule; private final Collection transactions; private final Collection charges; - private final Collection collateral; + private final Collection collateral; private final Collection guarantors; private final CalendarData meeting; private final Collection notes; @@ -245,14 +244,14 @@ public final class LoanAccountData { BigDecimal inArrearsTolerance, Long transactionProcessingStrategyId, Integer graceOnPrincipalPayment, Integer graceOnInterestPayment, Integer graceOnInterestCharged, LocalDate interestChargedFromDate, LocalDate repaymentsStartingFromDate, Integer rowIndex, String externalId, Long groupId, Collection charges, - String linkAccountId, String locale, String dateFormat) { + String linkAccountId, String locale, String dateFormat, List loanCollateralManagementData) { return new LoanAccountData(loanTypeEnumOption, clientId, productId, loanOfficerId, submittedOnDate, fundId, principal, numberOfRepayments, repaymentEvery, repaidEveryFrequencyEnums, loanTermFrequency, loanTermFrequencyTypeEnum, nominalInterestRate, expectedDisbursementDate, amortizationEnumOption, interestMethodEnum, interestCalculationPeriodTypeEnum, inArrearsTolerance, transactionProcessingStrategyId, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, repaymentsStartingFromDate, rowIndex, externalId, - null, charges, linkAccountId, locale, dateFormat); + null, charges, linkAccountId, locale, dateFormat, loanCollateralManagementData); } public static LoanAccountData importInstanceGroup(EnumOptionData loanTypeEnumOption, Long groupIdforGroupLoan, Long productId, @@ -268,7 +267,8 @@ public final class LoanAccountData { numberOfRepayments, repaidEvery, repaidEveryFrequencyEnums, loanTermFrequency, loanTermFrequencyTypeEnum, nominalInterestRate, null, amortizationEnumOption, interestMethodEnum, interestCalculationPeriodEnum, arrearsTolerance, transactionProcessingStrategyId, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, - interestChargedFromDate, repaymentsStartingFromDate, rowIndex, externalId, null, null, linkAccountId, locale, dateFormat); + interestChargedFromDate, repaymentsStartingFromDate, rowIndex, externalId, null, null, linkAccountId, locale, dateFormat, + null); } private LoanAccountData(EnumOptionData loanType, Long clientId, Long productId, Long loanOfficerId, LocalDate submittedOnDate, @@ -278,7 +278,8 @@ public final class LoanAccountData { EnumOptionData interestCalculationPeriodType, BigDecimal inArrearsTolerance, Long transactionProcessingStrategyId, Integer graceOnPrincipalPayment, Integer graceOnInterestPayment, Integer graceOnInterestCharged, LocalDate interestChargedFromDate, LocalDate repaymentsStartingFromDate, Integer rowIndex, String externalId, Long groupId, - Collection charges, String linkAccountId, String locale, String dateFormat) { + Collection charges, String linkAccountId, String locale, String dateFormat, + Collection loanCollateralManagementData) { this.dateFormat = dateFormat; this.locale = locale; this.rowIndex = rowIndex; @@ -362,7 +363,7 @@ public final class LoanAccountData { this.repaymentSchedule = null; this.transactions = null; - this.collateral = null; + this.collateral = loanCollateralManagementData; this.guarantors = null; this.meeting = null; this.notes = null; @@ -524,7 +525,7 @@ public final class LoanAccountData { final LoanScheduleData repaymentSchedule = null; final Collection transactions = null; final Collection charges = null; - final Collection collateral = null; + final Collection collateral = null; final Collection guarantors = null; final Collection notes = null; final CalendarData calendarData = null; @@ -665,7 +666,7 @@ public final class LoanAccountData { final LoanScheduleData repaymentSchedule = null; final Collection transactions = null; final Collection charges = null; - final Collection collateral = null; + final Collection collateral = null; final Collection guarantors = null; final Collection notes = null; final CalendarData calendarData = null; @@ -839,7 +840,7 @@ public final class LoanAccountData { final LoanScheduleData repaymentSchedule = null; final Collection transactions = null; final Collection charges = null; - final Collection collateral = null; + final Collection collateral = null; final Collection guarantors = null; final Collection notes = null; final CalendarData calendarData = null; @@ -1006,7 +1007,7 @@ public final class LoanAccountData { final LoanScheduleData repaymentSchedule = null; final Collection transactions = null; - final Collection collateral = null; + final Collection collateral = null; final Collection guarantors = null; final Collection notes = null; final CalendarData calendarData = null; @@ -1112,7 +1113,7 @@ public final class LoanAccountData { final LoanScheduleData repaymentSchedule = null; final Collection transactions = null; - final Collection collateral = null; + final Collection collateral = null; final Collection guarantors = null; final Collection notes = null; final CalendarData calendarData = null; @@ -1203,7 +1204,7 @@ public final class LoanAccountData { final LoanScheduleData repaymentSchedule = null; final Collection transactions = null; final Collection charges = null; - final Collection collateral = null; + final Collection collateral = null; final Collection guarantors = null; final Collection notes = null; final CalendarData calendarData = null; @@ -1265,9 +1266,9 @@ public final class LoanAccountData { */ public static LoanAccountData associationsAndTemplate(final LoanAccountData acc, final LoanScheduleData repaymentSchedule, final Collection transactions, final Collection charges, - final Collection collateral, final Collection guarantors, final CalendarData calendarData, - final Collection productOptions, final Collection termFrequencyTypeOptions, - final Collection repaymentFrequencyTypeOptions, + final Collection collateral, final Collection guarantors, + final CalendarData calendarData, final Collection productOptions, + final Collection termFrequencyTypeOptions, final Collection repaymentFrequencyTypeOptions, final Collection repaymentFrequencyNthDayTypeOptions, final Collection repaymentFrequencyDayOfWeekTypeOptions, final Collection transactionProcessingStrategyOptions, @@ -1535,7 +1536,7 @@ public final class LoanAccountData { final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final LocalDate interestChargedFromDate, final LoanApplicationTimelineData timeline, final LoanSummaryData summary, final BigDecimal feeChargesDueAtDisbursementCharged, final LoanScheduleData repaymentSchedule, final Collection transactions, - final Collection charges, final Collection collateral, + final Collection charges, final Collection collateral, final Collection guarantors, final CalendarData meeting, final Collection productOptions, final Collection termFrequencyTypeOptions, final Collection repaymentFrequencyTypeOptions, final Collection repaymentFrequencyNthDayTypeOptions, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanCollateralManagementData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanCollateralManagementData.java new file mode 100644 index 000000000..5c8b03a83 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanCollateralManagementData.java @@ -0,0 +1,60 @@ +/** + * 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.loanaccount.data; + +import java.math.BigDecimal; + +public class LoanCollateralManagementData { + + private final Long clientCollateralId; + + private final BigDecimal quantity; + + private final BigDecimal total; + + private final BigDecimal totalCollateral; + + private final Long id; + + public LoanCollateralManagementData(final Long clientCollateralIdId, final BigDecimal quantity, final BigDecimal total, + final BigDecimal totalCollateral, final Long id) { + this.clientCollateralId = clientCollateralIdId; + this.quantity = quantity; + this.totalCollateral = totalCollateral; + this.total = total; + this.id = id; + } + + public Long getClientCollateralId() { + return this.clientCollateralId; + } + + public BigDecimal getQuantity() { + return this.quantity; + } + + public BigDecimal getTotal() { + return this.total; + } + + public BigDecimal getTotalCollateral() { + return this.totalCollateral; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java index 1e62691df..686550a55 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java @@ -94,7 +94,6 @@ import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType; import org.apache.fineract.portfolio.charge.domain.ChargeTimeType; import org.apache.fineract.portfolio.charge.exception.LoanChargeCannotBeAddedException; import org.apache.fineract.portfolio.client.domain.Client; -import org.apache.fineract.portfolio.collateral.data.CollateralData; import org.apache.fineract.portfolio.collateral.domain.LoanCollateral; import org.apache.fineract.portfolio.common.domain.DayOfWeekType; import org.apache.fineract.portfolio.common.domain.NthDayType; @@ -107,6 +106,7 @@ import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants; import org.apache.fineract.portfolio.loanaccount.command.LoanChargeCommand; import org.apache.fineract.portfolio.loanaccount.data.DisbursementData; import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO; +import org.apache.fineract.portfolio.loanaccount.data.LoanCollateralManagementData; import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData; import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO; import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor; @@ -312,6 +312,9 @@ public class Loan extends AbstractPersistableCustom { @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = true, fetch = FetchType.LAZY) private Set collateral = null; + @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = true, fetch = FetchType.EAGER) + private Set loanCollateralManagements = new HashSet<>(); + @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = true, fetch = FetchType.LAZY) private Set loanOfficerHistory; @@ -406,9 +409,10 @@ public class Loan extends AbstractPersistableCustom { final LoanProduct loanProduct, final Fund fund, final Staff officer, final CodeValue loanPurpose, final LoanTransactionProcessingStrategy transactionProcessingStrategy, final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set loanCharges, - final Set collateral, final BigDecimal fixedEmiAmount, final List disbursementDetails, - final BigDecimal maxOutstandingLoanBalance, final Boolean createStandingInstructionAtDisbursement, - final Boolean isFloatingInterestRate, final BigDecimal interestRateDifferential, final List rates) { + final Set collateral, final BigDecimal fixedEmiAmount, + final List disbursementDetails, final BigDecimal maxOutstandingLoanBalance, + final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate, + final BigDecimal interestRateDifferential, final List rates) { final LoanStatus status = null; final Group group = null; final Boolean syncDisbursementWithMeeting = null; @@ -422,7 +426,7 @@ public class Loan extends AbstractPersistableCustom { final LoanProduct loanProduct, final Fund fund, final Staff officer, final CodeValue loanPurpose, final LoanTransactionProcessingStrategy transactionProcessingStrategy, final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set loanCharges, - final Set collateral, final Boolean syncDisbursementWithMeeting, final BigDecimal fixedEmiAmount, + final Set collateral, final Boolean syncDisbursementWithMeeting, final BigDecimal fixedEmiAmount, final List disbursementDetails, final BigDecimal maxOutstandingLoanBalance, final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate, final BigDecimal interestRateDifferential, final List rates) { @@ -438,7 +442,7 @@ public class Loan extends AbstractPersistableCustom { final Integer loanType, final LoanProduct loanProduct, final Fund fund, final Staff officer, final CodeValue loanPurpose, final LoanTransactionProcessingStrategy transactionProcessingStrategy, final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set loanCharges, - final Set collateral, final Boolean syncDisbursementWithMeeting, final BigDecimal fixedEmiAmount, + final Set collateral, final Boolean syncDisbursementWithMeeting, final BigDecimal fixedEmiAmount, final List disbursementDetails, final BigDecimal maxOutstandingLoanBalance, final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate, final BigDecimal interestRateDifferential, final List rates) { @@ -456,7 +460,7 @@ public class Loan extends AbstractPersistableCustom { private Loan(final String accountNo, final Client client, final Group group, final Integer loanType, final Fund fund, final Staff loanOfficer, final CodeValue loanPurpose, final LoanTransactionProcessingStrategy transactionProcessingStrategy, final LoanProduct loanProduct, final LoanProductRelatedDetail loanRepaymentScheduleDetail, final LoanStatus loanStatus, - final Set loanCharges, final Set collateral, final Boolean syncDisbursementWithMeeting, + final Set loanCharges, final Set collateral, final Boolean syncDisbursementWithMeeting, final BigDecimal fixedEmiAmount, final List disbursementDetails, final BigDecimal maxOutstandingLoanBalance, final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate, final BigDecimal interestRateDifferential, final List rates) { @@ -494,10 +498,11 @@ public class Loan extends AbstractPersistableCustom { this.charges = null; this.summary = new LoanSummary(); } - if (collateral != null && !collateral.isEmpty()) { - this.collateral = associateWithThisLoan(collateral); + + if (loanType.equals(1) && collateral != null && !collateral.isEmpty()) { + this.loanCollateralManagements = associateWithThisLoan(collateral); } else { - this.collateral = null; + this.loanCollateralManagements = null; } this.loanOfficerHistory = null; @@ -552,9 +557,9 @@ public class Loan extends AbstractPersistableCustom { return loanCharges; } - private Set associateWithThisLoan(final Set collateral) { - for (final LoanCollateral item : collateral) { - item.associateWith(this); + private Set associateWithThisLoan(final Set collateral) { + for (final LoanCollateralManagement item : collateral) { + item.setLoan(this); } return collateral; } @@ -1174,12 +1179,12 @@ public class Loan extends AbstractPersistableCustom { updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement()); } - public void updateLoanCollateral(final Set loanCollateral) { - if (this.collateral == null) { - this.collateral = new HashSet<>(); + public void updateLoanCollateral(final Set loanCollateral) { + if (this.loanCollateralManagements == null) { + this.loanCollateralManagements = new HashSet<>(); } - this.collateral.clear(); - this.collateral.addAll(associateWithThisLoan(loanCollateral)); + this.loanCollateralManagements.clear(); + this.loanCollateralManagements.addAll(associateWithThisLoan(loanCollateral)); } public void updateLoanRates(final List loanRates) { @@ -1328,8 +1333,8 @@ public class Loan extends AbstractPersistableCustom { } public Map loanApplicationModification(final JsonCommand command, final Set possiblyModifedLoanCharges, - final Set possiblyModifedLoanCollateralItems, final AprCalculator aprCalculator, boolean isChargesModified, - final LoanProduct loanProduct) { + final Set possiblyModifedLoanCollateralItems, final AprCalculator aprCalculator, + boolean isChargesModified, final LoanProduct loanProduct) { final Map actualChanges = this.loanRepaymentScheduleDetail.updateLoanApplicationAttributes(command, aprCalculator); final MonetaryCurrency currency = new MonetaryCurrency(loanProduct.getCurrency().getCode(), @@ -1541,10 +1546,16 @@ public class Loan extends AbstractPersistableCustom { } final String collateralParamName = "collateral"; - if (command.parameterExists(collateralParamName)) { - if (!possiblyModifedLoanCollateralItems.equals(this.collateral)) { - actualChanges.put(collateralParamName, listOfLoanCollateralData(possiblyModifedLoanCollateralItems)); + if (command.parameterExists(collateralParamName) && possiblyModifedLoanCollateralItems != null) { + + if (possiblyModifedLoanCollateralItems.size() != 0) { + Set loanCollateralManagements = this.loanCollateralManagements; + boolean isTrue = possiblyModifedLoanCollateralItems.equals(loanCollateralManagements); + + if (!isTrue) { + actualChanges.put(collateralParamName, getLoanCollateralDataFormCommand(possiblyModifedLoanCollateralItems)); + } } } @@ -1916,19 +1927,18 @@ public class Loan extends AbstractPersistableCustom { return list; } - private CollateralData[] listOfLoanCollateralData(final Set setOfLoanCollateral) { + private LoanCollateralManagementData[] getLoanCollateralDataFormCommand(final Set setOfLoanCollateral) { - CollateralData[] existingLoanCollateral = null; + LoanCollateralManagementData[] existingLoanCollateral = null; - final List loanCollateralList = new ArrayList<>(); - for (final LoanCollateral loanCollateral : setOfLoanCollateral) { + final List loanCollateralList = new ArrayList<>(); + for (final LoanCollateralManagement loanCollateral : setOfLoanCollateral) { - final CollateralData data = loanCollateral.toData(); + loanCollateralList.add(loanCollateral.toCommand()); - loanCollateralList.add(data); } - existingLoanCollateral = loanCollateralList.toArray(new CollateralData[loanCollateralList.size()]); + existingLoanCollateral = loanCollateralList.toArray(new LoanCollateralManagementData[loanCollateralList.size()]); return existingLoanCollateral; } @@ -3008,6 +3018,7 @@ public class Loan extends AbstractPersistableCustom { final String errorMessage = "Transfer funds is allowed only for loan accounts with overpaid status "; throw new InvalidLoanStateTransitionException("transaction", "is.not.a.overpaid.loan", errorMessage); } + loanTransaction.updateLoan(this); if (loanTransaction.isNotZero(loanCurrency())) { @@ -6592,6 +6603,7 @@ public class Loan extends AbstractPersistableCustom { checkAndFetchLazyCollection(this.loanTermVariations); checkAndFetchLazyCollection(this.collateral); checkAndFetchLazyCollection(this.loanOfficerHistory); + checkAndFetchLazyCollection(this.loanCollateralManagements); } private void checkAndFetchLazyCollection(Collection lazyCollection) { @@ -6636,4 +6648,8 @@ public class Loan extends AbstractPersistableCustom { this.loanType = loanType; } + public Set getLoanCollateralManagements() { + return this.loanCollateralManagements; + } + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainService.java index 98eec6117..bb2879afe 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainService.java @@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.domain; import java.math.BigDecimal; import java.time.LocalDate; import java.util.Map; +import java.util.Set; import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO; import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail; @@ -48,6 +49,10 @@ public interface LoanAccountDomainService { LoanTransaction makeRefundForActiveLoan(Long accountId, CommandProcessingResultBuilder builderResult, LocalDate transactionDate, BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, String txnExternalId); + void updateLoanCollateralTransaction(Set loanCollateralManagementList); + + void updateLoanCollateralStatus(Set loanCollateralManagementSet, Integer isReleased); + /** * This method is to recalculate and accrue the income till the last accrued date. this method is used when the * schedule changes due to interest recalculation diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java index 9531b5047..cfa1039c3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java @@ -101,6 +101,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { private final BusinessEventNotifierService businessEventNotifierService; private final LoanUtilService loanUtilService; private final StandingInstructionRepository standingInstructionRepository; + private final LoanCollateralManagementRepository loanCollateralManagementRepository; @Autowired public LoanAccountDomainServiceJpa(final LoanAssembler loanAccountAssembler, final LoanRepositoryWrapper loanRepositoryWrapper, @@ -114,7 +115,8 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository, final LoanAccrualPlatformService loanAccrualPlatformService, final PlatformSecurityContext context, final BusinessEventNotifierService businessEventNotifierService, final LoanUtilService loanUtilService, - final StandingInstructionRepository standingInstructionRepository) { + final StandingInstructionRepository standingInstructionRepository, + final LoanCollateralManagementRepository loanCollateralManagementRepository) { this.loanAccountAssembler = loanAccountAssembler; this.loanRepositoryWrapper = loanRepositoryWrapper; this.loanTransactionRepository = loanTransactionRepository; @@ -132,6 +134,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { this.businessEventNotifierService = businessEventNotifierService; this.loanUtilService = loanUtilService; this.standingInstructionRepository = standingInstructionRepository; + this.loanCollateralManagementRepository = loanCollateralManagementRepository; } @Transactional @@ -144,6 +147,21 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { isRecoveryRepayment, isAccountTransfer, holidayDetailDto, isHolidayValidationDone, false); } + @Transactional + @Override + public void updateLoanCollateralTransaction(Set loanCollateralManagementSet) { + this.loanCollateralManagementRepository.saveAll(loanCollateralManagementSet); + } + + @Transactional + @Override + public void updateLoanCollateralStatus(Set loanCollateralManagementSet, Integer isReleased) { + for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagementSet) { + loanCollateralManagement.setIsReleased(isReleased); + } + this.loanCollateralManagementRepository.saveAll(loanCollateralManagementSet); + } + @Transactional @Override public LoanTransaction makeRepayment(final Loan loan, final CommandProcessingResultBuilder builderResult, @@ -232,7 +250,8 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { private void saveLoanTransactionWithDataIntegrityViolationChecks(LoanTransaction newRepaymentTransaction) { try { - this.loanTransactionRepository.save(newRepaymentTransaction); + LoanTransaction loanTransaction = this.loanTransactionRepository.save(newRepaymentTransaction); + } catch (final JpaSystemException | DataIntegrityViolationException e) { final Throwable realCause = e.getCause(); final List dataValidationErrors = new ArrayList<>(); @@ -524,6 +543,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { throw new GeneralPlatformDomainRuleException(globalisationMessageCode, e.getMessage(), e); } } + } private void generateLoanScheduleAccrualData(final LocalDate accruedTill, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCollateralManagement.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCollateralManagement.java new file mode 100644 index 000000000..f5d840c77 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCollateralManagement.java @@ -0,0 +1,124 @@ +/** + * 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.loanaccount.domain; + +import java.math.BigDecimal; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement; +import org.apache.fineract.portfolio.loanaccount.data.LoanCollateralManagementData; + +@Entity +@Table(name = "m_loan_collateral_management") +public class LoanCollateralManagement extends AbstractPersistableCustom { + + @Column(name = "quantity", nullable = false, scale = 5, precision = 20) + private BigDecimal quantity; + + @ManyToOne() + @JoinColumn(name = "transaction_id") + private LoanTransaction loanTransaction = null; + + @ManyToOne(optional = false) + @JoinColumn(name = "loan_id", referencedColumnName = "id", nullable = false) + private Loan loan; + + @Column(name = "is_released", nullable = false, columnDefinition = "0") + private Integer isReleased = Integer.valueOf(0); + + @ManyToOne(optional = false) + @JoinColumn(name = "client_collateral_id", nullable = false) + private ClientCollateralManagement clientCollateralManagement; + + public LoanCollateralManagement() { + + } + + public LoanCollateralManagement(final BigDecimal quantity, final Integer isReleased) { + this.quantity = quantity; + this.isReleased = isReleased; + } + + private LoanCollateralManagement(final BigDecimal quantity, final ClientCollateralManagement clientCollateralManagement) { + this.clientCollateralManagement = clientCollateralManagement; + this.quantity = quantity; + } + + public void setLoan(Loan loan) { + this.loan = loan; + } + + public static LoanCollateralManagement from(final ClientCollateralManagement clientCollateralManagement, final BigDecimal quantity) { + return new LoanCollateralManagement(quantity, clientCollateralManagement); + } + + public static LoanCollateralManagement fromExisting(final ClientCollateralManagement clientCollateralManagement, + final BigDecimal quantity, final Loan loan, final LoanTransaction transaction, final Long id) { + LoanCollateralManagement loanCollateralManagementInstance = new LoanCollateralManagement(quantity, clientCollateralManagement); + loanCollateralManagementInstance.setLoan(loan); + loanCollateralManagementInstance.setLoanTransactionData(transaction); + loanCollateralManagementInstance.setId(id); + return loanCollateralManagementInstance; + } + + public void setClientCollateralManagement(final ClientCollateralManagement clientCollateralManagement) { + this.clientCollateralManagement = clientCollateralManagement; + } + + public void setLoanTransactionData(final LoanTransaction loanTransaction) { + this.loanTransaction = loanTransaction; + } + + public void setIsReleased(final Integer isReleased) { + this.isReleased = isReleased; + } + + public void setQuantity(final BigDecimal quantity) { + this.quantity = quantity; + } + + public BigDecimal getQuantity() { + return this.quantity; + } + + public Loan getLoanData() { + return this.loan; + } + + public LoanTransaction getLoanTransaction() { + return this.loanTransaction; + } + + public ClientCollateralManagement getClientCollateralManagement() { + return this.clientCollateralManagement; + } + + public Integer getIsReleased() { + return this.isReleased; + } + + public LoanCollateralManagementData toCommand() { + return new LoanCollateralManagementData(this.clientCollateralManagement.getId(), this.getQuantity(), null, null, getId()); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCollateralManagementRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCollateralManagementRepository.java new file mode 100644 index 000000000..39923fc9f --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCollateralManagementRepository.java @@ -0,0 +1,32 @@ +/** + * 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.loanaccount.domain; + +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; + +public interface LoanCollateralManagementRepository + extends JpaRepository, JpaSpecificationExecutor { + + @Query("select loanCollaterals from LoanCollateralManagement loanCollaterals where loanCollaterals.loan=:loan") + List findByLoan(Loan loan); + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java index 65f8ff5f6..c1e9ff8aa 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java @@ -129,6 +129,9 @@ public class LoanTransaction extends AbstractPersistableCustom { @Column(name = "manually_adjusted_or_reversed", nullable = false) private boolean manuallyAdjustedOrReversed; + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "loanTransaction") + private Set loanCollateralManagementSet = new HashSet<>(); + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) @JoinColumn(name = "loan_transaction_id", referencedColumnName = "id", nullable = false) private Set loanTransactionToRepaymentScheduleMappings = new HashSet<>(); @@ -803,6 +806,10 @@ public class LoanTransaction extends AbstractPersistableCustom { || this.isNonMonetaryTransaction() || this.isIncomePosting()); } + public Set getLoanCollateralManagementSet() { + return this.loanCollateralManagementSet; + } + // TODO missing hashCode(), equals(Object obj), but probably OK as long as // this is never stored in a Collection. } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/exception/InvalidAmountOfCollateralQuantity.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/exception/InvalidAmountOfCollateralQuantity.java new file mode 100644 index 000000000..93ab45dd4 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/exception/InvalidAmountOfCollateralQuantity.java @@ -0,0 +1,36 @@ +/** + * 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.loanaccount.exception; + +import java.math.BigDecimal; +import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException; + +public class InvalidAmountOfCollateralQuantity extends AbstractPlatformDomainRuleException { + + public InvalidAmountOfCollateralQuantity(final BigDecimal quantity) { + super("error.msg.loan.collateral.failed", + "The collateral quantity value`" + quantity.toString() + "`" + "` cannot exceed the available quantity", + new Object[] { quantity.toString() }); + } + + public InvalidAmountOfCollateralQuantity(final String defaultUserMessage, final String entity, final Object... defaultUserMessageArgs) { + super("error.msg.loan." + entity, defaultUserMessage, defaultUserMessageArgs); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/exception/InvalidAmountOfCollaterals.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/exception/InvalidAmountOfCollaterals.java new file mode 100644 index 000000000..3076d28a6 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/exception/InvalidAmountOfCollaterals.java @@ -0,0 +1,35 @@ +/** + * 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.loanaccount.exception; + +import java.math.BigDecimal; +import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException; + +public class InvalidAmountOfCollaterals extends AbstractPlatformDomainRuleException { + + public InvalidAmountOfCollaterals(final BigDecimal amount) { + super("error.msg.loan.collateral.failed", + "The total collateral value`" + amount.toString() + "`" + "` should be greater than or equal to the loan amount", + new Object[] { amount.toString() }); + } + + public InvalidAmountOfCollaterals(final String defaultUserMessage, final String entity, final Object... defaultUserMessageArgs) { + super("error.msg.loan." + entity, defaultUserMessage, defaultUserMessageArgs); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java index dfa8af9e0..db0450609 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java @@ -41,9 +41,13 @@ import org.apache.fineract.infrastructure.core.exception.UnsupportedParameterExc import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; import org.apache.fineract.portfolio.accountdetails.domain.AccountType; import org.apache.fineract.portfolio.calendar.service.CalendarUtils; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagementRepositoryWrapper; import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants; import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge; +import org.apache.fineract.portfolio.loanaccount.exception.InvalidAmountOfCollateralQuantity; +import org.apache.fineract.portfolio.loanaccount.exception.InvalidAmountOfCollaterals; import org.apache.fineract.portfolio.loanproduct.LoanProductConstants; import org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod; import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod; @@ -88,16 +92,20 @@ public final class LoanApplicationCommandFromApiJsonHelper { LoanApiConstants.createStandingInstructionAtDisbursementParameterName, LoanApiConstants.isTopup, LoanApiConstants.loanIdToClose, LoanApiConstants.datatables, LoanApiConstants.isEqualAmortizationParam, LoanProductConstants.RATES_PARAM_NAME, LoanApiConstants.applicationId, // glim specific - LoanApiConstants.lastApplication, LoanApiConstants.daysInYearTypeParameterName)); // glim specific + LoanApiConstants.lastApplication, LoanApiConstants.daysInYearTypeParameterName)); // glim + // specific private final FromJsonHelper fromApiJsonHelper; private final CalculateLoanScheduleQueryFromApiJsonHelper apiJsonHelper; + private final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper; @Autowired public LoanApplicationCommandFromApiJsonHelper(final FromJsonHelper fromApiJsonHelper, - final CalculateLoanScheduleQueryFromApiJsonHelper apiJsonHelper) { + final CalculateLoanScheduleQueryFromApiJsonHelper apiJsonHelper, + final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper) { this.fromApiJsonHelper = fromApiJsonHelper; this.apiJsonHelper = apiJsonHelper; + this.clientCollateralManagementRepositoryWrapper = clientCollateralManagementRepositoryWrapper; } public void validateForCreate(final String json, final boolean isMeetingMandatoryForJLGLoans, final LoanProduct loanProduct) { @@ -414,38 +422,54 @@ public final class LoanApplicationCommandFromApiJsonHelper { } } - // collateral - final String collateralParameterName = "collateral"; - if (element.isJsonObject() && this.fromApiJsonHelper.parameterExists(collateralParameterName, element)) { - final JsonObject topLevelJsonElement = element.getAsJsonObject(); - final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement); - if (topLevelJsonElement.get("collateral").isJsonArray()) { + /** + * TODO: Add collaterals for other loan accounts if needed. For now it's only applicable for individual + * accounts. (loanType.isJLG() || loanType.isGLIM()) + */ - final Type collateralParameterTypeOfMap = new TypeToken>() {}.getType(); - final Set supportedParameters = new HashSet<>(Arrays.asList("id", "type", "value", "description")); - final JsonArray array = topLevelJsonElement.get("collateral").getAsJsonArray(); - for (int i = 1; i <= array.size(); i++) { - final JsonObject collateralItemElement = array.get(i - 1).getAsJsonObject(); + if (!StringUtils.isBlank(loanTypeStr)) { + final AccountType loanType = AccountType.fromName(loanTypeStr); - final String collateralJson = this.fromApiJsonHelper.toJson(collateralItemElement); - this.fromApiJsonHelper.checkForUnsupportedParameters(collateralParameterTypeOfMap, collateralJson, supportedParameters); + if (loanType.isIndividualAccount()) { + // collateral + final String collateralParameterName = "collateral"; + if (element.isJsonObject() && this.fromApiJsonHelper.parameterExists(collateralParameterName, element)) { + final JsonObject topLevelJsonElement = element.getAsJsonObject(); + final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement); + if (topLevelJsonElement.get("collateral").isJsonArray()) { - final Long collateralTypeId = this.fromApiJsonHelper.extractLongNamed("type", collateralItemElement); - baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("type", i).value(collateralTypeId).notNull() - .integerGreaterThanZero(); + final Type collateralParameterTypeOfMap = new TypeToken>() {}.getType(); + final Set supportedParameters = new HashSet<>(Arrays.asList("clientCollateralId", "quantity")); + final JsonArray array = topLevelJsonElement.get("collateral").getAsJsonArray(); + for (int i = 1; i <= array.size(); i++) { + final JsonObject collateralItemElement = array.get(i - 1).getAsJsonObject(); - final BigDecimal collateralValue = this.fromApiJsonHelper.extractBigDecimalNamed("value", collateralItemElement, - locale); - baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("value", i).value(collateralValue) - .ignoreIfNull().positiveAmount(); + final String collateralJson = this.fromApiJsonHelper.toJson(collateralItemElement); + this.fromApiJsonHelper.checkForUnsupportedParameters(collateralParameterTypeOfMap, collateralJson, + supportedParameters); - final String description = this.fromApiJsonHelper.extractStringNamed("description", collateralItemElement); - baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("description", i).value(description).notBlank() - .notExceedingLengthOf(500); + final Long clientCollateralId = this.fromApiJsonHelper.extractLongNamed("clientCollateralId", + collateralItemElement); + baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("clientCollateralId", i) + .value(clientCollateralId).notNull().integerGreaterThanZero(); + final BigDecimal quantity = this.fromApiJsonHelper.extractBigDecimalNamed("quantity", collateralItemElement, + locale); + baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("quantity", i).value(quantity).notNull() + .positiveAmount(); + + final ClientCollateralManagement clientCollateralManagement = this.clientCollateralManagementRepositoryWrapper + .getCollateral(clientCollateralId); + + if (clientCollateralId != null + && BigDecimal.valueOf(0).compareTo(clientCollateralManagement.getQuantity()) >= 0) { + throw new InvalidAmountOfCollateralQuantity(clientCollateralManagement.getQuantity()); + } + } + } else { + baseDataValidator.reset().parameter(collateralParameterName).expectedArrayButIsNot(); + } } - } else { - baseDataValidator.reset().parameter(collateralParameterName).expectedArrayButIsNot(); } } @@ -847,38 +871,67 @@ public final class LoanApplicationCommandFromApiJsonHelper { } } - // collateral - final String collateralParameterName = "collateral"; - if (element.isJsonObject() && this.fromApiJsonHelper.parameterExists(collateralParameterName, element)) { - final JsonObject topLevelJsonElement = element.getAsJsonObject(); - final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement); - if (topLevelJsonElement.get("collateral").isJsonArray()) { + final String loanTypeParameterName = "loanType"; + final String loanTypeStr = this.fromApiJsonHelper.extractStringNamed(loanTypeParameterName, element); + baseDataValidator.reset().parameter(loanTypeParameterName).value(loanTypeStr).notNull(); - final Type collateralParameterTypeOfMap = new TypeToken>() {}.getType(); - final Set supportedParameters = new HashSet<>(Arrays.asList("id", "type", "value", "description")); - final JsonArray array = topLevelJsonElement.get("collateral").getAsJsonArray(); - for (int i = 1; i <= array.size(); i++) { - final JsonObject collateralItemElement = array.get(i - 1).getAsJsonObject(); + if (!StringUtils.isBlank(loanTypeStr)) { + final AccountType loanType = AccountType.fromName(loanTypeStr); - final String collateralJson = this.fromApiJsonHelper.toJson(collateralItemElement); - this.fromApiJsonHelper.checkForUnsupportedParameters(collateralParameterTypeOfMap, collateralJson, supportedParameters); + if (loanType.isInvalid()) { + baseDataValidator.reset().parameter(loanTypeParameterName).value(loanType.getValue()).isOneOfEnumValues(AccountType.class); + } - final Long collateralTypeId = this.fromApiJsonHelper.extractLongNamed("type", collateralItemElement); - baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("type", i).value(collateralTypeId).notNull() - .integerGreaterThanZero(); + if (!loanType.isInvalid() && loanType.isIndividualAccount()) { + // collateral + final String collateralParameterName = "collateral"; + if (element.isJsonObject() && this.fromApiJsonHelper.parameterExists(collateralParameterName, element)) { + final JsonObject topLevelJsonElement = element.getAsJsonObject(); + final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement); + if (topLevelJsonElement.get("collateral").isJsonArray()) { - final BigDecimal collateralValue = this.fromApiJsonHelper.extractBigDecimalNamed("value", collateralItemElement, - locale); - baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("value", i).value(collateralValue) - .ignoreIfNull().positiveAmount(); + final Type collateralParameterTypeOfMap = new TypeToken>() {}.getType(); + final Set supportedParameters = new HashSet<>(Arrays.asList("id", "clientCollateralId", "quantity")); + final JsonArray array = topLevelJsonElement.get("collateral").getAsJsonArray(); + BigDecimal totalAmount = BigDecimal.ZERO; + for (int i = 1; i <= array.size(); i++) { + final JsonObject collateralItemElement = array.get(i - 1).getAsJsonObject(); - final String description = this.fromApiJsonHelper.extractStringNamed("description", collateralItemElement); - baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("description", i).value(description).notBlank() - .notExceedingLengthOf(500); + final String collateralJson = this.fromApiJsonHelper.toJson(collateralItemElement); + this.fromApiJsonHelper.checkForUnsupportedParameters(collateralParameterTypeOfMap, collateralJson, + supportedParameters); + final Long id = this.fromApiJsonHelper.extractLongNamed("id", collateralItemElement); + baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("id", i).value(id).ignoreIfNull(); + + final Long clientCollateralId = this.fromApiJsonHelper.extractLongNamed("clientCollateralId", + collateralItemElement); + baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("clientCollateralId", i) + .value(clientCollateralId).notNull().integerGreaterThanZero(); + + final BigDecimal quantity = this.fromApiJsonHelper.extractBigDecimalNamed("quantity", collateralItemElement, + locale); + baseDataValidator.reset().parameter("collateral").parameterAtIndexArray("quantity", i).value(quantity).notNull() + .positiveAmount(); + + if (clientCollateralId != null || quantity != null) { + BigDecimal baseAmount = this.clientCollateralManagementRepositoryWrapper.getCollateral(clientCollateralId) + .getCollaterals().getBasePrice(); + BigDecimal pctToBase = this.clientCollateralManagementRepositoryWrapper.getCollateral(clientCollateralId) + .getCollaterals().getPctToBase(); + BigDecimal total = baseAmount.multiply(pctToBase).multiply(quantity); + totalAmount = totalAmount.add(total); + } + } + if (principal != null) { + if (principal.compareTo(totalAmount) > 0 || array.size() == 0) { + throw new InvalidAmountOfCollaterals(totalAmount); + } + } + } else { + baseDataValidator.reset().parameter(collateralParameterName).expectedArrayButIsNot(); + } } - } else { - baseDataValidator.reset().parameter(collateralParameterName).expectedArrayButIsNot(); } } @@ -1201,6 +1254,20 @@ public final class LoanApplicationCommandFromApiJsonHelper { } } + public void validateLoanForCollaterals(final Loan loan, final BigDecimal total) { + String errorCode = ""; + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan"); + if (loan.getProposedPrincipal().compareTo(total) >= 0) { + errorCode = LoanApiConstants.LOAN_COLLATERAL_TOTAL_VALUE_SHOULD_BE_SUFFICIENT; + baseDataValidator.reset().parameter("collaterals").failWithCode(errorCode); + } + + if (!dataValidationErrors.isEmpty()) { + throw new PlatformApiDataValidationException(dataValidationErrors); + } + } + private void validatePartialPeriodSupport(final Integer interestCalculationPeriodType, final DataValidatorBuilder baseDataValidator, final JsonElement element, final LoanProduct loanProduct) { if (interestCalculationPeriodType != null) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java index 3e7866e18..35d608cbf 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java @@ -81,8 +81,9 @@ import org.apache.fineract.portfolio.client.domain.AccountNumberGenerator; import org.apache.fineract.portfolio.client.domain.Client; import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper; import org.apache.fineract.portfolio.client.exception.ClientNotActiveException; -import org.apache.fineract.portfolio.collateral.domain.LoanCollateral; -import org.apache.fineract.portfolio.collateral.service.CollateralAssembler; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagementRepository; +import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralAssembler; import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BusinessEntity; import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BusinessEvents; import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType; @@ -100,6 +101,8 @@ import org.apache.fineract.portfolio.loanaccount.domain.GLIMAccountInfoRepositor import org.apache.fineract.portfolio.loanaccount.domain.GroupLoanIndividualMonitoringAccount; import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge; +import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement; +import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagementRepository; import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails; import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; @@ -165,7 +168,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa private final ClientRepositoryWrapper clientRepository; private final LoanProductRepository loanProductRepository; private final LoanChargeAssembler loanChargeAssembler; - private final CollateralAssembler loanCollateralAssembler; + private final LoanCollateralAssembler loanCollateralAssembler; private final AprCalculator aprCalculator; private final AccountNumberGenerator accountNumberGenerator; private final LoanSummaryWrapper loanSummaryWrapper; @@ -194,6 +197,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa private final GLIMAccountInfoRepository glimRepository; private final LoanRepository loanRepository; private final GSIMReadPlatformService gsimReadPlatformService; + private final LoanCollateralManagementRepository loanCollateralManagementRepository; + private final ClientCollateralManagementRepository clientCollateralManagementRepository; @Autowired public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final FromJsonHelper fromJsonHelper, @@ -201,7 +206,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa final LoanApplicationCommandFromApiJsonHelper fromApiJsonDeserializer, final LoanProductDataValidator loanProductCommandFromApiJsonDeserializer, final AprCalculator aprCalculator, final LoanAssembler loanAssembler, final LoanChargeAssembler loanChargeAssembler, - final CollateralAssembler loanCollateralAssembler, final LoanRepositoryWrapper loanRepositoryWrapper, + final LoanCollateralAssembler loanCollateralAssembler, final LoanRepositoryWrapper loanRepositoryWrapper, final NoteRepository noteRepository, final LoanScheduleCalculationPlatformService calculationPlatformService, final ClientRepositoryWrapper clientRepository, final LoanProductRepository loanProductRepository, final AccountNumberGenerator accountNumberGenerator, final LoanSummaryWrapper loanSummaryWrapper, @@ -220,7 +225,9 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService, final GLIMAccountInfoWritePlatformService glimAccountInfoWritePlatformService, final GLIMAccountInfoRepository glimRepository, final LoanRepository loanRepository, final GSIMReadPlatformService gsimReadPlatformService, final RateAssembler rateAssembler, - final LoanProductReadPlatformService loanProductReadPlatformService) { + final LoanProductReadPlatformService loanProductReadPlatformService, + final LoanCollateralManagementRepository loanCollateralManagementRepository, + final ClientCollateralManagementRepository clientCollateralManagementRepository) { this.context = context; this.fromJsonHelper = fromJsonHelper; this.loanApplicationTransitionApiJsonValidator = loanApplicationTransitionApiJsonValidator; @@ -261,6 +268,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa this.glimRepository = glimRepository; this.loanRepository = loanRepository; this.gsimReadPlatformService = gsimReadPlatformService; + this.loanCollateralManagementRepository = loanCollateralManagementRepository; + this.clientCollateralManagementRepository = clientCollateralManagementRepository; } private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() { @@ -813,8 +822,16 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa } } - final Set possiblyModifedLoanCollateralItems = this.loanCollateralAssembler - .fromParsedJson(command.parsedJson()); + Set possiblyModifedLoanCollateralItems = null; + + if (command.parameterExists("loanType")) { + final String loanTypeStr = command.stringValueOfParameterNamed("loanType"); + final AccountType loanType = AccountType.fromName(loanTypeStr); + + if (!StringUtils.isBlank(loanTypeStr) && loanType.isIndividualAccount()) { + possiblyModifedLoanCollateralItems = this.loanCollateralAssembler.fromParsedJson(command.parsedJson()); + } + } final Map changes = existingLoanApplication.loanApplicationModification(command, possiblyModifedLoanCharges, possiblyModifedLoanCollateralItems, this.aprCalculator, isChargeModified, loanProductForValidations); @@ -991,10 +1008,19 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa existingLoanApplication.updateTransactionProcessingStrategy(strategy); } - final String collateralParamName = "collateral"; - if (changes.containsKey(collateralParamName)) { - final Set loanCollateral = this.loanCollateralAssembler.fromParsedJson(command.parsedJson()); - existingLoanApplication.updateLoanCollateral(loanCollateral); + /** + * TODO: Allow other loan types if needed. + */ + if (command.parameterExists("loanType")) { + final String loanTypeStr = command.stringValueOfParameterNamed("loanType"); + final AccountType loanType = AccountType.fromName(loanTypeStr); + + if (!StringUtils.isBlank(loanTypeStr) && loanType.isIndividualAccount()) { + final String collateralParamName = "collateral"; + if (changes.containsKey(collateralParamName)) { + existingLoanApplication.updateLoanCollateral(possiblyModifedLoanCollateralItems); + } + } } final String chargesParamName = "charges"; @@ -1268,6 +1294,15 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa this.accountAssociationsRepository.delete(accountAssociations); } + Set loanCollateralManagements = loan.getLoanCollateralManagements(); + for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagements) { + BigDecimal quantity = loanCollateralManagement.getQuantity(); + ClientCollateralManagement clientCollateralManagement = loanCollateralManagement.getClientCollateralManagement(); + clientCollateralManagement.updateQuantityAfterLoanClosed(quantity); + loanCollateralManagement.setIsReleased(Integer.valueOf(1)); + loanCollateralManagement.setClientCollateralManagement(clientCollateralManagement); + } + this.loanRepositoryWrapper.delete(loanId); return new CommandProcessingResultBuilder() // @@ -1610,6 +1645,20 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa final Map changes = loan.loanApplicationWithdrawnByApplicant(currentUser, command, defaultLoanLifecycleStateMachine()); + + // Release attached collaterals + if (AccountType.fromInt(loan.getLoanType()).isIndividualAccount()) { + Set loanCollateralManagements = loan.getLoanCollateralManagements(); + for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagements) { + ClientCollateralManagement clientCollateralManagement = loanCollateralManagement.getClientCollateralManagement(); + clientCollateralManagement + .updateQuantity(clientCollateralManagement.getQuantity().add(loanCollateralManagement.getQuantity())); + loanCollateralManagement.setClientCollateralManagement(clientCollateralManagement); + loanCollateralManagement.setIsReleased(Integer.valueOf(1)); + } + loan.updateLoanCollateral(loanCollateralManagements); + } + if (!changes.isEmpty()) { this.loanRepositoryWrapper.save(loan); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java index 403a85e00..e2e8ff439 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java @@ -24,9 +24,11 @@ import java.time.LocalDate; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Set; +import org.apache.commons.lang3.StringUtils; import org.apache.fineract.infrastructure.codes.domain.CodeValue; import org.apache.fineract.infrastructure.codes.domain.CodeValueRepositoryWrapper; import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService; @@ -43,12 +45,13 @@ import org.apache.fineract.organisation.staff.exception.StaffNotFoundException; import org.apache.fineract.organisation.staff.exception.StaffRoleException; import org.apache.fineract.organisation.workingdays.domain.WorkingDays; import org.apache.fineract.organisation.workingdays.domain.WorkingDaysRepositoryWrapper; +import org.apache.fineract.portfolio.accountdetails.domain.AccountType; import org.apache.fineract.portfolio.accountdetails.service.AccountEnumerations; import org.apache.fineract.portfolio.client.domain.Client; import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper; import org.apache.fineract.portfolio.client.exception.ClientNotActiveException; -import org.apache.fineract.portfolio.collateral.domain.LoanCollateral; -import org.apache.fineract.portfolio.collateral.service.CollateralAssembler; +import org.apache.fineract.portfolio.collateralmanagement.domain.CollateralManagementDomain; +import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralAssembler; import org.apache.fineract.portfolio.fund.domain.Fund; import org.apache.fineract.portfolio.fund.domain.FundRepository; import org.apache.fineract.portfolio.fund.exception.FundNotFoundException; @@ -61,6 +64,7 @@ import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants; import org.apache.fineract.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine; import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge; +import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement; import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails; import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory; @@ -69,6 +73,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; import org.apache.fineract.portfolio.loanaccount.domain.LoanSummaryWrapper; import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionProcessingStrategyRepository; import org.apache.fineract.portfolio.loanaccount.exception.ExceedingTrancheCountException; +import org.apache.fineract.portfolio.loanaccount.exception.InvalidAmountOfCollaterals; import org.apache.fineract.portfolio.loanaccount.exception.LoanTransactionProcessingStrategyNotFoundException; import org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementDataRequiredException; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms; @@ -101,7 +106,7 @@ public class LoanAssembler { private final CodeValueRepositoryWrapper codeValueRepository; private final LoanScheduleAssembler loanScheduleAssembler; private final LoanChargeAssembler loanChargeAssembler; - private final CollateralAssembler loanCollateralAssembler; + private final LoanCollateralAssembler collateralAssembler; private final LoanSummaryWrapper loanSummaryWrapper; private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory; private final HolidayRepository holidayRepository; @@ -117,7 +122,7 @@ public class LoanAssembler { final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository, final StaffRepository staffRepository, final CodeValueRepositoryWrapper codeValueRepository, final LoanScheduleAssembler loanScheduleAssembler, final LoanChargeAssembler loanChargeAssembler, - final CollateralAssembler loanCollateralAssembler, final LoanSummaryWrapper loanSummaryWrapper, + final LoanCollateralAssembler collateralAssembler, final LoanSummaryWrapper loanSummaryWrapper, final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory, final HolidayRepository holidayRepository, final ConfigurationDomainService configurationDomainService, final WorkingDaysRepositoryWrapper workingDaysRepository, final LoanUtilService loanUtilService, RateAssembler rateAssembler) { @@ -132,7 +137,7 @@ public class LoanAssembler { this.codeValueRepository = codeValueRepository; this.loanScheduleAssembler = loanScheduleAssembler; this.loanChargeAssembler = loanChargeAssembler; - this.loanCollateralAssembler = loanCollateralAssembler; + this.collateralAssembler = collateralAssembler; this.loanSummaryWrapper = loanSummaryWrapper; this.loanRepaymentScheduleTransactionProcessorFactory = loanRepaymentScheduleTransactionProcessorFactory; this.holidayRepository = holidayRepository; @@ -178,7 +183,8 @@ public class LoanAssembler { final LoanProduct loanProduct = this.loanProductRepository.findById(productId) .orElseThrow(() -> new LoanProductNotFoundException(productId)); - + final BigDecimal amount = this.fromApiJsonHelper + .extractBigDecimalWithLocaleNamed(LoanApiConstants.disbursementPrincipalParameterName, element); final Fund fund = findFundByIdIfProvided(fundId); final Staff loanOfficer = findLoanOfficerByIdIfProvided(loanOfficerId); final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided( @@ -209,7 +215,37 @@ public class LoanAssembler { loanProduct.maxTrancheCount(), disbursementDetails.size()); } } - final Set collateral = this.loanCollateralAssembler.fromParsedJson(element); + + final String loanTypeParameterName = "loanType"; + final String loanTypeStr = this.fromApiJsonHelper.extractStringNamed(loanTypeParameterName, element); + final EnumOptionData loanType = AccountEnumerations.loanType(loanTypeStr); + Set collateral = new HashSet<>(); + + if (!StringUtils.isBlank(loanTypeStr)) { + final AccountType loanAccountType = AccountType.fromName(loanTypeStr); + + if (loanAccountType.isIndividualAccount()) { + collateral = this.collateralAssembler.fromParsedJson(element); + + if (collateral.size() == 0) { + throw new InvalidAmountOfCollaterals(BigDecimal.ZERO); + } + + BigDecimal totalValue = BigDecimal.ZERO; + for (LoanCollateralManagement collateralManagement : collateral) { + final CollateralManagementDomain collateralManagementDomain = collateralManagement.getClientCollateralManagement() + .getCollaterals(); + BigDecimal totalCollateral = collateralManagement.getQuantity().multiply(collateralManagementDomain.getBasePrice()) + .multiply(collateralManagementDomain.getPctToBase()).divide(BigDecimal.valueOf(100)); + totalValue = totalValue.add(totalCollateral); + } + + if (amount.compareTo(totalValue) > 0) { + throw new InvalidAmountOfCollaterals(totalValue); + } + } + } + final Set loanCharges = this.loanChargeAssembler.fromParsedJson(element, disbursementDetails); for (final LoanCharge loanCharge : loanCharges) { if (!loanProduct.hasCurrencyCodeOf(loanCharge.currencyCode())) { @@ -239,10 +275,6 @@ public class LoanAssembler { final Boolean isFloatingInterestRate = this.fromApiJsonHelper .extractBooleanNamed(LoanApiConstants.isFloatingInterestRateParameterName, element); - final String loanTypeParameterName = "loanType"; - final String loanTypeStr = this.fromApiJsonHelper.extractStringNamed(loanTypeParameterName, element); - final EnumOptionData loanType = AccountEnumerations.loanType(loanTypeStr); - if (clientId != null) { client = this.clientRepository.findOneWithNotFoundDetection(clientId); if (client.isNotActive()) { @@ -264,14 +296,13 @@ public class LoanAssembler { } loanApplication = Loan.newIndividualLoanApplicationFromGroup(accountNo, client, group, loanType.getId().intValue(), loanProduct, - fund, loanOfficer, loanPurpose, loanTransactionProcessingStrategy, loanProductRelatedDetail, loanCharges, collateral, + fund, loanOfficer, loanPurpose, loanTransactionProcessingStrategy, loanProductRelatedDetail, loanCharges, null, syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates); } else if (group != null) { - loanApplication = Loan.newGroupLoanApplication(accountNo, group, loanType.getId().intValue(), loanProduct, fund, loanOfficer, - loanPurpose, loanTransactionProcessingStrategy, loanProductRelatedDetail, loanCharges, collateral, + loanPurpose, loanTransactionProcessingStrategy, loanProductRelatedDetail, loanCharges, null, syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 4bf120ede..7fab6a547 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -111,6 +111,8 @@ import org.apache.fineract.portfolio.charge.exception.LoanChargeCannotBeWaivedEx import org.apache.fineract.portfolio.charge.exception.LoanChargeNotFoundException; import org.apache.fineract.portfolio.client.domain.Client; import org.apache.fineract.portfolio.client.exception.ClientNotActiveException; +import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement; +import org.apache.fineract.portfolio.collateralmanagement.exception.LoanCollateralAmountNotSufficientException; import org.apache.fineract.portfolio.collectionsheet.command.CollectionSheetBulkDisbursalCommand; import org.apache.fineract.portfolio.collectionsheet.command.CollectionSheetBulkRepaymentCommand; import org.apache.fineract.portfolio.collectionsheet.command.SingleDisbursalCommand; @@ -136,6 +138,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService; import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge; import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeRepository; +import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement; import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails; import org.apache.fineract.portfolio.loanaccount.domain.LoanEvent; import org.apache.fineract.portfolio.loanaccount.domain.LoanInstallmentCharge; @@ -348,6 +351,28 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final Loan loan = this.loanAssembler.assembleFrom(loanId); + // Get disbursedAmount + final BigDecimal disbursedAmount = loan.getDisbursedAmount(); + + // Get relevant loan collateral modules + if (AccountType.fromInt(loan.getLoanType()).isIndividualAccount()) { + final Set loanCollateralManagements = loan.getLoanCollateralManagements(); + + BigDecimal totalCollateral = BigDecimal.valueOf(0); + + for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagements) { + BigDecimal quantity = loanCollateralManagement.getQuantity(); + BigDecimal pctToBase = loanCollateralManagement.getClientCollateralManagement().getCollaterals().getPctToBase(); + BigDecimal basePrice = loanCollateralManagement.getClientCollateralManagement().getCollaterals().getBasePrice(); + totalCollateral = totalCollateral.add(quantity.multiply(basePrice).multiply(pctToBase).divide(BigDecimal.valueOf(100))); + } + + // Validate the loan collateral value against the disbursedAmount + if (disbursedAmount.compareTo(totalCollateral) > 0) { + throw new LoanCollateralAmountNotSufficientException(disbursedAmount); + } + } + final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate"); // validate ActualDisbursement Date Against Expected Disbursement Date @@ -892,8 +917,26 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final HolidayDetailDTO holidayDetailDto = null; boolean isAccountTransfer = false; final CommandProcessingResultBuilder commandProcessingResultBuilder = new CommandProcessingResultBuilder(); - this.loanAccountDomainService.makeRepayment(loan, commandProcessingResultBuilder, transactionDate, transactionAmount, paymentDetail, - noteText, txnExternalId, isRecoveryRepayment, isAccountTransfer, holidayDetailDto, isHolidayValidationDone); + LoanTransaction loanTransaction = this.loanAccountDomainService.makeRepayment(loan, commandProcessingResultBuilder, transactionDate, + transactionAmount, paymentDetail, noteText, txnExternalId, isRecoveryRepayment, isAccountTransfer, holidayDetailDto, + isHolidayValidationDone); + + // Update loan transaction on repayment. + if (AccountType.fromInt(loan.getLoanType()).isIndividualAccount()) { + Set loanCollateralManagements = loan.getLoanCollateralManagements(); + for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagements) { + loanCollateralManagement.setLoanTransactionData(loanTransaction); + ClientCollateralManagement clientCollateralManagement = loanCollateralManagement.getClientCollateralManagement(); + + if (loan.status().isClosed()) { + loanCollateralManagement.setIsReleased(Integer.valueOf(1)); + BigDecimal quantity = loanCollateralManagement.getQuantity(); + clientCollateralManagement.updateQuantity(clientCollateralManagement.getQuantity().add(quantity)); + loanCollateralManagement.setClientCollateralManagement(clientCollateralManagement); + } + } + this.loanAccountDomainService.updateLoanCollateralTransaction(loanCollateralManagements); + } return commandProcessingResultBuilder.withCommandId(command.commandId()) // .withLoanId(loanId) // @@ -1290,9 +1333,26 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); } this.loanAccountDomainService.recalculateAccruals(loan); + this.businessEventNotifierService.notifyBusinessEventWasExecuted(BusinessEvents.LOAN_CLOSE, constructEntityMap(BusinessEntity.LOAN, loan)); + // Update loan transaction on repayment. + if (AccountType.fromInt(loan.getLoanType()).isIndividualAccount()) { + Set loanCollateralManagements = loan.getLoanCollateralManagements(); + for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagements) { + ClientCollateralManagement clientCollateralManagement = loanCollateralManagement.getClientCollateralManagement(); + + if (loan.status().isClosed()) { + loanCollateralManagement.setIsReleased(Integer.valueOf(1)); + BigDecimal quantity = loanCollateralManagement.getQuantity(); + clientCollateralManagement.updateQuantity(clientCollateralManagement.getQuantity().add(quantity)); + loanCollateralManagement.setClientCollateralManagement(clientCollateralManagement); + } + } + this.loanAccountDomainService.updateLoanCollateralTransaction(loanCollateralManagements); + } + // disable all active standing instructions linked to the loan this.loanAccountDomainService.disableStandingInstructionsLinkedToClosedLoan(loan); @@ -1344,6 +1404,22 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf // disable all active standing instructions linked to the loan this.loanAccountDomainService.disableStandingInstructionsLinkedToClosedLoan(loan); + // Update loan transaction on repayment. + if (AccountType.fromInt(loan.getLoanType()).isIndividualAccount()) { + Set loanCollateralManagements = loan.getLoanCollateralManagements(); + for (LoanCollateralManagement loanCollateralManagement : loanCollateralManagements) { + ClientCollateralManagement clientCollateralManagement = loanCollateralManagement.getClientCollateralManagement(); + + if (loan.status().isClosed()) { + loanCollateralManagement.setIsReleased(Integer.valueOf(1)); + BigDecimal quantity = loanCollateralManagement.getQuantity(); + clientCollateralManagement.updateQuantity(clientCollateralManagement.getQuantity().add(quantity)); + loanCollateralManagement.setClientCollateralManagement(clientCollateralManagement); + } + } + this.loanAccountDomainService.updateLoanCollateralTransaction(loanCollateralManagements); + } + return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // .withEntityId(loanId) // diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V27__add-loan-type-column-to-loan-table.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V27__add-loan-type-column-to-loan-table.sql index e806bddc6..cad7fe82a 100644 --- a/fineract-provider/src/main/resources/sql/migrations/core_db/V27__add-loan-type-column-to-loan-table.sql +++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V27__add-loan-type-column-to-loan-table.sql @@ -19,3 +19,48 @@ ALTER TABLE `m_loan` ADD COLUMN `loan_type_enum` SMALLINT NOT NULL AFTER `loan_status_id`; + +-- create collateral management table +CREATE TABLE IF NOT EXISTS `m_collateral_management` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `quality` varchar(40) NOT NULL, + `base_price` decimal(20,5) NOT NULL, + `unit_type` varchar(10) NOT NULL, + `pct_to_base` decimal(20,5) NOT NULL, + `currency` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + KEY `fkCurrencyCode` (`currency`), + CONSTRAINT `fkCurrencyCode` FOREIGN KEY (`currency`) REFERENCES `m_currency` (`id`) ON DELETE CASCADE +); + +-- create client collateral management +CREATE TABLE IF NOT EXISTS `m_client_collateral_management` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `quantity` decimal(20,5) NOT NULL, + `client_id` bigint(20) DEFAULT NULL, + `collateral_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + KEY `fkClient` (`client_id`), + KEY `fkCollateral` (`collateral_id`), + CONSTRAINT `fkClient` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `fkCollateral` FOREIGN KEY (`collateral_id`) REFERENCES `m_collateral_management` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +); + + +-- create loan collateral management +CREATE TABLE IF NOT EXISTS `m_loan_collateral_management` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `quantity` decimal(20,5) NOT NULL, + `loan_id` bigint(20) DEFAULT NULL, + `client_collateral_id` bigint(20) DEFAULT NULL, + `is_released` tinyint(4) DEFAULT '0', + `transaction_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + KEY `fkLoan` (`loan_id`), + KEY `fkTransaction` (`transaction_id`), + KEY `fkClientCollateral` (`client_collateral_id`), + CONSTRAINT `fkClientCollateral` FOREIGN KEY (`client_collateral_id`) REFERENCES `m_client_collateral_management` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `fkLoan` FOREIGN KEY (`loan_id`) REFERENCES `m_loan` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `fkTransaction` FOREIGN KEY (`transaction_id`) REFERENCES `m_loan_transaction` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +); diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V368__collateral_management.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V368__collateral_management.sql new file mode 100644 index 000000000..40ec486db --- /dev/null +++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V368__collateral_management.sql @@ -0,0 +1,73 @@ +-- +-- 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. +-- + +-- create collateral management table +CREATE TABLE IF NOT EXISTS `m_collateral_management` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `quality` varchar(40) NOT NULL, + `base_price` decimal(20,5) NOT NULL, + `unit_type` varchar(10) NOT NULL, + `pct_to_base` decimal(20,5) NOT NULL, + `currency` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + KEY `fkCurrencyCode` (`currency`), + CONSTRAINT `fkCurrencyCode` FOREIGN KEY (`currency`) REFERENCES `m_currency` (`id`) ON DELETE CASCADE +); + +-- create client collateral management +CREATE TABLE IF NOT EXISTS `m_client_collateral_management` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `quantity` decimal(20,5) NOT NULL, + `client_id` bigint(20) DEFAULT NULL, + `collateral_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + KEY `fkClient` (`client_id`), + KEY `fkCollateral` (`collateral_id`), + CONSTRAINT `fkClient` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `fkCollateral` FOREIGN KEY (`collateral_id`) REFERENCES `m_collateral_management` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +); + + +-- create loan collateral management +CREATE TABLE IF NOT EXISTS `m_loan_collateral_management` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `quantity` decimal(20,5) NOT NULL, + `loan_id` bigint(20) DEFAULT NULL, + `client_collateral_id` bigint(20) DEFAULT NULL, + `is_released` tinyint(4) DEFAULT '0', + `transaction_id` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + KEY `fkLoan` (`loan_id`), + KEY `fkTransaction` (`transaction_id`), + KEY `fkClientCollateral` (`client_collateral_id`), + CONSTRAINT `fkClientCollateral` FOREIGN KEY (`client_collateral_id`) REFERENCES `m_client_collateral_management` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `fkLoan` FOREIGN KEY (`loan_id`) REFERENCES `m_loan` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `fkTransaction` FOREIGN KEY (`transaction_id`) REFERENCES `m_loan_transaction` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +); + +INSERT INTO `m_permission` +(`grouping`,`code`,`entity_name`,`action_name`,`can_maker_checker`) VALUES +('portfolio', 'CREATE_CLIENT_COLLATERAL_PRODUCT', 'CLIENT_COLLATERAL_PRODUCT', 'CREATE', '0'), +('portfolio', 'CREATE_COLLATERAL_PRODUCT', 'COLLATERAL_PRODUCT', 'CREATE', '0'), +('portfolio', 'DELETE_CLIENT_COLLATERAL_PRODUCT', 'CLIENT_COLLATERAL_PRODUCT', 'DELETE', '0'), +('portfolio', 'DELETE_COLLATERAL_PRODUCT', 'COLLATERAL_PRODUCT', 'DELETE', '0'), +('portfolio', 'DELETE_LOAN_COLLATERAL_PRODUCT', 'LOAN_COLLATERAL_PRODUCT', 'DELETE', '0'), +('portfolio', 'UPDATE_CLIENT_COLLATERAL_PRODUCT', 'CLIENT_COLLATERAL_PRODUCT', 'UPDATE', '0'), +('portfolio', 'UPDATE_COLLATERAL_PRODUCT', 'COLLATERAL_PRODUCT', 'UPDATE', '0'); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AccountNumberPreferencesTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AccountNumberPreferencesTest.java index ef02c3715..cf9bca7ec 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AccountNumberPreferencesTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AccountNumberPreferencesTest.java @@ -23,12 +23,15 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.sql.Timestamp; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import org.apache.fineract.integrationtests.common.CenterDomain; import org.apache.fineract.integrationtests.common.CenterHelper; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.CommonConstants; import org.apache.fineract.integrationtests.common.GroupHelper; import org.apache.fineract.integrationtests.common.OfficeHelper; @@ -355,15 +358,17 @@ public class AccountNumberPreferencesTest { /* Create Client with Client Type */ this.clientId = ClientHelper.createClientForAccountPreference(this.requestSpec, this.responseSpec, this.clientCodeValueId, "clientId"); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, this.clientId); - Assertions.assertNotNull(clientId); + // Assertions.assertNotNull(clientId); clientAccountNo = (String) ClientHelper.getClient(this.requestSpec, this.responseSpec, this.clientId.toString(), "accountNo"); this.validateAccountNumberLengthAndStartsWithPrefix(clientAccountNo, this.clientCodeValueName); } else if (clientPrefixName.equals(this.officeName)) { this.clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientId); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, this.clientId); + // Assertions.assertNotNull(clientId); clientAccountNo = (String) ClientHelper.getClient(requestSpec, responseSpec, this.clientId.toString(), "accountNo"); String officeName = (String) ClientHelper.getClient(requestSpec, responseSpec, this.clientId.toString(), "officeName"); this.validateAccountNumberLengthAndStartsWithPrefix(clientAccountNo, officeName); @@ -393,17 +398,34 @@ public class AccountNumberPreferencesTest { LOG.info("Successfully created loan product (ID: {} )", this.loanProductId); } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + private void createAndValidateLoanEntity(Boolean isAccountPreferenceSetUp) { this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); LOG.info("---------------------------------NEW LOAN APPLICATION------------------------------------------"); - + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + this.clientId.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(loanPrincipalAmount) .withLoanTermFrequency(numberOfRepayments).withLoanTermFrequencyAsMonths().withNumberOfRepayments(numberOfRepayments) .withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments() .withInterestCalculationPeriodTypeAsDays().withInterestRatePerPeriod(interestRatePerPeriod).withLoanTermFrequencyAsMonths() .withSubmittedOnDate(dateString).withExpectedDisbursementDate(dateString).withPrincipalGrace("2").withInterestGrace("2") - .build(this.clientId.toString(), this.loanProductId.toString(), null); + .withCollaterals(collaterals).build(this.clientId.toString(), this.loanProductId.toString(), null); LOG.info("Loan Application :{}", loanApplicationJSON); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AccountTransferTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AccountTransferTest.java index 8d7ef09af..31c77aea5 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AccountTransferTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AccountTransferTest.java @@ -25,9 +25,12 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.CommonConstants; import org.apache.fineract.integrationtests.common.OfficeHelper; import org.apache.fineract.integrationtests.common.Utils; @@ -474,6 +477,14 @@ public class AccountTransferTest { private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal("8,000.00") // .withLoanTermFrequency("4") // @@ -487,7 +498,18 @@ public class AccountTransferTest { .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withExpectedDisbursementDate("10 January 2013") // .withSubmittedOnDate("10 January 2013") // - .build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } + + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AccountingScenarioIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AccountingScenarioIntegrationTest.java index a66e491c5..7d92d47d9 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AccountingScenarioIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AccountingScenarioIntegrationTest.java @@ -25,6 +25,7 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.text.DateFormat; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; @@ -39,6 +40,7 @@ import java.util.List; import java.util.Locale; import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.CommonConstants; import org.apache.fineract.integrationtests.common.SchedulerJobHelper; import org.apache.fineract.integrationtests.common.Utils; @@ -138,7 +140,16 @@ public class AccountingScenarioIntegrationTest { overpaymentAccount); final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec, DATE_OF_JOINING); - final Integer loanID = applyForLoanApplication(clientID, loanProductID); + + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(requestSpec, responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(requestSpec, responseSpec, clientID.toString(), + collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + + final Integer loanID = applyForLoanApplication(clientID, loanProductID, collaterals); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -238,14 +249,14 @@ public class AccountingScenarioIntegrationTest { return this.loanTransactionHelper.getLoanProductId(loanProductJSON); } - private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID) { + private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, List collaterals) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(LP_PRINCIPAL.toString()) .withLoanTermFrequency(LOAN_TERM_FREQUENCY).withLoanTermFrequencyAsMonths().withNumberOfRepayments(LP_REPAYMENTS) .withRepaymentEveryAfter(LP_REPAYMENT_PERIOD).withRepaymentFrequencyTypeAsMonths() .withInterestRatePerPeriod(LP_INTEREST_RATE).withInterestTypeAsFlatBalance().withAmortizationTypeAsEqualPrincipalPayments() .withInterestCalculationPeriodTypeSameAsRepaymentPeriod().withExpectedDisbursementDate(EXPECTED_DISBURSAL_DATE) - .withSubmittedOnDate(LOAN_APPLICATION_SUBMISSION_DATE).withLoanType(INDIVIDUAL_LOAN) + .withSubmittedOnDate(LOAN_APPLICATION_SUBMISSION_DATE).withLoanType(INDIVIDUAL_LOAN).withCollaterals(collaterals) .build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } @@ -378,7 +389,8 @@ public class AccountingScenarioIntegrationTest { final Account liabilityAccount = this.accountHelper.createLiabilityAccount(); Integer clientId = ClientHelper.createClient(requestSpec, responseSpec); - Assertions.assertNotNull(clientId); + ClientHelper.verifyClientCreatedOnServer(requestSpec, responseSpec, clientId); + // Assertions.assertNotNull(clientId); Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO, assetAccount, incomeAccount, expenseAccount, liabilityAccount); @@ -456,7 +468,7 @@ public class AccountingScenarioIntegrationTest { final String INTEREST_POSTED_DATE = dateFormat.format(todaysDate.getTime()); Integer clientId = ClientHelper.createClient(requestSpec, responseSpec); - Assertions.assertNotNull(clientId); + ClientHelper.verifyClientCreatedOnServer(requestSpec, responseSpec, clientId); Integer recurringDepositProductId = createRecurringDepositProduct(VALID_FROM, VALID_TO, assetAccount, liabilityAccount, incomeAccount, expenseAccount); @@ -564,7 +576,16 @@ public class AccountingScenarioIntegrationTest { overpaymentAccount); final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec, DATE_OF_JOINING); - final Integer loanID = applyForLoanApplication(clientID, loanProductID); + + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(requestSpec, responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(requestSpec, responseSpec, clientID.toString(), + collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + + final Integer loanID = applyForLoanApplication(clientID, loanProductID, collaterals); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -677,7 +698,16 @@ public class AccountingScenarioIntegrationTest { overpaymentAccount); final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec, DATE_OF_JOINING); - final Integer loanID = applyForLoanApplication(clientID, loanProductID); + + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(requestSpec, responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(requestSpec, responseSpec, clientID.toString(), + collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + + final Integer loanID = applyForLoanApplication(clientID, loanProductID, collaterals); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -721,6 +751,17 @@ public class AccountingScenarioIntegrationTest { } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + @Test public void checkPeriodicAccrualAccountingTillCurrentDateFlow() throws InterruptedException, ParseException { final Account assetAccount = this.accountHelper.createAssetAccount(); @@ -732,7 +773,16 @@ public class AccountingScenarioIntegrationTest { overpaymentAccount); final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec, DATE_OF_JOINING); - final Integer loanID = applyForLoanApplication(clientID, loanProductID); + + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(requestSpec, responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(requestSpec, responseSpec, clientID.toString(), + collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + + final Integer loanID = applyForLoanApplication(clientID, loanProductID, collaterals); final float FEE_PORTION = 50.0f; final float PENALTY_PORTION = 100.0f; @@ -821,7 +871,16 @@ public class AccountingScenarioIntegrationTest { overpaymentAccount); final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec, DATE_OF_JOINING); - final Integer loanID = applyForLoanApplication(clientID, loanProductID); + + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(requestSpec, responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(requestSpec, responseSpec, clientID.toString(), + collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + + final Integer loanID = applyForLoanApplication(clientID, loanProductID, collaterals); final float FEE_PORTION = 50.0f; final float PENALTY_PORTION = 100.0f; @@ -942,7 +1001,16 @@ public class AccountingScenarioIntegrationTest { overpaymentAccount); final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec, DATE_OF_JOINING); - final Integer loanID = applyForLoanApplication(clientID, loanProductID); + + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(requestSpec, responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(requestSpec, responseSpec, clientID.toString(), + collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + + final Integer loanID = applyForLoanApplication(clientID, loanProductID, collaterals); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AuditIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AuditIntegrationTest.java index 327a2fb9a..cb51d9a25 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AuditIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AuditIntegrationTest.java @@ -31,7 +31,6 @@ import org.apache.fineract.integrationtests.common.AuditHelper; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.OfficeHelper; import org.apache.fineract.integrationtests.common.Utils; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -77,7 +76,8 @@ public class AuditIntegrationTest { // When Client is created: Count should be "1" final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientId); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientId); + auditsRecieved = auditHelper.getAuditDetails(clientId, "CREATE", "CLIENT"); auditHelper.verifyOneAuditOnly(auditsRecieved, clientId, "CREATE", "CLIENT"); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BatchApiTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BatchApiTest.java index e0f45b871..022c1e8a9 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BatchApiTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BatchApiTest.java @@ -32,6 +32,8 @@ import org.apache.fineract.batch.domain.BatchRequest; import org.apache.fineract.batch.domain.BatchResponse; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; import org.apache.fineract.integrationtests.common.BatchHelper; +import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; @@ -202,6 +204,15 @@ public class BatchApiTest { .withInterestTypeAsDecliningBalance() // .currencyDetails("0", "100").build(null); + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + final Integer productId = new LoanTransactionHelper(this.requestSpec, this.responseSpec).getLoanProductId(loanProductJSON); // Create a createClient Request @@ -211,7 +222,7 @@ public class BatchApiTest { final BatchRequest br2 = BatchHelper.activateClientRequest(4719L, 4718L); // Create a ApplyLoan Request - final BatchRequest br3 = BatchHelper.applyLoanRequest(4720L, 4719L, productId); + final BatchRequest br3 = BatchHelper.applyLoanRequest(4720L, 4719L, productId, clientCollateralId); final List batchRequests = new ArrayList<>(); @@ -293,6 +304,15 @@ public class BatchApiTest { .withInterestTypeAsDecliningBalance() // .currencyDetails("0", "100").build(null); + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + final Integer productId = new LoanTransactionHelper(this.requestSpec, this.responseSpec).getLoanProductId(loanProductJSON); // Create a createClient Request @@ -302,7 +322,7 @@ public class BatchApiTest { final BatchRequest br2 = BatchHelper.activateClientRequest(4723L, 4722L); // Create a ApplyLoan Request - final BatchRequest br3 = BatchHelper.applyLoanRequest(4724L, 4723L, productId); + final BatchRequest br3 = BatchHelper.applyLoanRequest(4724L, 4723L, productId, clientCollateralId); // Create a Collect Charges Request final BatchRequest br4 = BatchHelper.collectChargesRequest(4725L, 4724L); @@ -343,6 +363,15 @@ public class BatchApiTest { .withInterestTypeAsDecliningBalance() // .currencyDetails("0", "100").build(null); + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + final Integer productId = new LoanTransactionHelper(this.requestSpec, this.responseSpec).getLoanProductId(loanProductJSON); // Create a createClient Request @@ -352,7 +381,7 @@ public class BatchApiTest { final BatchRequest br2 = BatchHelper.activateClientRequest(4731L, 4730L); // Create a ApplyLoan Request - final BatchRequest br3 = BatchHelper.applyLoanRequest(4732L, 4731L, productId); + final BatchRequest br3 = BatchHelper.applyLoanRequest(4732L, 4731L, productId, clientCollateralId); // Create a approveLoan Request final BatchRequest br4 = BatchHelper.approveLoanRequest(4733L, 4732L); @@ -434,6 +463,15 @@ public class BatchApiTest { .withInterestTypeAsDecliningBalance() // .currencyDetails("0", "100").build(null); + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + final Integer productId = new LoanTransactionHelper(this.requestSpec, this.responseSpec).getLoanProductId(loanProductJSON); // Create a createClient Request @@ -443,7 +481,7 @@ public class BatchApiTest { final BatchRequest br2 = BatchHelper.activateClientRequest(4731L, 4730L); // Create a ApplyLoan Request - final BatchRequest br3 = BatchHelper.applyLoanRequest(4732L, 4731L, productId); + final BatchRequest br3 = BatchHelper.applyLoanRequest(4732L, 4731L, productId, clientCollateralId); // Create a approveLoan Request final BatchRequest br4 = BatchHelper.approveLoanRequest(4733L, 4732L); @@ -488,13 +526,22 @@ public class BatchApiTest { .withInterestTypeAsDecliningBalance() // .currencyDetails("0", "100").build(null); + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + final Integer productId = new LoanTransactionHelper(this.requestSpec, this.responseSpec).getLoanProductId(loanProductJSON); // Create a createClient Request final BatchRequest br1 = BatchHelper.createActiveClientRequest(4740L, ""); // Create a ApplyLoan Request - final BatchRequest br2 = BatchHelper.applyLoanRequest(4742L, 4740L, productId); + final BatchRequest br2 = BatchHelper.applyLoanRequest(4742L, 4740L, productId, clientCollateralId); // Create a approveLoan Request final BatchRequest br3 = BatchHelper.approveLoanRequest(4743L, 4742L); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BatchRequestsIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BatchRequestsIntegrationTest.java index af37939b4..fd835ce77 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BatchRequestsIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BatchRequestsIntegrationTest.java @@ -29,6 +29,7 @@ import org.apache.fineract.batch.domain.BatchRequest; import org.apache.fineract.batch.domain.BatchResponse; import org.apache.fineract.integrationtests.common.BatchHelper; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.GroupHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; @@ -119,7 +120,14 @@ public class BatchRequestsIntegrationTest { // Select a few clients from created group at random Integer selClientsCount = (int) Math.ceil(Math.random() * clientsCount) + 2; for (int i = 0; i < selClientsCount; i++) { - BatchRequest br = BatchHelper.applyLoanRequest((long) selClientsCount, null, loanProductID); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientIDs[(int) Math.floor(Math.random() * (clientsCount - 1))]), collateralId); + Assertions.assertNotNull(clientCollateralId); + + BatchRequest br = BatchHelper.applyLoanRequest((long) selClientsCount, null, loanProductID, clientCollateralId); br.setBody(br.getBody().replace("$.clientId", String.valueOf(clientIDs[(int) Math.floor(Math.random() * (clientsCount - 1))]))); batchRequests.add(br); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientCollateralIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientCollateralIntegrationTest.java new file mode 100644 index 000000000..1df188ff9 --- /dev/null +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientCollateralIntegrationTest.java @@ -0,0 +1,78 @@ +/** + * 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.integrationtests; + +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.builder.ResponseSpecBuilder; +import io.restassured.http.ContentType; +import io.restassured.specification.RequestSpecification; +import io.restassured.specification.ResponseSpecification; +import java.util.HashMap; +import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; +import org.apache.fineract.integrationtests.common.Utils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ClientCollateralIntegrationTest { + + private static final Logger LOG = LoggerFactory.getLogger(ClientCollateralIntegrationTest.class); + private ResponseSpecification responseSpec; + private RequestSpecification requestSpec; + + @BeforeEach + public void setup() { + Utils.initializeRESTAssured(); + this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); + this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); + this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); + } + + @Test + public void createClientCollateralTest() { + LOG.info("-------------------------Creating Client Collateral---------------------------"); + final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec); + ClientHelper.verifyClientCreatedOnServer(requestSpec, responseSpec, clientID); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + } + + @Test + public void updateClientCollateral() { + LOG.info("-------------------------Updating Client Collateral---------------------------"); + final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec); + ClientHelper.verifyClientCreatedOnServer(requestSpec, responseSpec, clientID); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + final HashMap changes = CollateralManagementHelper.updateClientCollateral(this.requestSpec, this.responseSpec, clientCollateralId); + Assertions.assertEquals("1", changes.get("quantity").toString()); + } + +} diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java index e42fa892b..990111a5a 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java @@ -41,6 +41,7 @@ import java.util.List; import java.util.Map; import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.SchedulerJobHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.accounting.Account; @@ -103,11 +104,19 @@ public class ClientLoanIntegrationTest { @Test public void checkClientLoanCreateAndDisburseFlow() { this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + List collaterals = new ArrayList<>(); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanProductID = createLoanProduct(false, NONE); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, null, "12,000.00"); + final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, null, "12,000.00", collaterals); final ArrayList loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); verifyLoanRepaymentSchedule(loanSchedule); @@ -116,11 +125,18 @@ public class ClientLoanIntegrationTest { @Test public void testLoanCharges_DISBURSEMENT_FEE() { this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); final Integer loanProductID = createLoanProduct(false, NONE); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + List collaterals = new ArrayList<>(); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + List charges = new ArrayList<>(); Integer flatDisbursement = ChargesHelper.createCharges(requestSpec, responseSpec, ChargesHelper.getLoanDisbursementJSON()); @@ -134,7 +150,7 @@ public class ClientLoanIntegrationTest { ChargesHelper.getLoanDisbursementJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_INTEREST, "1")); addCharges(charges, interestPercentage, "1", null); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00"); + final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); @@ -180,7 +196,7 @@ public class ClientLoanIntegrationTest { validateNumberForEqual("654.24", String.valueOf(disbursementDetail.get("feeChargesDue"))); this.loanTransactionHelper.updateLoan(loanID, - updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, null, null), null)); + updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, null, null), null, collaterals)); loanCharges = this.loanTransactionHelper.getLoanCharges(loanID); loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); @@ -192,7 +208,7 @@ public class ClientLoanIntegrationTest { validateNumberForEqual("570.2", String.valueOf(disbursementDetail.get("feeChargesDue"))); this.loanTransactionHelper.updateLoan(loanID, - updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, flatDisbursement, "1"), null)); + updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, flatDisbursement, "1"), null, collaterals)); loanCharges = this.loanTransactionHelper.getLoanCharges(loanID); loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); @@ -204,7 +220,7 @@ public class ClientLoanIntegrationTest { charges.clear(); addCharges(charges, flatDisbursement, "100", null); - this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, charges, null)); + this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, charges, null, collaterals)); loanCharges = this.loanTransactionHelper.getLoanCharges(loanID); loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); @@ -240,7 +256,16 @@ public class ClientLoanIntegrationTest { ChargesHelper.getLoanDisbursementJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_INTEREST, "1")); addCharges(charges, interestPercentage, "1", null); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00"); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + + final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); @@ -301,7 +326,16 @@ public class ClientLoanIntegrationTest { ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_INTEREST, "1", false)); addCharges(charges, interestPercentage, "1", "29 September 2011"); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00"); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + + final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); @@ -348,8 +382,8 @@ public class ClientLoanIntegrationTest { final Integer savingsId = SavingsAccountHelper.openSavingsAccount(this.requestSpec, this.responseSpec, clientID, MINIMUM_OPENING_BALANCE); - this.loanTransactionHelper.updateLoan(loanID, - updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, null, null), String.valueOf(savingsId))); + this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, null, null), + String.valueOf(savingsId), collaterals)); loanCharges = this.loanTransactionHelper.getLoanCharges(loanID); loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); @@ -361,7 +395,7 @@ public class ClientLoanIntegrationTest { validateNumberForEqual("570.2", String.valueOf(firstInstallment.get("feeChargesDue"))); this.loanTransactionHelper.updateLoan(loanID, - updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, flat, "1"), null)); + updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, flat, "1"), null, collaterals)); loanCharges = this.loanTransactionHelper.getLoanCharges(loanID); loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); @@ -373,7 +407,7 @@ public class ClientLoanIntegrationTest { charges.clear(); addCharges(charges, flat, "100", "29 September 2011"); - this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, charges, null)); + this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, charges, null, collaterals)); loanCharges = this.loanTransactionHelper.getLoanCharges(loanID); loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); @@ -461,7 +495,15 @@ public class ClientLoanIntegrationTest { ChargesHelper.getLoanInstallmentJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_INTEREST, "1", false)); addCharges(charges, interestPercentage, "1", "29 September 2011"); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00"); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + + final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); @@ -553,8 +595,8 @@ public class ClientLoanIntegrationTest { final Integer savingsId = SavingsAccountHelper.openSavingsAccount(this.requestSpec, this.responseSpec, clientID, MINIMUM_OPENING_BALANCE); - this.loanTransactionHelper.updateLoan(loanID, - updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, null, null), String.valueOf(savingsId))); + this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, null, null), + String.valueOf(savingsId), collaterals)); loanCharges = this.loanTransactionHelper.getLoanCharges(loanID); loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); @@ -581,7 +623,7 @@ public class ClientLoanIntegrationTest { validateChargeExcludePrecission(flat, loanCharges, "100.0", "400", "0.0", "0.0"); this.loanTransactionHelper.updateLoan(loanID, - updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, flat, "1"), null)); + updateLoanJson(clientID, loanProductID, copyChargesForUpdate(loanCharges, flat, "1"), null, collaterals)); loanCharges = this.loanTransactionHelper.getLoanCharges(loanID); loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); @@ -608,7 +650,7 @@ public class ClientLoanIntegrationTest { charges.clear(); addCharges(charges, flat, "50", "29 September 2011"); - this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, charges, null)); + this.loanTransactionHelper.updateLoan(loanID, updateLoanJson(clientID, loanProductID, charges, null, collaterals)); loanCharges = this.loanTransactionHelper.getLoanCharges(loanID); loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); @@ -715,7 +757,15 @@ public class ClientLoanIntegrationTest { final Integer savingsId = SavingsAccountHelper.openSavingsAccount(this.requestSpec, this.responseSpec, clientID, MINIMUM_OPENING_BALANCE); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, savingsId.toString(), "12,000.00"); + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + + final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, savingsId.toString(), "12,000.00", collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); @@ -760,7 +810,16 @@ public class ClientLoanIntegrationTest { tranches.add(createTrancheDetail("01 March 2014", "25000")); tranches.add(createTrancheDetail("23 April 2014", "20000")); - final Integer loanID = applyForLoanApplicationWithTranches(clientID, loanProductID, null, null, "45,000.00", tranches); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + + final Integer loanID = applyForLoanApplicationWithTranches(clientID, loanProductID, null, null, "45,000.00", tranches, collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); @@ -803,8 +862,17 @@ public class ClientLoanIntegrationTest { tranches.add(createTrancheDetail("01 March 2014", "25000")); tranches.add(createTrancheDetail("23 April 2014", "20000")); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanID = applyForLoanApplicationWithTranches(clientID, loanProductID, null, savingsId.toString(), "45,000.00", - tranches); + tranches, collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); @@ -938,7 +1006,8 @@ public class ClientLoanIntegrationTest { return this.loanTransactionHelper.getLoanProductId(loanProductJSON); } - private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, String graceOnPrincipalPayment) { + private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, String graceOnPrincipalPayment, + List collaterals) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal("10000000.00") // @@ -953,12 +1022,12 @@ public class ClientLoanIntegrationTest { .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withPrincipalGrace(graceOnPrincipalPayment).withExpectedDisbursementDate("02 June 2014") // .withSubmittedOnDate("02 June 2014") // - .build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, List charges, - final String savingsId, String principal) { + final String savingsId, String principal, List collaterals) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal(principal) // @@ -973,12 +1042,12 @@ public class ClientLoanIntegrationTest { .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withExpectedDisbursementDate("20 September 2011") // .withSubmittedOnDate("20 September 2011") // - .withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); + .withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } private Integer applyForLoanApplicationWithTranches(final Integer clientID, final Integer loanProductID, List charges, - final String savingsId, String principal, List tranches) { + final String savingsId, String principal, List tranches, List collaterals) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal(principal) // @@ -992,14 +1061,14 @@ public class ClientLoanIntegrationTest { .withInterestTypeAsDecliningBalance() // .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withExpectedDisbursementDate("01 March 2014") // - .withTranches(tranches) // + .withCollaterals(collaterals).withTranches(tranches) // .withSubmittedOnDate("01 March 2014") // - .withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } - private String updateLoanJson(final Integer clientID, final Integer loanProductID, List charges, String savingsId) { + private String updateLoanJson(final Integer clientID, final Integer loanProductID, List charges, String savingsId, + List collaterals) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal("10,000.00") // @@ -1014,12 +1083,12 @@ public class ClientLoanIntegrationTest { .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withExpectedDisbursementDate("20 September 2011") // .withSubmittedOnDate("20 September 2011") // - .withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); + .withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); return loanApplicationJSON; } private Integer applyForLoanApplicationWithPaymentStrategy(final Integer clientID, final Integer loanProductID, List charges, - final String savingsId, String principal, final String repaymentStrategy) { + final String savingsId, String principal, final String repaymentStrategy, final List collaterals) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal(principal) // @@ -1035,12 +1104,13 @@ public class ClientLoanIntegrationTest { .withExpectedDisbursementDate("20 September 2011") // .withSubmittedOnDate("20 September 2011") // .withwithRepaymentStrategy(repaymentStrategy) // - .withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); + .withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } private Integer applyForLoanApplicationWithPaymentStrategyAndPastMonth(final Integer clientID, final Integer loanProductID, - List charges, final String savingsId, String principal, final String repaymentStrategy, final int month) { + List charges, final String savingsId, String principal, final String repaymentStrategy, final int month, + List collaterals) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); Calendar fourMonthsfromNowCalendar = Calendar.getInstance(Utils.getTimeZoneOfTenant()); @@ -1062,7 +1132,7 @@ public class ClientLoanIntegrationTest { .withExpectedDisbursementDate(fourMonthsfromNow) // .withSubmittedOnDate(fourMonthsfromNow) // .withwithRepaymentStrategy(repaymentStrategy) // - .withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); + .withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } @@ -1203,6 +1273,10 @@ public class ClientLoanIntegrationTest { charges.add(charges(chargeId, amount, duedate)); } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + private HashMap charges(Integer chargeId, String amount, String duedate) { HashMap charge = new HashMap(2); charge.put("chargeId", chargeId.toString()); @@ -1213,6 +1287,13 @@ public class ClientLoanIntegrationTest { return charge; } + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + private HashMap getloanCharge(Integer chargeId, List charges) { HashMap charge = null; for (HashMap loancharge : charges) { @@ -1282,8 +1363,17 @@ public class ClientLoanIntegrationTest { final Account expenseAccount = this.accountHelper.createExpenseAccount(); final Account overpaymentAccount = this.accountHelper.createLiabilityAccount(); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanProductID = createLoanProduct(false, CASH_BASED, assetAccount, incomeAccount, expenseAccount, overpaymentAccount); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00"); + + final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -1462,8 +1552,17 @@ public class ClientLoanIntegrationTest { final Account expenseAccount = this.accountHelper.createExpenseAccount(); final Account overpaymentAccount = this.accountHelper.createLiabilityAccount(); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanProductID = createLoanProduct(false, CASH_BASED, assetAccount, incomeAccount, expenseAccount, overpaymentAccount); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00"); + final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -1642,8 +1741,18 @@ public class ClientLoanIntegrationTest { final Account expenseAccount = this.accountHelper.createExpenseAccount(); final Account overpaymentAccount = this.accountHelper.createLiabilityAccount(); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(collateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanProductID = createLoanProduct(false, CASH_BASED, assetAccount, incomeAccount, expenseAccount, overpaymentAccount); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00"); + final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -1819,9 +1928,18 @@ public class ClientLoanIntegrationTest { final Account expenseAccount = this.accountHelper.createExpenseAccount(); final Account overpaymentAccount = this.accountHelper.createLiabilityAccount(); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanProductID = createLoanProduct(false, ACCRUAL_UPFRONT, assetAccount, incomeAccount, expenseAccount, overpaymentAccount); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00"); + final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -2016,9 +2134,18 @@ public class ClientLoanIntegrationTest { final Account expenseAccount = this.accountHelper.createExpenseAccount(); final Account overpaymentAccount = this.accountHelper.createLiabilityAccount(); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanProductID = createLoanProduct(false, ACCRUAL_UPFRONT, assetAccount, incomeAccount, expenseAccount, overpaymentAccount); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00"); + final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -2205,9 +2332,17 @@ public class ClientLoanIntegrationTest { final Account expenseAccount = this.accountHelper.createExpenseAccount(); final Account overpaymentAccount = this.accountHelper.createLiabilityAccount(); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanProductID = createLoanProduct(false, ACCRUAL_UPFRONT, assetAccount, incomeAccount, expenseAccount, overpaymentAccount); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00"); + final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -2399,9 +2534,17 @@ public class ClientLoanIntegrationTest { final Account expenseAccount = this.accountHelper.createExpenseAccount(); final Account overpaymentAccount = this.accountHelper.createLiabilityAccount(); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanProductID = createLoanProduct(false, ACCRUAL_PERIODIC, assetAccount, incomeAccount, expenseAccount, overpaymentAccount); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00"); + final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -2591,9 +2734,17 @@ public class ClientLoanIntegrationTest { final Account expenseAccount = this.accountHelper.createExpenseAccount(); final Account overpaymentAccount = this.accountHelper.createLiabilityAccount(); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanProductID = createLoanProduct(false, ACCRUAL_PERIODIC, assetAccount, incomeAccount, expenseAccount, overpaymentAccount); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00"); + final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -2784,9 +2935,18 @@ public class ClientLoanIntegrationTest { final Account expenseAccount = this.accountHelper.createExpenseAccount(); final Account overpaymentAccount = this.accountHelper.createLiabilityAccount(); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanProductID = createLoanProduct(false, ACCRUAL_PERIODIC, assetAccount, incomeAccount, expenseAccount, overpaymentAccount); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00"); + final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "12,000.00", collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -2954,8 +3114,17 @@ public class ClientLoanIntegrationTest { final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanProductID = createLoanProduct("100", "0", LoanProductTestBuilder.DEFAULT_STRATEGY); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, null); + final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, collaterals); final ArrayList loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); verifyLoanRepaymentScheduleForEqualPrincipal(loanSchedule); @@ -2968,8 +3137,17 @@ public class ClientLoanIntegrationTest { final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanProductID = createLoanProduct("100", "0", LoanProductTestBuilder.DEFAULT_STRATEGY); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, "5"); + final Integer loanID = applyForLoanApplication(clientID, loanProductID, "5", collaterals); final ArrayList loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); verifyLoanRepaymentScheduleForEqualPrincipalWithGrace(loanSchedule); @@ -2997,8 +3175,17 @@ public class ClientLoanIntegrationTest { */ final String savingsId = null; final String principal = "12,000.00"; + + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanID = applyForLoanApplicationWithPaymentStrategy(clientID, loanProductID, null, savingsId, principal, - LoanApplicationTestBuilder.RBI_INDIA_STRATEGY); + LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -4321,6 +4508,15 @@ public class ClientLoanIntegrationTest { final String disbursementDate, final String repaymentStrategy, final List charges, final String graceOnInterestPayment, final String graceOnPrincipalPayment) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + List collaterals = new ArrayList<>(); + + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal("10000.00") // .withLoanTermFrequency("4") // @@ -4338,7 +4534,7 @@ public class ClientLoanIntegrationTest { .withPrincipalGrace(graceOnPrincipalPayment) // .withInterestGrace(graceOnInterestPayment)// .withCharges(charges)// - .build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } @@ -4415,8 +4611,16 @@ public class ClientLoanIntegrationTest { ChargesHelper.getLoanInstallmentJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "50", false)); addCharges(charges, flatInstallmentFee, "50", null); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanID = applyForLoanApplicationWithPaymentStrategyAndPastMonth(clientID, loanProductID, charges, savingsId, - principal, LoanApplicationTestBuilder.DEFAULT_STRATEGY, -4); + principal, LoanApplicationTestBuilder.DEFAULT_STRATEGY, -4, collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -4590,8 +4794,17 @@ public class ClientLoanIntegrationTest { ChargesHelper.getLoanInstallmentJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "50", false)); addCharges(charges, flatInstallmentFee, "50", null); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanID = applyForLoanApplicationWithPaymentStrategyAndPastMonth(clientID, loanProductID, charges, savingsId, - principal, LoanApplicationTestBuilder.DEFAULT_STRATEGY, -4); + principal, LoanApplicationTestBuilder.DEFAULT_STRATEGY, -4, collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -4776,8 +4989,17 @@ public class ClientLoanIntegrationTest { ChargesHelper.getLoanInstallmentJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "50", false)); addCharges(charges, flatInstallmentFee, "50", null); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanID = applyForLoanApplicationWithPaymentStrategyAndPastMonth(clientID, loanProductID, charges, null, principal, - LoanApplicationTestBuilder.DEFAULT_STRATEGY, -4); + LoanApplicationTestBuilder.DEFAULT_STRATEGY, -4, collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -4999,7 +5221,15 @@ public class ClientLoanIntegrationTest { ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "100", true)); addCharges(charges, flatAmountChargeTwo, "100", "15 December 2011"); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "10,000.00"); + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + + final Integer loanID = applyForLoanApplication(clientID, loanProductID, charges, null, "10,000.00", collaterals); Assertions.assertNotNull(loanID); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); @@ -5284,6 +5514,14 @@ public class ClientLoanIntegrationTest { private Integer applyForLoanApplicationWithProductConfigurationAsTrue(final Integer clientID, final Integer loanProductID, String principal) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + List collaterals = new ArrayList<>(); + + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal(principal) // .withRepaymentEveryAfter("1") // @@ -5295,13 +5533,21 @@ public class ClientLoanIntegrationTest { .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withExpectedDisbursementDate("01 March 2014") // .withSubmittedOnDate("01 March 2014") // - .build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } private Integer applyForLoanApplicationWithProductConfigurationAsFalse(final Integer clientID, final Integer loanProductID, String principal) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + List collaterals = new ArrayList<>(); + + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal(principal) @@ -5319,7 +5565,7 @@ public class ClientLoanIntegrationTest { .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withExpectedDisbursementDate("01 March 2014") // .withSubmittedOnDate("01 March 2014") // - .build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java index b56918913..e3acbaa26 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java @@ -88,7 +88,8 @@ public class ClientSavingsIntegrationTest { this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; final String minRequiredBalance = null; final String enforceMinRequiredBalance = "false"; @@ -131,7 +132,8 @@ public class ClientSavingsIntegrationTest { this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = "5000"; final String minRequiredBalance = null; final String enforceMinRequiredBalance = "false"; @@ -178,7 +180,8 @@ public class ClientSavingsIntegrationTest { final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; final String minRequiredBalance = "1000.0"; final String enforceMinRequiredBalance = "true"; @@ -221,7 +224,8 @@ public class ClientSavingsIntegrationTest { final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; final String minRequiredBalance = "1500.0"; final String openningBalance = "1600"; @@ -288,7 +292,8 @@ public class ClientSavingsIntegrationTest { new ResponseSpecBuilder().build()); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; final String minRequiredBalance = null; final String enforceMinRequiredBalance = "false"; @@ -331,7 +336,8 @@ public class ClientSavingsIntegrationTest { new ResponseSpecBuilder().build()); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; final String minRequiredBalance = null; final String enforceMinRequiredBalance = "false"; @@ -376,7 +382,8 @@ public class ClientSavingsIntegrationTest { this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; final String minRequiredBalance = null; final String enforceMinRequiredBalance = "false"; @@ -404,7 +411,8 @@ public class ClientSavingsIntegrationTest { new ResponseSpecBuilder().build()); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; final String minRequiredBalance = null; final String enforceMinRequiredBalance = "false"; @@ -505,7 +513,8 @@ public class ClientSavingsIntegrationTest { final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, erroResponseSpec); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; final String minRequiredBalance = null; final String enforceMinRequiredBalance = "false"; @@ -670,7 +679,8 @@ public class ClientSavingsIntegrationTest { * Create a client to apply for savings account (overdraft account). */ final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; /*** @@ -802,7 +812,8 @@ public class ClientSavingsIntegrationTest { * Create a client to apply for savings account (overdraft account). */ final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; /*** @@ -1053,7 +1064,8 @@ public class ClientSavingsIntegrationTest { * Create a client to apply for savings account (overdraft account). */ final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; /*** @@ -1315,7 +1327,8 @@ public class ClientSavingsIntegrationTest { * Create a client to apply for savings account (overdraft account). */ final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; /*** @@ -1483,7 +1496,8 @@ public class ClientSavingsIntegrationTest { * Create a client to apply for savings account (overdraft account). */ final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; /*** @@ -1635,7 +1649,8 @@ public class ClientSavingsIntegrationTest { this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; final String minRequiredBalance = null; final String enforceMinRequiredBalance = "false"; @@ -1684,7 +1699,8 @@ public class ClientSavingsIntegrationTest { this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; final String minRequiredBalance = null; final String enforceMinRequiredBalance = "false"; @@ -1735,6 +1751,7 @@ public class ClientSavingsIntegrationTest { this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; final String minRequiredBalance = null; @@ -1935,7 +1952,8 @@ public class ClientSavingsIntegrationTest { new ResponseSpecBuilder().build()); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; final String minRequiredBalance = null; final String enforceMinRequiredBalance = "false"; @@ -2055,7 +2073,9 @@ public class ClientSavingsIntegrationTest { // ResponseSpecBuilder().build()); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); final String minBalanceForInterestCalculation = null; final String minRequiredBalance = "500"; final String enforceMinRequiredBalance = "false"; diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientTest.java index 6c3133ba4..94751141b 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientTest.java @@ -30,7 +30,6 @@ import java.util.List; import java.util.Random; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.Utils; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -53,7 +52,8 @@ public class ClientTest { public void testClientStatus() { final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientId); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientId); + // Assertions.assertNotNull(clientId); HashMap status = ClientHelper.getClientStatus(requestSpec, responseSpec, String.valueOf(clientId)); ClientStatusChecker.verifyClientIsActive(status); @@ -85,7 +85,8 @@ public class ClientTest { public void testClientAsPersonStatus() { final Integer clientId = ClientHelper.createClientAsPerson(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientId); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientId); + // Assertions.assertNotNull(clientId); HashMap status = ClientHelper.getClientStatus(requestSpec, responseSpec, String.valueOf(clientId)); ClientStatusChecker.verifyClientIsActive(status); @@ -117,7 +118,8 @@ public class ClientTest { public void testClientAsEntityStatus() { final Integer clientId = ClientHelper.createClientAsEntity(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientId); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientId); + // Assertions.assertNotNull(clientId); HashMap status = ClientHelper.getClientStatus(requestSpec, responseSpec, String.valueOf(clientId)); ClientStatusChecker.verifyClientIsActive(status); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientUndoRejectAndWithdrawalIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientUndoRejectAndWithdrawalIntegrationTest.java index a8a875d91..ed795a376 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientUndoRejectAndWithdrawalIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientUndoRejectAndWithdrawalIntegrationTest.java @@ -66,7 +66,8 @@ public class ClientUndoRejectAndWithdrawalIntegrationTest { // CREATE CLIENT this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec); final Integer clientId = ClientHelper.createClientPending(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientId); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientId); + // Assertions.assertNotNull(clientId); // GET CLIENT STATUS HashMap status = ClientHelper.getClientStatus(requestSpec, responseSpec, String.valueOf(clientId)); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/CollateralProductIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/CollateralProductIntegrationTest.java new file mode 100644 index 000000000..b8a7715ad --- /dev/null +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/CollateralProductIntegrationTest.java @@ -0,0 +1,67 @@ +/** + * 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.integrationtests; + +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.builder.ResponseSpecBuilder; +import io.restassured.http.ContentType; +import io.restassured.specification.RequestSpecification; +import io.restassured.specification.ResponseSpecification; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; +import org.apache.fineract.integrationtests.common.Utils; +import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CollateralProductIntegrationTest { + + private static final Logger LOG = LoggerFactory.getLogger(CollateralProductIntegrationTest.class); + private ResponseSpecification responseSpec; + private RequestSpecification requestSpec; + private LoanTransactionHelper loanTransactionHelper; + + @BeforeEach + public void setup() { + Utils.initializeRESTAssured(); + this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); + this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); + this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); + this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); + } + + @Test + public void createCollateralProductTest() { + LOG.info("-------------------------Creating Collateral Product---------------------------"); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + } + + @Test + public void updateCollateralProductTest() { + LOG.info("-------------------------Updating Collateral Product---------------------------"); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer resourceId = CollateralManagementHelper.updateCollateralProduct(this.requestSpec, this.responseSpec, collateralId); + + Assertions.assertEquals(collateralId, resourceId); + } +} diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ConcurrencyIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ConcurrencyIntegrationTest.java index 131d3add6..966ec9f13 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ConcurrencyIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ConcurrencyIntegrationTest.java @@ -23,18 +23,24 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Calendar; +import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.accounting.Account; import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -115,6 +121,13 @@ public class ConcurrencyIntegrationTest { private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, String principal) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal(principal) // .withLoanTermFrequency("4") // @@ -128,10 +141,21 @@ public class ConcurrencyIntegrationTest { .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withExpectedDisbursementDate("20 September 2011") // .withSubmittedOnDate("20 September 2011") // - .build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + public static class LoanRepaymentExecutor implements Runnable { private final Integer loanId; diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/GroupLoanIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/GroupLoanIntegrationTest.java index b078ffdd1..1d11515a9 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/GroupLoanIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/GroupLoanIntegrationTest.java @@ -25,12 +25,14 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.CommonConstants; import org.apache.fineract.integrationtests.common.GroupHelper; import org.apache.fineract.integrationtests.common.Utils; @@ -225,6 +227,16 @@ public class GroupLoanIntegrationTest { private HashMap applyForGlimApplication(final Integer clientID, final Integer groupID, final Integer loanProductID) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String GlimApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal("12,000.00") // .withLoanTermFrequency("4") // @@ -238,11 +250,22 @@ public class GroupLoanIntegrationTest { .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withExpectedDisbursementDate("20 September 2011") // .withSubmittedOnDate("20 September 2011").withLoanType("glim").withtotalLoan("10000").withParentAccount("1") - .build(clientID.toString(), groupID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).build(clientID.toString(), groupID.toString(), loanProductID.toString(), null); LOG.info(GlimApplicationJSON); return this.loanTransactionHelper.getGlimId(GlimApplicationJSON); } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal amount) { + collaterals.add(collaterals(collateralId, amount)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal amount) { + HashMap collateral = new HashMap(1); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("amount", amount.toString()); + return collateral; + } + private void verifyLoanRepaymentSchedule(final ArrayList loanSchedule) { LOG.info("--------------------VERIFYING THE PRINCIPAL DUES,INTEREST DUE AND DUE DATE--------------------------"); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/GroupSavingsIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/GroupSavingsIntegrationTest.java index e9b2b0367..cd7b0e1a3 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/GroupSavingsIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/GroupSavingsIntegrationTest.java @@ -82,6 +82,7 @@ public class GroupSavingsIntegrationTest { this.savingsAccountHelper = new SavingsAccountHelper(requestSpec, responseSpec); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); Assertions.assertNotNull(clientID); Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); @@ -285,6 +286,7 @@ public class GroupSavingsIntegrationTest { this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); Assertions.assertNotNull(clientID); Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); @@ -341,7 +343,8 @@ public class GroupSavingsIntegrationTest { final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); Assertions.assertNotNull(groupID); @@ -389,7 +392,8 @@ public class GroupSavingsIntegrationTest { final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build(); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); Assertions.assertNotNull(groupID); @@ -422,7 +426,8 @@ public class GroupSavingsIntegrationTest { final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build(); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); Assertions.assertNotNull(groupID); @@ -455,7 +460,8 @@ public class GroupSavingsIntegrationTest { new ResponseSpecBuilder().build()); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); Assertions.assertNotNull(groupID); @@ -506,7 +512,8 @@ public class GroupSavingsIntegrationTest { this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); Assertions.assertNotNull(groupID); @@ -540,7 +547,8 @@ public class GroupSavingsIntegrationTest { new ResponseSpecBuilder().build()); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); Assertions.assertNotNull(groupID); @@ -644,7 +652,8 @@ public class GroupSavingsIntegrationTest { this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(clientID); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + // Assertions.assertNotNull(clientID); Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); Assertions.assertNotNull(groupID); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/GroupTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/GroupTest.java index 7d7392ab1..594ceaf68 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/GroupTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/GroupTest.java @@ -26,8 +26,12 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.GroupHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; @@ -61,7 +65,6 @@ public class GroupTest { this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - } @Test @@ -104,6 +107,8 @@ public class GroupTest { // create client and add client to group final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + groupID = GroupHelper.associateClient(this.requestSpec, this.responseSpec, groupID.toString(), clientID.toString()); GroupHelper.verifyGroupMembers(this.requestSpec, this.responseSpec, groupID, clientID); @@ -158,6 +163,14 @@ public class GroupTest { private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, String principal) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal(principal) // .withLoanTermFrequency("4") // @@ -171,8 +184,19 @@ public class GroupTest { .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withExpectedDisbursementDate("20 September 2014") // .withSubmittedOnDate("20 September 2014") // - .build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationApprovalTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationApprovalTest.java index 1ddd1199c..c50d89cfb 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationApprovalTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationApprovalTest.java @@ -25,16 +25,19 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.CommonConstants; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker; import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -243,16 +246,43 @@ public class LoanApplicationApprovalTest { } private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, final String proposedAmount) { + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String loanApplication = new LoanApplicationTestBuilder().withPrincipal(proposedAmount).withLoanTermFrequency("5") .withLoanTermFrequencyAsMonths().withNumberOfRepayments("5").withRepaymentEveryAfter("1") .withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("2").withExpectedDisbursementDate("04 April 2012") - .withSubmittedOnDate("02 April 2012").build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).withSubmittedOnDate("02 April 2012") + .build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplication); } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + public Integer applyForLoanApplicationWithTranches(final Integer clientID, final Integer loanProductID, String principal, List tranches) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal(principal) @@ -267,7 +297,7 @@ public class LoanApplicationApprovalTest { .withTranches(tranches) // .withInterestTypeAsDecliningBalance() // .withSubmittedOnDate("01 March 2014") // - .build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationUndoLastTrancheTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationUndoLastTrancheTest.java index 017ac44d3..2172b6170 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationUndoLastTrancheTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationUndoLastTrancheTest.java @@ -23,10 +23,12 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; @@ -128,9 +130,27 @@ public class LoanApplicationUndoLastTrancheTest { } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + public Integer applyForLoanApplicationWithTranches(final Integer clientID, final Integer loanProductID, String principal, List tranches) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal(principal) @@ -145,7 +165,7 @@ public class LoanApplicationUndoLastTrancheTest { .withTranches(tranches) // .withInterestTypeAsDecliningBalance() // .withSubmittedOnDate("01 March 2014") // - .build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDisbursalDateValidationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDisbursalDateValidationTest.java index 322844808..2c14185a7 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDisbursalDateValidationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDisbursalDateValidationTest.java @@ -23,9 +23,12 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.CommonConstants; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; @@ -100,11 +103,30 @@ public class LoanDisbursalDateValidationTest { } private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, final String proposedAmount) { + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); final String loanApplication = new LoanApplicationTestBuilder().withPrincipal(proposedAmount).withLoanTermFrequency("5") .withLoanTermFrequencyAsMonths().withNumberOfRepayments("5").withRepaymentEveryAfter("1") .withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("2").withExpectedDisbursementDate("01 March 2014") - .withSubmittedOnDate("26 February 2014").build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).withSubmittedOnDate("26 February 2014") + .build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplication); } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDisbursementDetailsIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDisbursementDetailsIntegrationTest.java index 0e83209ae..036c70b1b 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDisbursementDetailsIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDisbursementDetailsIntegrationTest.java @@ -25,18 +25,21 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanDisbursementTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker; import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -309,6 +312,14 @@ public class LoanDisbursementDetailsIntegrationTest { List tranches, final String installmentAmount) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal(proposedAmount) @@ -325,7 +336,7 @@ public class LoanDisbursementDetailsIntegrationTest { .withInterestTypeAsDecliningBalance() // .withSubmittedOnDate("01 June 2015") // .withAmortizationTypeAsEqualInstallments() // - .build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); @@ -434,6 +445,13 @@ public class LoanDisbursementDetailsIntegrationTest { private Integer applyForLoanApplicationWithTranches(final Integer clientID, final Integer loanProductID, String principal, List tranches) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal(principal) @@ -448,9 +466,20 @@ public class LoanDisbursementDetailsIntegrationTest { .withTranches(tranches) // .withInterestTypeAsDecliningBalance() // .withSubmittedOnDate("01 March 2014") // - .build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentRescheduleAtDisbursementTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentRescheduleAtDisbursementTest.java index 8d3a887b1..1e4efa84b 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentRescheduleAtDisbursementTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentRescheduleAtDisbursementTest.java @@ -25,6 +25,7 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -32,12 +33,14 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.accounting.Account; import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker; import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -95,9 +98,17 @@ public class LoanRepaymentRescheduleAtDisbursementTest { approveTranches.add(this.loanApplicationApprovalTest.createTrancheDetail("01 March 2015", "5000")); approveTranches.add(this.loanApplicationApprovalTest.createTrancheDetail("01 May 2015", "5000")); + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + // APPLY FOR TRANCHE LOAN WITH INTEREST RECALCULATION final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, disbursementDate, - LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, new ArrayList(0), createTranches); + LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, new ArrayList(0), createTranches, collaterals); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); @@ -134,6 +145,17 @@ public class LoanRepaymentRescheduleAtDisbursementTest { } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + private void verifyLoanRepaymentSchedule(final HashMap firstInstallement, final Map expectedvalues) { assertEquals(expectedvalues.get("dueDate"), firstInstallement.get("dueDate")); @@ -195,16 +217,18 @@ public class LoanRepaymentRescheduleAtDisbursementTest { } private Integer applyForLoanApplicationForInterestRecalculation(final Integer clientID, final Integer loanProductID, - final String disbursementDate, final String repaymentStrategy, final List charges, List tranches) { + final String disbursementDate, final String repaymentStrategy, final List charges, List tranches, + final List collaterals) { final String graceOnInterestPayment = null; final String graceOnPrincipalPayment = null; + return applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, disbursementDate, repaymentStrategy, charges, - graceOnInterestPayment, graceOnPrincipalPayment, tranches); + graceOnInterestPayment, graceOnPrincipalPayment, tranches, collaterals); } private Integer applyForLoanApplicationForInterestRecalculation(final Integer clientID, final Integer loanProductID, final String disbursementDate, final String repaymentStrategy, final List charges, final String graceOnInterestPayment, - final String graceOnPrincipalPayment, List tranches) { + final String graceOnPrincipalPayment, List tranches, List collaterals) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal("10000.00") // @@ -222,7 +246,7 @@ public class LoanRepaymentRescheduleAtDisbursementTest { .withExpectedDisbursementDate(disbursementDate) // .withSubmittedOnDate(disbursementDate) // .withwithRepaymentStrategy(repaymentStrategy) // - .withCharges(charges)// + .withCollaterals(collaterals).withCharges(charges)// .build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleOnDecliningBalanceLoanTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleOnDecliningBalanceLoanTest.java index c7b6d6e67..7ed3e0028 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleOnDecliningBalanceLoanTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleOnDecliningBalanceLoanTest.java @@ -26,10 +26,13 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper; import org.apache.fineract.integrationtests.common.LoanRescheduleRequestHelper; import org.apache.fineract.integrationtests.common.Utils; @@ -38,6 +41,7 @@ import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanRescheduleRequestTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -160,12 +164,21 @@ public class LoanRescheduleOnDecliningBalanceLoanTest { private void createLoanEntity() { LOG.info("---------------------------------NEW LOAN APPLICATION------------------------------------------"); + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + this.clientId.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(loanPrincipalAmount) .withLoanTermFrequency(numberOfRepayments).withLoanTermFrequencyAsMonths().withNumberOfRepayments(numberOfRepayments) .withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments() .withInterestCalculationPeriodTypeAsDays().withInterestRatePerPeriod(interestRatePerPeriod) .withInterestTypeAsDecliningBalance().withSubmittedOnDate(dateString).withExpectedDisbursementDate(dateString) - .withPrincipalGrace("2").withInterestGrace("2").build(this.clientId.toString(), this.loanProductId.toString(), null); + .withCollaterals(collaterals).withPrincipalGrace("2").withInterestGrace("2") + .build(this.clientId.toString(), this.loanProductId.toString(), null); this.loanId = this.loanTransactionHelper.getLoanId(loanApplicationJSON); @@ -175,6 +188,17 @@ public class LoanRescheduleOnDecliningBalanceLoanTest { this.disburseLoan(); } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + /** * approve the loan application **/ diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleRequestTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleRequestTest.java index 988654ad9..13f265cbd 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleRequestTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleRequestTest.java @@ -26,14 +26,19 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.LoanRescheduleRequestHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanRescheduleRequestTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -112,13 +117,19 @@ public class LoanRescheduleRequestTest { **/ private void createLoanEntity() { LOG.info("---------------------------------NEW LOAN APPLICATION------------------------------------------"); - + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + this.clientId.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(loanPrincipalAmount) .withLoanTermFrequency(numberOfRepayments).withLoanTermFrequencyAsMonths().withNumberOfRepayments(numberOfRepayments) .withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments() .withInterestCalculationPeriodTypeAsDays().withInterestRatePerPeriod(interestRatePerPeriod).withLoanTermFrequencyAsMonths() .withSubmittedOnDate(dateString).withExpectedDisbursementDate(dateString).withPrincipalGrace("2").withInterestGrace("2") - .build(this.clientId.toString(), this.loanProductId.toString(), null); + .withCollaterals(collaterals).build(this.clientId.toString(), this.loanProductId.toString(), null); this.loanId = this.loanTransactionHelper.getLoanId(loanApplicationJSON); @@ -128,6 +139,17 @@ public class LoanRescheduleRequestTest { this.disburseLoan(); } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + /** * approve the loan application **/ diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java index 9d2a2f036..9f78e91e3 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanReschedulingWithinCenterTest.java @@ -26,6 +26,7 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.sql.Timestamp; import java.text.DateFormat; import java.text.SimpleDateFormat; @@ -38,6 +39,7 @@ import org.apache.fineract.integrationtests.common.CalendarHelper; import org.apache.fineract.integrationtests.common.CenterDomain; import org.apache.fineract.integrationtests.common.CenterHelper; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper; import org.apache.fineract.integrationtests.common.GroupHelper; import org.apache.fineract.integrationtests.common.OfficeHelper; @@ -109,6 +111,15 @@ public class LoanReschedulingWithinCenterTest { final String recalculationRestFrequencyDate = "01 January 2012"; final boolean isMultiTrancheLoan = false; + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientId), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + // CREATE LOAN MULTIDISBURSAL PRODUCT WITH INTEREST RECALCULATION final Integer loanProductID = createLoanProductWithInterestRecalculation(LoanProductTestBuilder.RBI_INDIA_STRATEGY, LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE, @@ -118,7 +129,8 @@ public class LoanReschedulingWithinCenterTest { // APPLY FOR TRANCHE LOAN WITH INTEREST RECALCULATION final Integer loanId = applyForLoanApplicationForInterestRecalculation(clientId, groupId, calendarId, loanProductID, disbursalDate, - recalculationRestFrequencyDate, LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, new ArrayList(0), null); + recalculationRestFrequencyDate, LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, new ArrayList(0), null, + collaterals); // Test for loan account is created Assertions.assertNotNull(loanId); @@ -153,6 +165,17 @@ public class LoanReschedulingWithinCenterTest { assertEquals("90.82", String.valueOf(interestDue)); } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal amount) { + collaterals.add(collaterals(collateralId, amount)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal amount) { + HashMap collateral = new HashMap(1); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("amount", amount.toString()); + return collateral; + } + private void associateClientsToGroup(Integer groupId, Integer clientId) { // Associate client to the group GroupHelper.associateClient(this.requestSpec, this.responseSpec, groupId.toString(), clientId.toString()); @@ -244,10 +267,19 @@ public class LoanReschedulingWithinCenterTest { approveTranches.add(this.loanApplicationApprovalTest.createTrancheDetail(disbursementDate, "5000")); approveTranches.add(this.loanApplicationApprovalTest.createTrancheDetail(secondDisbursement, "5000")); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientId), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + // APPLY FOR TRANCHE LOAN WITH INTEREST RECALCULATION final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientId, groupId, calendarId, loanProductID, disbursementDate, recalculationRestFrequencyDate, LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, new ArrayList(0), - createTranches); + createTranches, collaterals); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); // VALIDATE THE LOAN STATUS @@ -340,19 +372,20 @@ public class LoanReschedulingWithinCenterTest { @SuppressWarnings("rawtypes") private Integer applyForLoanApplicationForInterestRecalculation(final Integer clientID, Integer groupId, Integer calendarId, final Integer loanProductID, final String disbursementDate, final String restStartDate, final String repaymentStrategy, - final List charges, List tranches) { + final List charges, List tranches, List collaterals) { final String graceOnInterestPayment = null; final String compoundingStartDate = null; final String graceOnPrincipalPayment = null; return applyForLoanApplicationForInterestRecalculation(clientID, groupId, calendarId, loanProductID, disbursementDate, - restStartDate, compoundingStartDate, repaymentStrategy, charges, graceOnInterestPayment, graceOnPrincipalPayment, tranches); + restStartDate, compoundingStartDate, repaymentStrategy, charges, graceOnInterestPayment, graceOnPrincipalPayment, tranches, + collaterals); } @SuppressWarnings({ "rawtypes", "unused" }) private Integer applyForLoanApplicationForInterestRecalculation(final Integer clientID, Integer groupId, Integer calendarId, final Integer loanProductID, final String disbursementDate, final String restStartDate, final String compoundingStartDate, final String repaymentStrategy, final List charges, final String graceOnInterestPayment, - final String graceOnPrincipalPayment, List tranches) { + final String graceOnPrincipalPayment, List tranches, List collaterals) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal("10000.00") // @@ -370,7 +403,7 @@ public class LoanReschedulingWithinCenterTest { .withExpectedDisbursementDate(disbursementDate) // .withSubmittedOnDate(disbursementDate) // .withwithRepaymentStrategy(repaymentStrategy) // - .withCharges(charges)// + .withCollaterals(collaterals).withCharges(charges)// .build(clientID.toString(), groupId.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWithWaiveInterestAndWriteOffIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWithWaiveInterestAndWriteOffIntegrationTest.java index 0fcbc5c7d..6ee827592 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWithWaiveInterestAndWriteOffIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWithWaiveInterestAndWriteOffIntegrationTest.java @@ -23,8 +23,12 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; @@ -205,13 +209,31 @@ public class LoanWithWaiveInterestAndWriteOffIntegrationTest { private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(PRINCIPAL) .withLoanTermFrequency(LOAN_TERM_FREQUENCY).withLoanTermFrequencyAsMonths().withNumberOfRepayments(NUMBER_OF_REPAYMENTS) .withRepaymentEveryAfter(REPAYMENT_PERIOD).withRepaymentFrequencyTypeAsMonths() .withInterestRatePerPeriod(RATE_OF_INTEREST_PER_PERIOD).withInterestTypeAsFlatBalance() .withAmortizationTypeAsEqualInstallments().withInterestCalculationPeriodTypeSameAsRepaymentPeriod() .withExpectedDisbursementDate(EXPECTED_DISBURSAL_DATE).withSubmittedOnDate(LOAN_APPLICATION_SUBMISSION_DATE) - .build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } + + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWithdrawnByApplicantIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWithdrawnByApplicantIntegrationTest.java index d3493846b..2038259ba 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWithdrawnByApplicantIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWithdrawnByApplicantIntegrationTest.java @@ -23,13 +23,18 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker; import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -65,11 +70,30 @@ public class LoanWithdrawnByApplicantIntegrationTest { } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID) { + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); final String loanApplication = new LoanApplicationTestBuilder().withPrincipal("5000").withLoanTermFrequency("5") .withLoanTermFrequencyAsMonths().withNumberOfRepayments("5").withRepaymentEveryAfter("1") .withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("2").withExpectedDisbursementDate("04 April 2012") - .withSubmittedOnDate("02 April 2012").build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).withSubmittedOnDate("02 April 2012") + .build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplication); } } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/MinimumDaysBetweenDisbursalAndFirstRepaymentTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/MinimumDaysBetweenDisbursalAndFirstRepaymentTest.java index 944fea261..7325d907d 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/MinimumDaysBetweenDisbursalAndFirstRepaymentTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/MinimumDaysBetweenDisbursalAndFirstRepaymentTest.java @@ -25,10 +25,13 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.fineract.integrationtests.common.CalendarHelper; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.CommonConstants; import org.apache.fineract.integrationtests.common.GroupHelper; import org.apache.fineract.integrationtests.common.Utils; @@ -83,12 +86,20 @@ public class MinimumDaysBetweenDisbursalAndFirstRepaymentTest { final String disbursalDate = "04 September 2014"; final String firstRepaymentDate = "11 September 2014"; + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + this.clientId.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(loanPrincipalAmount) .withLoanTermFrequency(numberOfRepayments).withLoanTermFrequencyAsWeeks().withNumberOfRepayments(numberOfRepayments) .withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments() .withInterestCalculationPeriodTypeAsDays().withInterestRatePerPeriod(interestRatePerPeriod) .withRepaymentFrequencyTypeAsWeeks().withSubmittedOnDate(disbursalDate).withExpectedDisbursementDate(disbursalDate) - .withPrincipalGrace("2").withInterestGrace("2").withFirstRepaymentDate(firstRepaymentDate) + .withPrincipalGrace("2").withInterestGrace("2").withFirstRepaymentDate(firstRepaymentDate).withCollaterals(collaterals) .build(this.clientId.toString(), this.loanProductId.toString(), null); this.loanId = this.loanTransactionHelper.getLoanId(loanApplicationJSON); @@ -110,6 +121,17 @@ public class MinimumDaysBetweenDisbursalAndFirstRepaymentTest { } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + /* * MinimumDaysBetweenDisbursalAndFirstRepayment is set to 7 days and days between disbursal date and first repayment * is set as 7. system should allow to create this loan and allow to disburse @@ -133,12 +155,20 @@ public class MinimumDaysBetweenDisbursalAndFirstRepaymentTest { final String disbursalDate = "04 September 2014"; final String firstRepaymentDate = "05 September 2014"; + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + this.clientId.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(loanPrincipalAmount) .withLoanTermFrequency(numberOfRepayments).withLoanTermFrequencyAsWeeks().withNumberOfRepayments(numberOfRepayments) .withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments() .withInterestCalculationPeriodTypeAsDays().withInterestRatePerPeriod(interestRatePerPeriod) .withRepaymentFrequencyTypeAsWeeks().withSubmittedOnDate(disbursalDate).withExpectedDisbursementDate(disbursalDate) - .withPrincipalGrace("2").withInterestGrace("2").withFirstRepaymentDate(firstRepaymentDate) + .withPrincipalGrace("2").withInterestGrace("2").withFirstRepaymentDate(firstRepaymentDate).withCollaterals(collaterals) .build(this.clientId.toString(), this.loanProductId.toString(), null); List error = (List) this.loanTransactionHelper.createLoanAccount(loanApplicationJSON, diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/NotesTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/NotesTest.java index bb4366948..38f9318c3 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/NotesTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/NotesTest.java @@ -23,8 +23,12 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.GroupHelper; import org.apache.fineract.integrationtests.common.NotesHelper; import org.apache.fineract.integrationtests.common.Utils; @@ -186,13 +190,33 @@ public class NotesTest { } private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID) { + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String loanApplication = new LoanApplicationTestBuilder().withPrincipal("5000").withLoanTermFrequency("5") .withLoanTermFrequencyAsMonths().withNumberOfRepayments("5").withRepaymentEveryAfter("1") .withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("2").withExpectedDisbursementDate("04 April 2012") - .withSubmittedOnDate("02 April 2012").build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).withSubmittedOnDate("02 April 2012") + .build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplication); } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + @Test public void testUpdateLoanNote() { String noteText = "this is a test loan note"; diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java index 8f59477d4..83a7bcc52 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java @@ -26,6 +26,7 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.text.DateFormat; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; @@ -39,6 +40,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper; import org.apache.fineract.integrationtests.common.HolidayHelper; import org.apache.fineract.integrationtests.common.SchedulerJobHelper; @@ -896,9 +898,29 @@ public class SchedulerJobsTestResults { return this.loanTransactionHelper.getLoanProductId(loanProductJSON); } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + private Integer applyForLoanApplication(final String clientID, final String loanProductID, final String savingsID) { // system.out.println("--------------------------------APPLYING FOR LOAN // APPLICATION--------------------------------"); + + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal("15,000.00") // .withLoanTermFrequency("4") // @@ -912,7 +934,7 @@ public class SchedulerJobsTestResults { .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withExpectedDisbursementDate("10 January 2013") // .withSubmittedOnDate("10 January 2013") // - .build(clientID, loanProductID, savingsID); + .withCollaterals(collaterals).build(clientID, loanProductID, savingsID); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SkipRepaymentOnMonthFirstTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SkipRepaymentOnMonthFirstTest.java index 90c0b6f6c..63306821e 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SkipRepaymentOnMonthFirstTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SkipRepaymentOnMonthFirstTest.java @@ -25,11 +25,14 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import org.apache.fineract.integrationtests.common.CalendarHelper; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper; import org.apache.fineract.integrationtests.common.GroupHelper; import org.apache.fineract.integrationtests.common.Utils; @@ -129,6 +132,14 @@ public class SkipRepaymentOnMonthFirstTest { private Integer applyForLoanApplication(final Integer groupID, final Integer loanProductID, Integer calendarID, Integer clientID) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal("12,000.00") // .withLoanTermFrequency("4") // @@ -143,11 +154,23 @@ public class SkipRepaymentOnMonthFirstTest { .withExpectedDisbursementDate("01 October 2011") // .withCalendarID(calendarID.toString()) // .withSubmittedOnDate("01 October 2011") // - .withLoanType("jlg").build(clientID.toString(), groupID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).withLoanType("jlg") + .build(clientID.toString(), groupID.toString(), loanProductID.toString(), null); LOG.info(loanApplicationJSON); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + private void verifyLoanRepaymentSchedule(final ArrayList loanSchedule) { LOG.info("--------------------VERIFYING THE REPAYMENT DATE--------------------------"); assertEquals(new ArrayList<>(Arrays.asList(2011, 10, 15)), loanSchedule.get(1).get("dueDate"), diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java index c1897bd4d..1692f901b 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/bulkimport/importhandler/loan/LoanImportHandlerTest.java @@ -32,13 +32,16 @@ import java.io.IOException; import java.io.OutputStream; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import org.apache.fineract.infrastructure.bulkimport.constants.LoanConstants; import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.GroupHelper; import org.apache.fineract.integrationtests.common.OfficeDomain; import org.apache.fineract.integrationtests.common.OfficeHelper; @@ -106,6 +109,17 @@ public class LoanImportHandlerTest { new Gson().toJson(clientMap), "clientId"); Assertions.assertNotNull(outcome_client_creation, "Could not create client"); + List collaterals = new ArrayList<>(); + HashMap collateralHashMap = new HashMap<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(outcome_client_creation), collateralId); + Assertions.assertNotNull(clientCollateralId); + collateralHashMap.put("clientCollateralId", collateralId.toString()); + collateralHashMap.put("quantity", "1"); + collaterals.add(collateralHashMap); + // in order to populate helper sheets Integer outcome_group_creation = GroupHelper.createGroup(requestSpec, responseSpec, true); Assertions.assertNotNull(outcome_group_creation, "Could not create group"); @@ -184,6 +198,8 @@ public class LoanImportHandlerTest { firstLoanRow.createCell(LoanConstants.TOTAL_AMOUNT_REPAID_COL).setCellValue(6000); firstLoanRow.createCell(LoanConstants.LAST_REPAYMENT_DATE_COL).setCellValue(date); firstLoanRow.createCell(LoanConstants.REPAYMENT_TYPE_COL).setCellValue(paymentTypeName); + firstLoanRow.createCell(LoanConstants.LOAN_COLLATERAL_ID).setCellValue(collaterals.get(0).get("clientCollateralId").toString()); + firstLoanRow.createCell(LoanConstants.LOAN_COLLATERAL_QUANTITY).setCellValue(collaterals.get(0).get("quantity").toString()); String currentdirectory = new File("").getAbsolutePath(); File directory = new File(currentdirectory + File.separator + "src" + File.separator + "integrationTest" + File.separator diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/BatchHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/BatchHelper.java index 2ca3807db..4961656a4 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/BatchHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/BatchHelper.java @@ -62,7 +62,7 @@ public final class BatchHelper { /** * Returns a Map from Json String * - * @param jsonBody + * @param * @return Map */ public static Map generateMapFromJsonString(final String jsonString) { @@ -112,7 +112,7 @@ public final class BatchHelper { /** * Returns a BatchResponse based on the given BatchRequest, by posting the request to the server. * - * @param BatchRequest + * @param * @return {@code List} */ public static List postWithSingleRequest(final RequestSpecification requestSpec, @@ -136,7 +136,7 @@ public final class BatchHelper { * Creates and returns a {@link org.apache.fineract.batch.command.internal.CreateClientCommandStrategy} Request as * one of the request in Batch. * - * @param reqId + * @param * @param externalId * @return BatchRequest */ @@ -166,7 +166,7 @@ public final class BatchHelper { * Creates and returns a {@link org.apache.fineract.batch.command.internal.CreateClientCommandStrategy} Request as * one of the request in Batch. * - * @param reqId + * @param * @param externalId * @return BatchRequest */ @@ -197,8 +197,8 @@ public final class BatchHelper { * Creates and returns a {@link org.apache.fineract.batch.command.internal.UpdateClientCommandStrategy} Request with * given requestId and reference. * - * @param reqId - * @param clientId + * @param + * @param * @return BatchRequest */ public static BatchRequest updateClientRequest(final Long requestId, final Long reference) { @@ -223,7 +223,8 @@ public final class BatchHelper { * @param productId * @return BatchRequest */ - public static BatchRequest applyLoanRequest(final Long requestId, final Long reference, final Integer productId) { + public static BatchRequest applyLoanRequest(final Long requestId, final Long reference, final Integer productId, + final Integer clientCollateralId) { final BatchRequest br = new BatchRequest(); @@ -238,6 +239,7 @@ public final class BatchHelper { + "\"repaymentEvery\": 1, \"repaymentFrequencyType\": 2, \"interestRatePerPeriod\": 10," + "\"amortizationType\": 1, \"interestType\": 0, \"interestCalculationPeriodType\": 1," + "\"transactionProcessingStrategyId\": 1, \"expectedDisbursementDate\": \"10 Jun 2013\"," + + "\"collateral\": [{\"clientCollateralId\": \"" + clientCollateralId.toString() + "\", \"quantity\": \"1\"}]," + "\"submittedOnDate\": \"10 Jun 2013\"}"; br.setBody(body); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/CollateralManagementHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/CollateralManagementHelper.java new file mode 100644 index 000000000..7486e6655 --- /dev/null +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/CollateralManagementHelper.java @@ -0,0 +1,159 @@ +/** + * 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.integrationtests.common; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import io.restassured.specification.RequestSpecification; +import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; +import java.util.HashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CollateralManagementHelper { + + private static final Logger LOG = LoggerFactory.getLogger(CollateralManagementHelper.class); + private final RequestSpecification requestSpec; + private final ResponseSpecification responseSpec; + + public CollateralManagementHelper(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) { + this.requestSpec = requestSpec; + this.responseSpec = responseSpec; + } + + public static Integer createClientCollateral(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final String clientId, final Integer collateralId) { + LOG.info("---------------------------------CREATING A CLIENT_COLLATERAL---------------------------------------------"); + final String CLIENT_COLLATERAL_URL = "/fineract-provider/api/v1/clients/" + clientId + "/collaterals" + "?" + + Utils.TENANT_IDENTIFIER; + return Utils.performServerPost(requestSpec, responseSpec, CLIENT_COLLATERAL_URL, + clientCollateralAsJson(collateralId, BigDecimal.valueOf(100)), "resourceId"); + } + + public static Object getClientCollateralData(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final Integer collateralId, final String clientId) { + final String CLIENT_COLLATERAL_URL = "/fineract-provider/api/v1/clients" + clientId + "/collaterals/" + collateralId + "?" + + Utils.TENANT_IDENTIFIER; + return Utils.performServerGet(requestSpec, responseSpec, CLIENT_COLLATERAL_URL, "quantity"); + } + + public static String clientCollateralAsJson(final Integer collateralId, final BigDecimal quantity) { + final HashMap map = new HashMap<>(); + map.put("collateralId", collateralId.toString()); + map.put("quantity", quantity.toString()); + map.put("locale", "en"); + LOG.info("map : {}", map); + return new Gson().toJson(map); + } + + public static Integer createCollateralProduct(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) { + LOG.info("---------------------------------CREATING A COLLATERAL_PRODUCT---------------------------------------------"); + final String COLLATERAL_PRODUCT_URL = "/fineract-provider/api/v1/collateral-management" + "?" + Utils.TENANT_IDENTIFIER; + return Utils.performServerPost(requestSpec, responseSpec, COLLATERAL_PRODUCT_URL, + collateralProductAsJson(Utils.randomNameGenerator("COLLATERAL_PRODUCT", 5), "USD", "acre", "agriculture", + BigDecimal.valueOf(40), BigDecimal.valueOf(100000000), "en"), + "resourceId"); + } + + public static String collateralProductAsJson(final String name, final String currency, final String unitType, final String quality, + final BigDecimal pctToBase, final BigDecimal baseAmount, final String locale) { + final HashMap map = new HashMap<>(); + map.put("name", name); + map.put("currency", currency); + map.put("unitType", unitType); + map.put("quality", quality); + map.put("pctToBase", pctToBase.toString()); + map.put("basePrice", baseAmount.toString()); + map.put("locale", locale); + LOG.info("map : {}", map); + return new Gson().toJson(map); + } + + public static Integer updateCollateralProduct(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final Integer collateralId) { + LOG.info("---------------------------------UPDATING A COLLATERAL_PRODUCT---------------------------------------------"); + final String COLLATERAL_PRODUCT_URL = "/fineract-provider/api/v1/collateral-management/" + collateralId + "?" + + Utils.TENANT_IDENTIFIER; + return Utils.performServerPut(requestSpec, responseSpec, COLLATERAL_PRODUCT_URL, + updateCollateralProductAsJson(Utils.randomNameGenerator("COLLATERAL_PRODUCT", 5), "USD", "acre", "agriculture", + BigDecimal.valueOf(30), BigDecimal.valueOf(100000), "en"), + "resourceId"); + } + + public static String updateCollateralProductAsString(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final Integer collateralId) { + + Object updateCollateralObject = updateCollateralProduct(requestSpec, responseSpec, collateralId); + // Convert the Object to String and fetch updated value + Gson gson = new Gson(); + String result = gson.toJson(updateCollateralObject); + JsonObject reportObject = JsonParser.parseString(result).getAsJsonObject(); + String value = reportObject.get("pctToBase").getAsString(); + + return value; + } + + public static String updateCollateralProductAsJson(final String name, final String currency, final String unitType, + final String quality, final BigDecimal pctToBase, final BigDecimal baseAmount, final String locale) { + final HashMap map = new HashMap<>(); + map.put("name", name); + map.put("currency", currency); + map.put("unitType", unitType); + map.put("quality", quality); + map.put("pctToBase", pctToBase.toString()); + map.put("basePrice", baseAmount.toString()); + map.put("locale", locale); + return new Gson().toJson(map); + } + + public static HashMap updateClientCollateral(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final Integer collateralId) { + final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec); + ClientHelper.verifyClientCreatedOnServer(requestSpec, responseSpec, clientID); + LOG.info("---------------------------------UPDATING A CLIENT COLLATERAL---------------------------------------------"); + final String CLIENT_COLLATERAL_URL = "/fineract-provider/api/v1/clients/" + clientID + "/collaterals/" + collateralId + "?" + + Utils.TENANT_IDENTIFIER; + return Utils.performServerPut(requestSpec, responseSpec, CLIENT_COLLATERAL_URL, updateClientCollateralAsJson(BigDecimal.valueOf(1)), + "changes"); + } + + public static String updateClientCollateralAsString(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final Integer collateralId) { + + Object clientCollateralObject = updateClientCollateral(requestSpec, responseSpec, collateralId); + // Convert the Object to String and fetch updated value + Gson gson = new Gson(); + String result = gson.toJson(clientCollateralObject); + JsonObject reportObject = JsonParser.parseString(result).getAsJsonObject(); + String value = reportObject.get("quantity").getAsString(); + + return value; + } + + public static String updateClientCollateralAsJson(final BigDecimal quantity) { + final HashMap map = new HashMap<>(); + map.put("quantity", quantity.toString()); + map.put("locale", "en"); + LOG.info("map : {}", map); + return new Gson().toJson(map); + } + +} diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ProvisioningIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ProvisioningIntegrationTest.java index 4925d181b..69468d6f8 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ProvisioningIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ProvisioningIntegrationTest.java @@ -24,6 +24,7 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -77,11 +78,19 @@ public class ProvisioningIntegrationTest { ArrayList loanProducts = new ArrayList<>(LOANPRODUCTS_SIZE); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + for (int i = 0; i < LOANPRODUCTS_SIZE; i++) { final Integer loanProductID = createLoanProduct(false, NONE); loanProducts.add(loanProductID); Assertions.assertNotNull(loanProductID); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, null, "1,00,000.00"); + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, null, "1,00,000.00", collaterals); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); loanStatusHashMap = this.loanTransactionHelper.approveLoan("20 September 2011", loanID); @@ -138,6 +147,17 @@ public class ProvisioningIntegrationTest { Assertions.assertTrue(((ArrayList) provisioningEntry.get("pageItems")).size() > 0); } + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + private void validateProvisioningCriteria(Map requestCriteria, Map newCriteria) { // criteria name validation @@ -206,7 +226,7 @@ public class ProvisioningIntegrationTest { } private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, List charges, - final String savingsId, String principal) { + final String savingsId, String principal, List collaterals) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal(principal) // @@ -221,7 +241,7 @@ public class ProvisioningIntegrationTest { .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withExpectedDisbursementDate("20 September 2011") // .withSubmittedOnDate("20 September 2011") // - .withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); + .withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/SchedulerJobHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/SchedulerJobHelper.java index b10082c58..d29d3226a 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/SchedulerJobHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/SchedulerJobHelper.java @@ -147,8 +147,8 @@ public class SchedulerJobHelper { * @author Michael Vorburger.ch */ public void executeAndAwaitJob(String jobName) { - final Duration timeout = Duration.ofSeconds(30); - final Duration pause = Duration.ofMillis(500); + final Duration timeout = Duration.ofSeconds(180); + final Duration pause = Duration.ofSeconds(1); DateTimeFormatter df = DateTimeFormatter.ISO_INSTANT; // FINERACT-926 Instant beforeExecuteTime = now().truncatedTo(ChronoUnit.SECONDS); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java index 3eb5d120c..7a22d88c1 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java @@ -67,6 +67,7 @@ public class LoanApplicationTestBuilder { private List disbursementData = null; @SuppressWarnings("rawtypes") private List charges = new ArrayList<>(); + private List collaterals = new ArrayList<>(); private String repaymentsStartingFromDate = null; private String isParentAccount = null; private String totalLoan = "0"; @@ -146,12 +147,15 @@ public class LoanApplicationTestBuilder { map.put("expectedDisbursementDate", this.expectedDisbursmentDate); map.put("submittedOnDate", this.submittedOnDate); map.put("loanType", this.loanType); + map.put("collateral", this.collaterals); + if (repaymentsStartingFromDate != null) { map.put("repaymentsStartingFromDate", this.repaymentsStartingFromDate); } if (charges != null) { map.put("charges", charges); } + if (savingsID != null) { map.put("linkAccountId", savingsID); } @@ -288,6 +292,11 @@ public class LoanApplicationTestBuilder { return this; } + public LoanApplicationTestBuilder withCollaterals(final List collaterals) { + this.collaterals = collaterals; + return this; + } + public LoanApplicationTestBuilder withLoanType(final String loanType) { this.loanType = loanType; return this; diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/organisation/EntityDatatableChecksIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/organisation/EntityDatatableChecksIntegrationTest.java index 98d369d4c..ce9cac217 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/organisation/EntityDatatableChecksIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/organisation/EntityDatatableChecksIntegrationTest.java @@ -26,10 +26,12 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.CommonConstants; import org.apache.fineract.integrationtests.common.GroupHelper; import org.apache.fineract.integrationtests.common.Utils; @@ -448,6 +450,14 @@ public class EntityDatatableChecksIntegrationTest { private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, String graceOnPrincipalPayment, final String registeredTableName) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal("10000000.00") // .withLoanTermFrequency("24") // @@ -462,13 +472,20 @@ public class EntityDatatableChecksIntegrationTest { .withPrincipalGrace(graceOnPrincipalPayment).withExpectedDisbursementDate("02 June 2014") // .withSubmittedOnDate("02 June 2014") // .withDatatables(getTestDatatableAsJson(registeredTableName)) // - .build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } private Object applyForLoanApplicationWithError(final Integer clientID, final Integer loanProductID, String graceOnPrincipalPayment, final String responseAttribute) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal("10000000.00") // .withLoanTermFrequency("24") // @@ -482,10 +499,21 @@ public class EntityDatatableChecksIntegrationTest { .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withPrincipalGrace(graceOnPrincipalPayment).withExpectedDisbursementDate("02 June 2014") // .withSubmittedOnDate("02 June 2014") // - .build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); return this.validationErrorHelper.getLoanError(loanApplicationJSON, responseAttribute); } + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(1); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal amount) { + collaterals.add(collaterals(collateralId, amount)); + } + public static List> getTestDatatableAsJson(final String registeredTableName) { List> datatablesListMap = new ArrayList<>(); HashMap datatableMap = new HashMap<>(); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/guarantor/GuarantorTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/guarantor/GuarantorTest.java index 5d6a99572..ad88a4a26 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/guarantor/GuarantorTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/guarantor/GuarantorTest.java @@ -27,6 +27,7 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -35,6 +36,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.CommonConstants; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; @@ -678,8 +680,28 @@ public class GuarantorTest { return this.loanTransactionHelper.getLoanProductId(loanProductJSON); } + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(1); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, final String disbursementDate) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal("10000.00") // .withLoanTermFrequency("4") // @@ -693,7 +715,7 @@ public class GuarantorTest { .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withExpectedDisbursementDate(disbursementDate) // .withSubmittedOnDate(disbursementDate) // - .build(clientID.toString(), loanProductID.toString(), null); + .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsDecliningBalanceHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsDecliningBalanceHelper.java index 362e795dc..ba813b69f 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsDecliningBalanceHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsDecliningBalanceHelper.java @@ -94,7 +94,7 @@ public class VariableInstallmentsDecliningBalanceHelper { } public static String applyForLoanApplication(final Integer clientID, final Integer loanProductID, List charges, - final String savingsId, String principal) { + final String savingsId, String principal, List collaterals) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal(principal) // @@ -109,12 +109,12 @@ public class VariableInstallmentsDecliningBalanceHelper { .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withExpectedDisbursementDate("20 September 2011") // .withSubmittedOnDate("20 September 2011") // - .withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); + .withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); return loanApplicationJSON; } public static String applyForLoanApplicationWithEqualPrincipal(final Integer clientID, final Integer loanProductID, - List charges, final String savingsId, String principal) { + List charges, final String savingsId, String principal, List collaterals) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal(principal) // @@ -129,7 +129,7 @@ public class VariableInstallmentsDecliningBalanceHelper { .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withExpectedDisbursementDate("20 September 2011") // .withSubmittedOnDate("20 September 2011") // - .withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); + .withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); return loanApplicationJSON; } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsFlatHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsFlatHelper.java index 49655c7c3..3d9b3b65a 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsFlatHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsFlatHelper.java @@ -56,7 +56,7 @@ public class VariableInstallmentsFlatHelper { } public static String applyForLoanApplication(final Integer clientID, final Integer loanProductID, List charges, - final String savingsId, String principal) { + final String savingsId, String principal, List collaterals) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal(principal) // @@ -71,7 +71,7 @@ public class VariableInstallmentsFlatHelper { .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // .withExpectedDisbursementDate("20 September 2011") // .withSubmittedOnDate("20 September 2011") // - .withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); + .withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId); return loanApplicationJSON; } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsIntegrationTest.java index 8c7b5bdef..4396565cd 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/variableinstallments/VariableInstallmentsIntegrationTest.java @@ -23,10 +23,13 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CollateralManagementHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker; import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; @@ -81,8 +84,17 @@ public class VariableInstallmentsIntegrationTest { Integer loanProductID = this.loanTransactionHelper.getLoanProductId(loanProductJson); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + + List collaterals = new ArrayList<>(); + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String json = VariableInstallmentsDecliningBalanceHelper.applyForLoanApplication(clientID, loanProductID, null, null, - "1,00,000.00"); + "1,00,000.00", collaterals); final Integer loanID = this.loanTransactionHelper.getLoanId(json); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -109,6 +121,17 @@ public class VariableInstallmentsIntegrationTest { } + private HashMap collaterals(Integer collateralId, BigDecimal quantity) { + HashMap collateral = new HashMap(2); + collateral.put("clientCollateralId", collateralId.toString()); + collateral.put("quantity", quantity.toString()); + return collateral; + } + + private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { + collaterals.add(collaterals(collateralId, quantity)); + } + private void assertAfterSubmit(ArrayList serverData, ArrayList expectedData) { Assertions.assertTrue(serverData.size() == expectedData.size()); for (int i = 0; i < serverData.size(); i++) { @@ -131,8 +154,17 @@ public class VariableInstallmentsIntegrationTest { Integer loanProductID = this.loanTransactionHelper.getLoanProductId(loanProductJson); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String json = VariableInstallmentsDecliningBalanceHelper.applyForLoanApplication(clientID, loanProductID, null, null, - "1,00,000.00"); + "1,00,000.00", collaterals); final Integer loanID = this.loanTransactionHelper.getLoanId(json); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -166,8 +198,17 @@ public class VariableInstallmentsIntegrationTest { Integer loanProductID = this.loanTransactionHelper.getLoanProductId(loanProductJson); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String json = VariableInstallmentsDecliningBalanceHelper.applyForLoanApplication(clientID, loanProductID, null, null, - "1,00,000.00"); + "1,00,000.00", collaterals); final Integer loanID = this.loanTransactionHelper.getLoanId(json); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -207,8 +248,16 @@ public class VariableInstallmentsIntegrationTest { Integer loanProductID = this.loanTransactionHelper.getLoanProductId(loanProductJson); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); final String json = VariableInstallmentsDecliningBalanceHelper.applyForLoanApplication(clientID, loanProductID, null, null, - "1,00,000.00"); + "1,00,000.00", collaterals); final Integer loanID = this.loanTransactionHelper.getLoanId(json); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -249,8 +298,16 @@ public class VariableInstallmentsIntegrationTest { Integer loanProductID = this.loanTransactionHelper.getLoanProductId(loanProductJson); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + clientID.toString(), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); final String json = VariableInstallmentsDecliningBalanceHelper.applyForLoanApplicationWithEqualPrincipal(clientID, loanProductID, - null, null, "1,00,000.00"); + null, null, "1,00,000.00", collaterals); final Integer loanID = this.loanTransactionHelper.getLoanId(json); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -290,8 +347,16 @@ public class VariableInstallmentsIntegrationTest { Integer loanProductID = this.loanTransactionHelper.getLoanProductId(loanProductJson); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); final String json = VariableInstallmentsDecliningBalanceHelper.applyForLoanApplication(clientID, loanProductID, null, null, - "1,00,000.00"); + "1,00,000.00", collaterals); final Integer loanID = this.loanTransactionHelper.getLoanId(json); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -329,7 +394,16 @@ public class VariableInstallmentsIntegrationTest { Integer loanProductID = this.loanTransactionHelper.getLoanProductId(loanProductJson); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); - final String json = VariableInstallmentsFlatHelper.applyForLoanApplication(clientID, loanProductID, null, null, "1,00,000.00"); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String json = VariableInstallmentsFlatHelper.applyForLoanApplication(clientID, loanProductID, null, null, "1,00,000.00", + collaterals); final Integer loanID = this.loanTransactionHelper.getLoanId(json); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -365,7 +439,16 @@ public class VariableInstallmentsIntegrationTest { Integer loanProductID = this.loanTransactionHelper.getLoanProductId(loanProductJson); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); - final String json = VariableInstallmentsFlatHelper.applyForLoanApplication(clientID, loanProductID, null, null, "1,00,000.00"); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String json = VariableInstallmentsFlatHelper.applyForLoanApplication(clientID, loanProductID, null, null, "1,00,000.00", + collaterals); final Integer loanID = this.loanTransactionHelper.getLoanId(json); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -399,7 +482,15 @@ public class VariableInstallmentsIntegrationTest { Integer loanProductID = this.loanTransactionHelper.getLoanProductId(loanProductJson); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); - final String json = VariableInstallmentsFlatHelper.applyForLoanApplication(clientID, loanProductID, null, null, "1,00,000.00"); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String json = VariableInstallmentsFlatHelper.applyForLoanApplication(clientID, loanProductID, null, null, "1,00,000.00", + collaterals); final Integer loanID = this.loanTransactionHelper.getLoanId(json); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -438,7 +529,16 @@ public class VariableInstallmentsIntegrationTest { Integer loanProductID = this.loanTransactionHelper.getLoanProductId(loanProductJson); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); - final String json = VariableInstallmentsFlatHelper.applyForLoanApplication(clientID, loanProductID, null, null, "1,00,000.00"); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String json = VariableInstallmentsFlatHelper.applyForLoanApplication(clientID, loanProductID, null, null, "1,00,000.00", + collaterals); final Integer loanID = this.loanTransactionHelper.getLoanId(json); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); @@ -478,7 +578,16 @@ public class VariableInstallmentsIntegrationTest { Integer loanProductID = this.loanTransactionHelper.getLoanProductId(loanProductJson); final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); - final String json = VariableInstallmentsFlatHelper.applyForLoanApplication(clientID, loanProductID, null, null, "1,00,000.00"); + List collaterals = new ArrayList<>(); + + final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + Assertions.assertNotNull(collateralId); + final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, + String.valueOf(clientID), collateralId); + Assertions.assertNotNull(clientCollateralId); + addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); + final String json = VariableInstallmentsFlatHelper.applyForLoanApplication(clientID, loanProductID, null, null, "1,00,000.00", + collaterals); final Integer loanID = this.loanTransactionHelper.getLoanId(json); HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);