From 2e88f6cdc29f0ef263f8aa64471eaf987936b531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Soma=20S=C3=B6r=C3=B6s?= Date: Thu, 3 Sep 2026 14:43:02 +0200 Subject: [PATCH] FINERACT-2455: WC - Transaction - Prepay Loan --- .../WorkingCapitalLoanAccountStepDef.java | 15 +++-- .../WorkingCapitalLoanRepayment.feature | 40 ++++++++++++++ ...ingCapitalLoanTransactionsApiResource.java | 55 +++++++++++++++++++ ...talLoanTransactionsApiResourceSwagger.java | 19 +++++++ ...ingCapitalLoanTransactionTemplateData.java | 50 +++++++++++++++++ ...talLoanApplicationReadPlatformService.java | 4 ++ ...oanApplicationReadPlatformServiceImpl.java | 15 +++++ 7 files changed, 190 insertions(+), 8 deletions(-) create mode 100644 fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/data/WorkingCapitalLoanTransactionTemplateData.java diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalLoanAccountStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalLoanAccountStepDef.java index b16a0a01902..27a2a10e4bc 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalLoanAccountStepDef.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalLoanAccountStepDef.java @@ -91,6 +91,7 @@ import org.apache.fineract.client.models.PutWorkingCapitalLoansLoanIdResponse; import org.apache.fineract.client.models.WorkingCapitalLoanCommandTemplateData; import org.apache.fineract.client.models.WorkingCapitalLoanPeriodPaymentRateChangeData; +import org.apache.fineract.client.models.WorkingCapitalLoanTransactionTemplateResponse; import org.apache.fineract.test.api.FineractClientConfiguration; import org.apache.fineract.test.data.FundId; import org.apache.fineract.test.data.LoanStatus; @@ -3338,16 +3339,14 @@ public void makeWorkingCapitalLoanRepaymentWithPaymentDetails(final String trans @Then("Admin closes the Working Capital loan with a full repayment on {string}") public void closeWorkingCapitalLoanWithFullRepayment(final String transactionDate) { final Long loanId = getCreatedLoanId(); - final GetWorkingCapitalLoansLoanIdResponse loanDetails = ok( - () -> fineractClient.workingCapitalLoans().retrieveWorkingCapitalLoanById(loanId)); - Assertions.assertNotNull(loanDetails.getBalance()); - Assertions.assertNotNull(loanDetails.getBalance().getTotalOutstanding()); - final BigDecimal totalOutstanding = loanDetails.getBalance().getTotalOutstanding(); + WorkingCapitalLoanTransactionTemplateResponse templateResponse = ok(() -> fineractClient.workingCapitalLoanTransactions() + .getWorkingCapitalLoanTransactionTemplateById(loanId, "prepayLoan", DATE_FORMAT, transactionDate, "en")); + Assertions.assertNotNull(templateResponse); + final BigDecimal transactionAmount = templateResponse.getTransactionAmount(); final PostWorkingCapitalLoanTransactionsRequest repaymentRequest = workingCapitalProductRequestFactory - .defaultWorkingCapitalLoanRepaymentRequest().transactionDate(transactionDate).transactionAmount(totalOutstanding); + .defaultWorkingCapitalLoanRepaymentRequest().transactionDate(transactionDate).transactionAmount(transactionAmount); final PostWorkingCapitalLoanTransactionsResponse response = executeRepaymentLikeById(loanId, "repayment", repaymentRequest); - Assertions.assertNotNull(loanDetails.getBalance()); - validateRepaymentResponse(response, totalOutstanding.doubleValue(), transactionDate, loanId); + validateRepaymentResponse(response, transactionAmount.doubleValue(), transactionDate, loanId); } @Then("Admin closes the Working Capital loan with all obligations met with a full repayment on {string}") diff --git a/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalLoanRepayment.feature b/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalLoanRepayment.feature index 34559d000b6..9e87bf59156 100644 --- a/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalLoanRepayment.feature +++ b/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalLoanRepayment.feature @@ -213,6 +213,7 @@ Feature: Working Capital Loan Repayment | 182 | 02 July 2026 | 50.00 | | 80.00 | | 0.00 | | 0.00 | | 183 | 03 July 2026 | 50.00 | | 30.00 | | 0.00 | | 0.00 | | 184 | 04 July 2026 | 30.00 | | 0.00 | | 0.00 | | 0.00 | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "10 January 2026" @TestRailId:C76618 Scenario: Verify working capital loan repayment - UC2: simple repayment by loan external ID: pay less than expected @@ -430,6 +431,7 @@ Feature: Working Capital Loan Repayment | 187 | 07 July 2026 | 50.00 | | 70.00 | | 0.00 | | 0.00 | | 188 | 08 July 2026 | 50.00 | | 20.00 | | 0.00 | | 0.00 | | 189 | 09 July 2026 | 20.00 | | 0.00 | | 0.00 | | 0.00 | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "10 January 2026" @TestRailId:C76619 Scenario: Verify working capital loan repayment - UC3: simple repayment with zero amount results an error (Negative) @@ -454,6 +456,7 @@ Feature: Working Capital Loan Repayment Then Initiating a repayment on "01 January 2026" with 0.0 transaction amount on Working Capital loan results an error with the following data: | httpCode | errorMessage | | 400 | The parameter `transactionAmount` must be greater than 0. | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "10 January 2026" @TestRailId:C76620 Scenario: Verify working capital loan repayment - UC4: simple repayment with negative amount results an error (Negative) @@ -478,6 +481,7 @@ Feature: Working Capital Loan Repayment Then Initiating a repayment on "01 January 2026" with -100.0 transaction amount on Working Capital loan results an error with the following data: | httpCode | errorMessage | | 400 | The parameter `transactionAmount` must be greater than 0. | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "10 January 2026" @TestRailId:C76621 Scenario: Verify working capital loan repayment - UC5: simple repayment with future date results an error (Negative) @@ -502,6 +506,7 @@ Feature: Working Capital Loan Repayment Then Initiating a repayment on "15 January 2026" with 270.0 transaction amount on Working Capital loan results an error with the following data: | httpCode | errorMessage | | 400 | Failed data validation due to: cannot.be.a.future.date. | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "10 January 2026" @TestRailId:C76622 Scenario: Verify working capital loan repayment - UC6: full expectedAmount repaid on disbursement day @@ -711,6 +716,7 @@ Feature: Working Capital Loan Repayment | 178 | 27 June 2026 | 50.00 | | 100.00 | | 0.00 | | 0.00 | | 179 | 28 June 2026 | 50.00 | | 50.00 | | 0.00 | | 0.00 | | 180 | 29 June 2026 | 50.00 | | 0.00 | | 0.00 | | 0.00 | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "01 January 2026" @TestRailId:C85164 Scenario: Verify working capital loan repayment - less then expectedAmount repaid on disbursement day - UC6.1 @@ -935,6 +941,7 @@ Feature: Working Capital Loan Repayment | transactionDate | type | transactionAmount | principalPortion | feeChargesPortion | penaltyChargesPortion | reversed | | 01 January 2026 | Disbursement | 9000.0 | 9000.0 | 0.0 | 0.0 | false | | 01 January 2026 | Repayment | 30.0 | 30.0 | 0.0 | 0.0 | false | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "02 January 2026" @TestRailId:C85165 Scenario: Verify working capital loan repayment - more then expectedAmount repaid on disbursement day - UC6.2 @@ -1154,6 +1161,7 @@ Feature: Working Capital Loan Repayment | transactionDate | type | transactionAmount | principalPortion | feeChargesPortion | penaltyChargesPortion | reversed | | 01 January 2026 | Disbursement | 9000.0 | 9000.0 | 0.0 | 0.0 | false | | 01 January 2026 | Repayment | 280.0 | 280.0 | 0.0 | 0.0 | false | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "02 January 2026" @TestRailId:C85166 Scenario: Verify working capital loan repayment - amount matches to expectedAmount repaid on disbursement day - UC6.3 @@ -1374,6 +1382,8 @@ Feature: Working Capital Loan Repayment | 01 January 2026 | Disbursement | 9000.0 | 9000.0 | 0.0 | 0.0 | false | | 01 January 2026 | Repayment | 270.0 | 270.0 | 0.0 | 0.0 | false | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "02 January 2026" + @TestRailId:C85167 Scenario: Verify working capital loan repayment - amount that closes the loan is repaid on disbursement day - UC6.4 When Admin sets the business date to "01 January 2026" @@ -1735,6 +1745,8 @@ Feature: Working Capital Loan Repayment | 01 January 2026 | Repayment | 50.0 | 50.0 | 0.0 | 0.0 | false | | 01 January 2026 | Repayment | 30.0 | 30.0 | 0.0 | 0.0 | false | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "02 January 2026" + @TestRailId:C85171 Scenario: Verify working capital loan repayment - discount after repayment on disbursement day - UC6.8 When Admin sets the business date to "01 January 2026" @@ -2196,6 +2208,8 @@ Feature: Working Capital Loan Repayment | INCOME | 404000 | Interest Income | | 17.26 | | LIABILITY | 240005 | Deferred Interest Revenue | 17.26 | | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "03 January 2026" + @TestRailId:C76623 Scenario: Verify working capital loan repayment - UC7: full minimum payment after disbursement day When Admin sets the business date to "01 January 2026" @@ -2444,6 +2458,8 @@ Feature: Working Capital Loan Repayment | 203 | 23 July 2026 | 50.00 | | 30.00 | | 0.00 | | 0.00 | | 204 | 24 July 2026 | 30.00 | | 0.00 | | 0.00 | | 0.00 | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "31 January 2026" + @TestRailId:C76624 Scenario: Verify working capital loan repayment - UC8: full expectedAmount repaid on last day of 1st period When Admin sets the business date to "01 January 2026" @@ -2692,6 +2708,8 @@ Feature: Working Capital Loan Repayment | 203 | 23 July 2026 | 50.00 | | 30.00 | | 0.00 | | 0.00 | | 204 | 24 July 2026 | 30.00 | | 0.00 | | 0.00 | | 0.00 | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "31 January 2026" + @TestRailId:C76625 Scenario: Verify working capital loan repayment - UC9: full expectedAmount repaid on first day of 2nd period When Admin sets the business date to "01 January 2026" @@ -2946,6 +2964,8 @@ Feature: Working Capital Loan Repayment | 204 | 24 July 2026 | 50.00 | | 30.00 | | 0.00 | | 0.00 | | 205 | 25 July 2026 | 30.00 | | 0.00 | | 0.00 | | 0.00 | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "01 February 2026" + @TestRailId:C76626 Scenario: Verify working capital loan repayment - UC10: full expectedAmount repaid in 1st period with multiple payments on same day When Admin sets the business date to "01 January 2026" @@ -3195,6 +3215,8 @@ Feature: Working Capital Loan Repayment | 203 | 23 July 2026 | 50.00 | | 30.00 | | 0.00 | | 0.00 | | 204 | 24 July 2026 | 30.00 | | 0.00 | | 0.00 | | 0.00 | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "31 January 2026" + @TestRailId:C76627 Scenario: Verify working capital loan repayment - UC11: full expectedAmount repaid in 1st period with multiple payments on different days When Admin sets the business date to "01 January 2026" @@ -3450,6 +3472,8 @@ Feature: Working Capital Loan Repayment | 203 | 23 July 2026 | 50.00 | | 30.00 | | 0.00 | | 0.00 | | 204 | 24 July 2026 | 30.00 | | 0.00 | | 0.00 | | 0.00 | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "31 January 2026" + @TestRailId:C76628 Scenario: Verify working capital loan repayment - UC12: partial expectedAmount repaid in 1st period When Admin sets the business date to "01 January 2026" @@ -3492,6 +3516,8 @@ Feature: Working Capital Loan Repayment | periodNumber | addedOnDate | liftedOnDate | classification | minimumAgeDays | maximumAgeDays | | 1 | 2026-01-31 | | D00 | 1 | 30 | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "31 January 2026" + @TestRailId:C76629 Scenario: Verify working capital loan repayment - UC13: partial expectedAmount repaid in 2nd period When Admin sets the business date to "01 January 2026" @@ -3758,6 +3784,8 @@ Feature: Working Capital Loan Repayment | 216 | 05 August 2026 | 50.00 | | 30.00 | | 0.00 | | 0.00 | | 217 | 06 August 2026 | 30.00 | | 0.00 | | 0.00 | | 0.00 | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "10 February 2026" + @TestRailId:C76630 Scenario: Verify working capital loan repayment - UC14: expectedAmount overpaid in 1st period When Admin sets the business date to "01 January 2026" @@ -4006,6 +4034,8 @@ Feature: Working Capital Loan Repayment | 201 | 21 July 2026 | 50.00 | | 30.00 | | 0.00 | | 0.00 | | 202 | 22 July 2026 | 30.00 | | 0.00 | | 0.00 | | 0.00 | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "31 January 2026" + @TestRailId:C76631 Scenario: Verify working capital loan repayment - UC15: expectedAmount overpaid in 2nd period When Admin sets the business date to "01 January 2026" @@ -4268,6 +4298,8 @@ Feature: Working Capital Loan Repayment | 212 | 01 August 2026 | 50.00 | | 30.00 | | 0.00 | | 0.00 | | 213 | 02 August 2026 | 30.00 | | 0.00 | | 0.00 | | 0.00 | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "10 February 2026" + @TestRailId:C76632 Scenario: Verify working capital loan repayment - UC16: expectedAmount overpaid in late period When Admin sets the business date to "01 January 2026" @@ -4620,6 +4652,8 @@ Feature: Working Capital Loan Repayment | 278 | 06 October 2026 | 50.00 | | 50.00 | | 0.00 | | 0.00 | | 279 | 07 October 2026 | 50.00 | | 0.00 | | 0.00 | | 0.00 | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "10 May 2026" + @TestRailId:C76633 Scenario: Verify working capital loan repayment - UC17: simple repayment with payment details When Admin sets the business date to "01 January 2026" @@ -4835,6 +4869,8 @@ Feature: Working Capital Loan Repayment | 183 | 03 July 2026 | 50.00 | | 30.00 | | 0.00 | | 0.00 | | 184 | 04 July 2026 | 30.00 | | 0.00 | | 0.00 | | 0.00 | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "10 January 2026" + @TestRailId:C76634 Scenario: Verify amortization schedule after repayment transaction - UC18 When Admin sets the business date to "01 January 2019" @@ -5257,6 +5293,8 @@ Feature: Working Capital Loan Repayment | 199 | 19 July 2019 | 50.00 | | 49.95 | | 0.11 | | 0.06 | | 200 | 20 July 2019 | 50.00 | | 0.00 | | 0.06 | | 0.00 | + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "04 January 2019" + @TestRailId:C83023 Scenario: Verify working capital loan repayment - UC19: actualBalance and actualDiscountFeeBalance progression across multiple on-time repayments When Admin sets the business date to "01 January 2019" @@ -5281,3 +5319,5 @@ Feature: Working Capital Loan Repayment | 4 | 05 January 2019 | 50.00 | | 8838.18 | | 9.48 | | 961.82 | | | 5 | 06 January 2019 | 50.00 | | 8797.62 | | 9.44 | | 952.38 | | | 200 | 20 July 2019 | 50.00 | | 0.00 | | 0.06 | | 0.00 | | + + Then Admin closes the Working Capital loan with all obligations met with a full repayment on "04 January 2019" diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanTransactionsApiResource.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanTransactionsApiResource.java index 858f395c759..9a282195dfc 100644 --- a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanTransactionsApiResource.java +++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanTransactionsApiResource.java @@ -41,20 +41,26 @@ import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.UriInfo; +import java.time.LocalDate; import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; 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.core.api.DateParam; import org.apache.fineract.infrastructure.core.api.jersey.Pagination; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.data.DateFormat; import org.apache.fineract.infrastructure.core.domain.ExternalId; import org.apache.fineract.infrastructure.core.exception.UnrecognizedQueryParamException; import org.apache.fineract.infrastructure.core.service.CommandParameterUtil; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.ExternalIdFactory; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.portfolio.workingcapitalloan.WorkingCapitalLoanConstants; import org.apache.fineract.portfolio.workingcapitalloan.data.WorkingCapitalLoanCommandTemplateData; import org.apache.fineract.portfolio.workingcapitalloan.data.WorkingCapitalLoanTransactionData; +import org.apache.fineract.portfolio.workingcapitalloan.data.WorkingCapitalLoanTransactionTemplateData; import org.apache.fineract.portfolio.workingcapitalloan.domain.WorkingCapitalLoanTransaction; import org.apache.fineract.portfolio.workingcapitalloan.exception.WorkingCapitalLoanNotFoundException; import org.apache.fineract.portfolio.workingcapitalloan.exception.WorkingCapitalLoanTransactionNotFoundException; @@ -287,6 +293,55 @@ public CommandProcessingResult executeWorkingCapitalLoanTransactionCommandByLoan return executeWorkingCapitalLoanTransactionCommand(loanId, null, null, transactionExternalId, command, apiRequestBodyAsJson); } + @GET + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(operationId = "getWorkingCapitalLoanTransactionTemplateById", summary = "Get Working Capital Loan transaction template by loan id", description = "Supported command query parameter: prepayLoan.") + @Path("{loanId}/transactions/template") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = WorkingCapitalLoanTransactionsApiResourceSwagger.WorkingCapitalLoanTransactionTemplateResponse.class))) }) + public WorkingCapitalLoanTransactionTemplateData getWorkingCapitalLoanTransactionTemplateById( + @PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId, + @QueryParam("command") @Parameter(description = "command") final String commandParam, + @QueryParam("dateFormat") @Parameter(description = "dateFormat") final String rawDateFormat, + @QueryParam("transactionDate") @Parameter(description = "transactionDate") final DateParam transactionDateParam, + @QueryParam("locale") @Parameter(description = "locale") final String locale) { + + return getWorkingCapitalLoanTransactionTemplate(commandParam, loanId, null, locale, rawDateFormat, transactionDateParam); + } + + @GET + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(operationId = "getWorkingCapitalLoanTransactionTemplateByExternalId", summary = "Get Working Capital Loan transaction template by loan external id", description = "Supported command query parameter: prepayLoan.") + @Path("external-id/{loanExternalId}/transactions/template") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = WorkingCapitalLoanTransactionsApiResourceSwagger.WorkingCapitalLoanTransactionTemplateResponse.class))) }) + public WorkingCapitalLoanTransactionTemplateData getWorkingCapitalLoanTransactionTemplateByExternalId( + @PathParam("loanExternalId") @Parameter(description = "loanExternalId", required = true) final String loanExternalId, + @QueryParam("command") @Parameter(description = "command") final String commandParam, + @QueryParam("dateFormat") @Parameter(description = "dateFormat") final String rawDateFormat, + @QueryParam("transactionDate") @Parameter(description = "transactionDate") final DateParam transactionDateParam, + @QueryParam("locale") @Parameter(description = "locale") final String locale) { + return getWorkingCapitalLoanTransactionTemplate(commandParam, null, loanExternalId, locale, rawDateFormat, transactionDateParam); + } + + private WorkingCapitalLoanTransactionTemplateData getWorkingCapitalLoanTransactionTemplate(String commandParam, Long loanId, + String externalId, String locale, String rawDateFormat, DateParam transactionDateParam) { + final Long resolvedLoanId = resolveLoanId(loanId, externalId); + this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS); + final DateFormat dateFormat = StringUtils.isBlank(rawDateFormat) ? null : new DateFormat(rawDateFormat); + if (CommandParameterUtil.is(commandParam, "prepayLoan")) { + LocalDate transactionDate; + if (transactionDateParam == null) { + transactionDate = DateUtils.getBusinessLocalDate(); + } else { + transactionDate = transactionDateParam.getDate("transactionDate", dateFormat, locale); + } + return this.loanReadPlatformService.retrieveLoanPrePaymentTemplate(resolvedLoanId, transactionDate); + } else { + throw new UnrecognizedQueryParamException("command", commandParam); + } + } + @POST @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanTransactionsApiResourceSwagger.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanTransactionsApiResourceSwagger.java index 6e28e174b60..05f0f4549a8 100644 --- a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanTransactionsApiResourceSwagger.java +++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanTransactionsApiResourceSwagger.java @@ -264,4 +264,23 @@ private ExecuteWorkingCapitalLoanTransactionCommandResponse() {} @Schema(example = "repayment-ext-001") public String resourceExternalId; } + + public static final class WorkingCapitalLoanTransactionTemplateResponse { + + @Schema(example = "1") + public Long id; + @Schema(description = "Transaction type") + public LoanTransactionEnumData type; + @Schema(example = "[2024, 2, 1]") + public LocalDate transactionDate; + @Schema(example = "10000.00") + public BigDecimal transactionAmount; + + @Schema(example = "10000.00", description = "Principal portion from allocation") + public BigDecimal principalPortion; + @Schema(example = "0.00", description = "Fee charges portion from allocation") + public BigDecimal feeChargesPortion; + @Schema(example = "0.00", description = "Penalty charges portion from allocation") + public BigDecimal penaltyChargesPortion; + } } diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/data/WorkingCapitalLoanTransactionTemplateData.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/data/WorkingCapitalLoanTransactionTemplateData.java new file mode 100644 index 00000000000..bf8785fff03 --- /dev/null +++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/data/WorkingCapitalLoanTransactionTemplateData.java @@ -0,0 +1,50 @@ +/** + * 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.workingcapitalloan.data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.apache.fineract.organisation.monetary.data.CurrencyData; +import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionEnumData; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WorkingCapitalLoanTransactionTemplateData implements Serializable { + + private Long wcLoanId; + private CurrencyData currency; + + private LocalDate transactionDate; + private BigDecimal transactionAmount; + private LoanTransactionEnumData type; + + private BigDecimal principalPortion; + private BigDecimal feeChargesPortion; + private BigDecimal penaltyChargesPortion; +} diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanApplicationReadPlatformService.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanApplicationReadPlatformService.java index 9e94c6461ca..7868a324a95 100644 --- a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanApplicationReadPlatformService.java +++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanApplicationReadPlatformService.java @@ -18,11 +18,13 @@ */ package org.apache.fineract.portfolio.workingcapitalloan.service; +import java.time.LocalDate; import java.util.List; import org.apache.fineract.infrastructure.core.domain.ExternalId; import org.apache.fineract.portfolio.accountdetails.data.WorkingCapitalLoanAccountSummaryData; import org.apache.fineract.portfolio.workingcapitalloan.data.WorkingCapitalLoanData; import org.apache.fineract.portfolio.workingcapitalloan.data.WorkingCapitalLoanTemplateData; +import org.apache.fineract.portfolio.workingcapitalloan.data.WorkingCapitalLoanTransactionTemplateData; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -58,4 +60,6 @@ public interface WorkingCapitalLoanApplicationReadPlatformService { * Checks if a Working Capital Loan exists with the given Id */ boolean existsByLoanId(Long loanId); + + WorkingCapitalLoanTransactionTemplateData retrieveLoanPrePaymentTemplate(Long loanId, LocalDate transactionDate); } diff --git a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanApplicationReadPlatformServiceImpl.java b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanApplicationReadPlatformServiceImpl.java index d9f82738721..d419213c9ea 100644 --- a/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanApplicationReadPlatformServiceImpl.java +++ b/fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/service/WorkingCapitalLoanApplicationReadPlatformServiceImpl.java @@ -21,6 +21,7 @@ import jakarta.persistence.criteria.Predicate; import java.math.BigDecimal; import java.math.MathContext; +import java.time.LocalDate; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -44,10 +45,13 @@ import org.apache.fineract.portfolio.delinquency.data.DelinquencyBucketData; import org.apache.fineract.portfolio.delinquency.domain.DelinquencyMinimumPaymentType; import org.apache.fineract.portfolio.delinquency.service.DelinquencyReadPlatformService; +import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType; import org.apache.fineract.portfolio.loanorigination.data.LoanOriginatorData; +import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations; import org.apache.fineract.portfolio.workingcapitalloan.data.WorkingCapitalLoanCollectionData; import org.apache.fineract.portfolio.workingcapitalloan.data.WorkingCapitalLoanData; import org.apache.fineract.portfolio.workingcapitalloan.data.WorkingCapitalLoanTemplateData; +import org.apache.fineract.portfolio.workingcapitalloan.data.WorkingCapitalLoanTransactionTemplateData; import org.apache.fineract.portfolio.workingcapitalloan.domain.WorkingCapitalLoan; import org.apache.fineract.portfolio.workingcapitalloan.domain.WorkingCapitalLoanPeriodFrequencyType; import org.apache.fineract.portfolio.workingcapitalloan.exception.WorkingCapitalLoanNotFoundException; @@ -274,4 +278,15 @@ public List retrieveLoanSummaryData(final public boolean existsByLoanId(Long loanId) { return this.repository.existsById(loanId); } + + @Override + public WorkingCapitalLoanTransactionTemplateData retrieveLoanPrePaymentTemplate(Long loanId, LocalDate transactionDate) { + WorkingCapitalLoan workingCapitalLoan = repository.getReferenceById(loanId); + return WorkingCapitalLoanTransactionTemplateData.builder().wcLoanId(loanId).currency(workingCapitalLoan.getCurrency().toData()) + .transactionDate(transactionDate).transactionAmount(workingCapitalLoan.getBalance().getTotalOutstanding()) + .type(LoanEnumerations.transactionType(LoanTransactionType.REPAYMENT)) + .principalPortion(workingCapitalLoan.getBalance().getPrincipalOutstanding()) + .feeChargesPortion(workingCapitalLoan.getBalance().getFeeOutstanding()) + .penaltyChargesPortion(workingCapitalLoan.getBalance().getPenaltyOutstanding()).build(); + } }