FINERACT-2326: Refractor redundant and some deprecated code as per new Java 21 style (Phase 2)

This commit is contained in:
Aman-Mittal
2025-12-17 08:51:47 +01:00
committed by Adam Saghy
parent 695816f990
commit 4bfae0400c
21 changed files with 196 additions and 206 deletions
@@ -20,8 +20,7 @@ package com.acme.fineract.event.starter;
import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
@AutoConfiguration @AutoConfiguration
@ComponentScans({ @ComponentScan("com.acme.fineract.event.externalevent") }) @ComponentScan("com.acme.fineract.event.externalevent")
public class AcmeEventAutoConfiguration {} public class AcmeEventAutoConfiguration {}
@@ -26,11 +26,9 @@ import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
@AutoConfiguration @AutoConfiguration
@ComponentScans({ @ComponentScan("com.acme.fineract.loan.cob"), @ComponentScan("com.acme.fineract.loan.processor"), @ComponentScan(basePackages = { "com.acme.fineract.loan.cob", "com.acme.fineract.loan.processor", "com.acme.fineract.loan.job" })
@ComponentScan("com.acme.fineract.loan.job") })
@ConditionalOnProperty("acme.loan.enabled") @ConditionalOnProperty("acme.loan.enabled")
public class AcmeLoanAutoConfiguration { public class AcmeLoanAutoConfiguration {
@@ -24,7 +24,6 @@ import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse; 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 io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST; import jakarta.ws.rs.POST;
@@ -52,9 +51,13 @@ public class AccrualAccountingApiResource {
@POST @POST
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Executes Periodic Accrual Accounting", method = "POST", description = "Mandatory Fields\n" + "\n" + "tillDate\n") @Operation(summary = "Executes Periodic Accrual Accounting", method = "POST", description = """
Mandatory Fields
tillDate
""")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = AccrualAccountingApiResourceSwagger.PostRunaccrualsRequest.class))) @RequestBody(required = true, content = @Content(schema = @Schema(implementation = AccrualAccountingApiResourceSwagger.PostRunaccrualsRequest.class)))
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK") }) @ApiResponse(responseCode = "200", description = "OK")
public CommandProcessingResult executePeriodicAccrualAccounting(@Parameter(hidden = true) AccrualAccountRequest accrualAccountRequest) { public CommandProcessingResult executePeriodicAccrualAccounting(@Parameter(hidden = true) AccrualAccountRequest accrualAccountRequest) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().excuteAccrualAccounting() final CommandWrapper commandRequest = new CommandWrapperBuilder().excuteAccrualAccounting()
.withJson(apiJsonSerializerService.serialize(accrualAccountRequest)).build(); .withJson(apiJsonSerializerService.serialize(accrualAccountRequest)).build();
@@ -24,7 +24,6 @@ import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse; 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 io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE; import jakarta.ws.rs.DELETE;
@@ -69,13 +68,15 @@ import org.springframework.stereotype.Component;
@Path("/v1/accountingrules") @Path("/v1/accountingrules")
@Component @Component
@Tag(name = "Accounting Rules", description = "It is typical scenario in MFI's that non accountants pass journal entries on a regular basis. For Ex: A branch office might deposit their entire cash at hand to their Bank account at the end of a working day. The branch office users might not understand enough of accounting to figure out which account needs to get credited and which account needs to be debited to represent this transaction.\n" @Tag(name = "Accounting Rules", description = """
+ "\n" It is typical scenario in MFI's that non accountants pass journal entries on a regular basis. For Ex: A branch office might deposit their entire cash at hand to their Bank account at the end of a working day. The branch office users might not understand enough of accounting to figure out which account needs to get credited and which account needs to be debited to represent this transaction.
+ "Enter accounting rules, an abstraction on top of manual Journal entires for enabling simpler data entry. An accounting rule can define any of the following abstractions\n"
+ "\n" + "A Simple journal entry where both the credit and debit account have been preselected\n" Enter accounting rules, an abstraction on top of manual Journal entires for enabling simpler data entry. An accounting rule can define any of the following abstractions
+ "A Simple journal entry where either credit or debit accounts have been limited to a pre-selected list of accounts (Ex: Debit account should be one of \"Bank of America\" of \"JP Morgan\" and credit account should be \"Cash\")\n"
+ "A Compound journal entry where multiple debits and / or multiple credits may be made amongst a set of preselected list of accounts (Ex: Credit account should be either \"Bank Of America\" or \"Cash\" and debit account can be \"Employee Salary\" and/or \"Miscellenous Expenses\")\n" A Simple journal entry where both the credit and debit account have been preselected
+ "An accounting rule can also be optionally associated with a branch, so that only a particular Branch's users have access to the rule") A Simple journal entry where either credit or debit accounts have been limited to a pre-selected list of accounts (Ex: Debit account should be one of "Bank of America" of "JP Morgan" and credit account should be "Cash")
A Compound journal entry where multiple debits and / or multiple credits may be made amongst a set of preselected list of accounts (Ex: Credit account should be either "Bank Of America" or "Cash" and debit account can be "Employee Salary" and/or "Miscellenous Expenses")
An accounting rule can also be optionally associated with a branch, so that only a particular Branch's users have access to the rule""")
@RequiredArgsConstructor @RequiredArgsConstructor
public class AccountingRuleApiResource { public class AccountingRuleApiResource {
@@ -94,8 +95,14 @@ public class AccountingRuleApiResource {
@Path("template") @Path("template")
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Retrieve Accounting Rule Details Template", description = "This is a convenience resource. It can be useful when building maintenance user interface screens for client applications. The template data returned consists of any or all of:\n" @Operation(summary = "Retrieve Accounting Rule Details Template", description = """
+ "\n" + "Field Defaults\n" + "Allowed Value Lists\n" + "Example Request:\n" + "\n" + "accountingrules/template") This is a convenience resource. It can be useful when building maintenance user interface screens for client applications. The template data returned consists of any or all of:
Field Defaults
Allowed Value Lists
Example Request:
accountingrules/template""")
public AccountingRuleData retrieveTemplate() { public AccountingRuleData retrieveTemplate() {
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION); context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
return handleTemplate(null); return handleTemplate(null);
@@ -104,8 +111,12 @@ public class AccountingRuleApiResource {
@GET @GET
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Retrieve Accounting Rules", description = "Returns the list of defined accounting rules.\n" + "\n" @Operation(summary = "Retrieve Accounting Rules", description = """
+ "Example Requests:\n" + "\n" + "accountingrules") Returns the list of defined accounting rules.
Example Requests:
accountingrules""")
public List<AccountingRuleData> retrieveAllAccountingRules(@Context final UriInfo uriInfo) { public List<AccountingRuleData> retrieveAllAccountingRules(@Context final UriInfo uriInfo) {
final AppUser currentUser = context.authenticatedUser(); final AppUser currentUser = context.authenticatedUser();
currentUser.validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION); currentUser.validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
@@ -122,8 +133,12 @@ public class AccountingRuleApiResource {
@Path("{accountingRuleId}") @Path("{accountingRuleId}")
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Retrieve a Accounting rule", description = "Returns the details of a defined Accounting rule.\n" + "\n" @Operation(summary = "Retrieve a Accounting rule", description = """
+ "Example Requests:\n" + "\n" + "accountingrules/1") Returns the details of a defined Accounting rule.
Example Requests:
accountingrules/1""")
public AccountingRuleData retreiveAccountingRule( public AccountingRuleData retreiveAccountingRule(
@PathParam("accountingRuleId") @Parameter(description = "accountingRuleId") final Long accountingRuleId, @PathParam("accountingRuleId") @Parameter(description = "accountingRuleId") final Long accountingRuleId,
@Context final UriInfo uriInfo) { @Context final UriInfo uriInfo) {
@@ -138,12 +153,18 @@ public class AccountingRuleApiResource {
@POST @POST
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Create/Define a Accounting rule", description = "Define a new Accounting rule.\n" + "\n" + "Mandatory Fields\n" @Operation(summary = "Create/Define a Accounting rule", description = """
+ "name, officeId,\n" + "accountToDebit OR debitTags,\n" + "accountToCredit OR creditTags.\n" + "\n" + "Optional Fields\n" Define a new Accounting rule.
+ "description")
Mandatory Fields
name, officeId,
accountToDebit OR debitTags,
accountToCredit OR creditTags.
Optional Fields
description""")
@RequestBody(content = @Content(schema = @Schema(implementation = AccountRuleRequest.class))) @RequestBody(content = @Content(schema = @Schema(implementation = AccountRuleRequest.class)))
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = AccountingRuleApiResourceSwagger.PostAccountingRulesResponse.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = AccountingRuleApiResourceSwagger.PostAccountingRulesResponse.class))) })
public CommandProcessingResult createAccountingRule(@Parameter(hidden = true) AccountRuleRequest accountRuleRequest) { public CommandProcessingResult createAccountingRule(@Parameter(hidden = true) AccountRuleRequest accountRuleRequest) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createAccountingRule() final CommandWrapper commandRequest = new CommandWrapperBuilder().createAccountingRule()
.withJson(apiJsonSerializerService.serialize(accountRuleRequest)).build(); .withJson(apiJsonSerializerService.serialize(accountRuleRequest)).build();
@@ -157,8 +178,7 @@ public class AccountingRuleApiResource {
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Update a Accounting Rule", description = "Updates the details of a Accounting rule.") @Operation(summary = "Update a Accounting Rule", description = "Updates the details of a Accounting rule.")
@RequestBody(content = @Content(schema = @Schema(implementation = AccountRuleRequest.class))) @RequestBody(content = @Content(schema = @Schema(implementation = AccountRuleRequest.class)))
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = AccountingRuleApiResourceSwagger.PutAccountingRulesResponse.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = AccountingRuleApiResourceSwagger.PutAccountingRulesResponse.class))) })
public CommandProcessingResult updateAccountingRule( public CommandProcessingResult updateAccountingRule(
@PathParam("accountingRuleId") @Parameter(description = "accountingRuleId") final Long accountingRuleId, @PathParam("accountingRuleId") @Parameter(description = "accountingRuleId") final Long accountingRuleId,
@Parameter(hidden = true) AccountRuleRequest accountRuleRequest) { @Parameter(hidden = true) AccountRuleRequest accountRuleRequest) {
@@ -173,8 +193,7 @@ public class AccountingRuleApiResource {
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Delete a Accounting Rule", description = "Deletes a Accounting rule.") @Operation(summary = "Delete a Accounting Rule", description = "Deletes a Accounting rule.")
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = AccountingRuleApiResourceSwagger.DeleteAccountingRulesResponse.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = AccountingRuleApiResourceSwagger.DeleteAccountingRulesResponse.class))) })
public CommandProcessingResult deleteAccountingRule( public CommandProcessingResult deleteAccountingRule(
@PathParam("accountingRuleId") @Parameter(description = "accountingRuleId") final Long accountingRuleId) { @PathParam("accountingRuleId") @Parameter(description = "accountingRuleId") final Long accountingRuleId) {
@@ -81,8 +81,7 @@ public final class AccountingConstants {
} }
public static CashAccountsForLoan fromInt(final int i) { public static CashAccountsForLoan fromInt(final int i) {
final CashAccountsForLoan type = intToEnumMap.get(Integer.valueOf(i)); return intToEnumMap.get(i);
return type;
} }
} }
@@ -142,8 +141,7 @@ public final class AccountingConstants {
} }
public static AccrualAccountsForLoan fromInt(final int i) { public static AccrualAccountsForLoan fromInt(final int i) {
final AccrualAccountsForLoan type = intToEnumMap.get(Integer.valueOf(i)); return intToEnumMap.get(i);
return type;
} }
} }
@@ -297,8 +295,7 @@ public final class AccountingConstants {
} }
public static CashAccountsForSavings fromInt(final int i) { public static CashAccountsForSavings fromInt(final int i) {
final CashAccountsForSavings type = intToEnumMap.get(Integer.valueOf(i)); return intToEnumMap.get(i);
return type;
} }
} }
@@ -346,8 +343,7 @@ public final class AccountingConstants {
} }
public static AccrualAccountsForSavings fromInt(final int i) { public static AccrualAccountsForSavings fromInt(final int i) {
final AccrualAccountsForSavings type = intToEnumMap.get(Integer.valueOf(i)); return intToEnumMap.get(i);
return type;
} }
} }
@@ -492,8 +488,7 @@ public final class AccountingConstants {
} }
public static FinancialActivity fromInt(final int financialActivityId) { public static FinancialActivity fromInt(final int financialActivityId) {
final FinancialActivity type = intToEnumMap.get(Integer.valueOf(financialActivityId)); return intToEnumMap.get(financialActivityId);
return type;
} }
public static FinancialActivityData toFinancialActivityData(final int financialActivityId) { public static FinancialActivityData toFinancialActivityData(final int financialActivityId) {
@@ -506,8 +501,7 @@ public final class AccountingConstants {
} }
private static FinancialActivityData convertToFinancialActivityData(final FinancialActivity type) { private static FinancialActivityData convertToFinancialActivityData(final FinancialActivity type) {
FinancialActivityData financialActivityData = new FinancialActivityData(type.value, type.code, type.getMappedGLAccountType()); return new FinancialActivityData(type.value, type.code, type.getMappedGLAccountType());
return financialActivityData;
} }
} }
@@ -545,8 +539,7 @@ public final class AccountingConstants {
} }
public static CashAccountsForShares fromInt(final int i) { public static CashAccountsForShares fromInt(final int i) {
final CashAccountsForShares type = intToEnumMap.get(Integer.valueOf(i)); return intToEnumMap.get(i);
return type;
} }
} }
@@ -37,9 +37,7 @@ public final class AccountingEnumerations {
} }
public static EnumOptionData gLAccountType(final GLAccountType accountType) { public static EnumOptionData gLAccountType(final GLAccountType accountType) {
final EnumOptionData optionData = new EnumOptionData(accountType.getValue().longValue(), accountType.getCode(), return new EnumOptionData(accountType.getValue().longValue(), accountType.getCode(), accountType.toString());
accountType.toString());
return optionData;
} }
public static List<EnumOptionData> gLAccountType(final GLAccountType[] accountTypes) { public static List<EnumOptionData> gLAccountType(final GLAccountType[] accountTypes) {
@@ -55,9 +53,7 @@ public final class AccountingEnumerations {
} }
public static EnumOptionData gLAccountUsage(final GLAccountUsage accountUsage) { public static EnumOptionData gLAccountUsage(final GLAccountUsage accountUsage) {
final EnumOptionData optionData = new EnumOptionData(accountUsage.getValue().longValue(), accountUsage.getCode(), return new EnumOptionData(accountUsage.getValue().longValue(), accountUsage.getCode(), accountUsage.toString());
accountUsage.toString());
return optionData;
} }
public static List<EnumOptionData> gLAccountUsage(final GLAccountUsage[] accountUsages) { public static List<EnumOptionData> gLAccountUsage(final GLAccountUsage[] accountUsages) {
@@ -73,9 +69,7 @@ public final class AccountingEnumerations {
} }
public static EnumOptionData journalEntryType(final JournalEntryType journalEntryType) { public static EnumOptionData journalEntryType(final JournalEntryType journalEntryType) {
final EnumOptionData optionData = new EnumOptionData(journalEntryType.getValue().longValue(), journalEntryType.getCode(), return new EnumOptionData(journalEntryType.getValue().longValue(), journalEntryType.getCode(), journalEntryType.toString());
journalEntryType.toString());
return optionData;
} }
public static List<EnumOptionData> journalEntryTypes(final JournalEntryType[] journalEntryTypes) { public static List<EnumOptionData> journalEntryTypes(final JournalEntryType[] journalEntryTypes) {
@@ -91,9 +85,8 @@ public final class AccountingEnumerations {
} }
public static EnumOptionData portfolioProductType(final PortfolioProductType portfolioProductType) { public static EnumOptionData portfolioProductType(final PortfolioProductType portfolioProductType) {
final EnumOptionData optionData = new EnumOptionData(portfolioProductType.getValue().longValue(), portfolioProductType.getCode(), return new EnumOptionData(portfolioProductType.getValue().longValue(), portfolioProductType.getCode(),
portfolioProductType.toString()); portfolioProductType.toString());
return optionData;
} }
public static EnumOptionData accountingRuleType(final int id) { public static EnumOptionData accountingRuleType(final int id) {
@@ -101,8 +94,7 @@ public final class AccountingEnumerations {
} }
public static EnumOptionData accountingRuleType(final AccountingRuleType type) { public static EnumOptionData accountingRuleType(final AccountingRuleType type) {
final EnumOptionData optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), type.toString()); return new EnumOptionData(type.getValue().longValue(), type.getCode(), type.toString());
return optionData;
} }
public static List<EnumOptionData> accountingRuleTypes(final AccountingRuleType[] accountingRuleTypes) { public static List<EnumOptionData> accountingRuleTypes(final AccountingRuleType[] accountingRuleTypes) {
@@ -45,8 +45,7 @@ public enum AccountingRuleType {
} }
public static AccountingRuleType fromInt(final Integer ruleTypeValue) { public static AccountingRuleType fromInt(final Integer ruleTypeValue) {
final AccountingRuleType type = intToEnumMap.get(ruleTypeValue); return intToEnumMap.get(ruleTypeValue);
return type;
} }
AccountingRuleType(final Integer value, final String code, final String description) { AccountingRuleType(final Integer value, final String code, final String description) {
@@ -44,26 +44,14 @@ public enum AccountType {
} }
public static AccountType fromInt(final Integer accountTypeValue) { public static AccountType fromInt(final Integer accountTypeValue) {
return switch (accountTypeValue) {
AccountType enumeration = AccountType.INVALID; case 1 -> AccountType.INDIVIDUAL;
switch (accountTypeValue) { case 2 -> AccountType.GROUP;
case 1: case 3 -> AccountType.JLG;
enumeration = AccountType.INDIVIDUAL; case 4 -> AccountType.GLIM;
break; case 5 -> AccountType.GSIM;
case 2: default -> AccountType.INVALID;
enumeration = AccountType.GROUP; };
break;
case 3:
enumeration = AccountType.JLG;
break;
case 4:
enumeration = AccountType.GLIM;
break;
case 5:
enumeration = AccountType.GSIM;
break;
}
return enumeration;
} }
public static AccountType fromName(final String name) { public static AccountType fromName(final String name) {
@@ -42,9 +42,8 @@ public class FineractClientConfiguration {
String apiBaseUrl = baseUrl + "/fineract-provider/api/"; String apiBaseUrl = baseUrl + "/fineract-provider/api/";
boolean debugEnabled = Boolean.parseBoolean(System.getProperty("fineract.feign.debug", "false")); boolean debugEnabled = Boolean.parseBoolean(System.getProperty("fineract.feign.debug", "false"));
FineractFeignClient client = FineractFeignClient.builder().baseUrl(apiBaseUrl).credentials(username, password).tenantId(tenantId) return FineractFeignClient.builder().baseUrl(apiBaseUrl).credentials(username, password).tenantId(tenantId)
.disableSslVerification(true).debug(debugEnabled).connectTimeout(60, TimeUnit.SECONDS) .disableSslVerification(true).debug(debugEnabled).connectTimeout(60, TimeUnit.SECONDS)
.readTimeout((int) readTimeout, TimeUnit.SECONDS).build(); .readTimeout((int) readTimeout, TimeUnit.SECONDS).build();
return client;
} }
} }
@@ -44,10 +44,8 @@ public class MessagingProperties implements InitializingBean {
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
if (eventProperties.isEventVerificationEnabled()) { if (eventProperties.isEventVerificationEnabled() && (isBlank(brokerUrl) || isBlank(topicName))) {
if (isBlank(brokerUrl) || isBlank(topicName)) { throw new IllegalStateException("Broker and topic must be configured in case event verification is enabled");
throw new IllegalStateException("Broker and topic must be configured in case event verification is enabled");
}
} }
} }
} }
@@ -165,7 +165,7 @@ public class JournalEntriesStepDef extends AbstractStepDef {
} }
public List<List<JournalEntryTransactionItem>> getJournalLinesActualList(List<GetLoansLoanIdTransactions> transactionsMatch) { public List<List<JournalEntryTransactionItem>> getJournalLinesActualList(List<GetLoansLoanIdTransactions> transactionsMatch) {
List<List<JournalEntryTransactionItem>> journalLinesActualList = transactionsMatch.stream().map(t -> { return transactionsMatch.stream().map(t -> {
String transactionId = "L" + t.getId(); String transactionId = "L" + t.getId();
GetJournalEntriesTransactionIdResponse journalEntryDataResponse = null; GetJournalEntriesTransactionIdResponse journalEntryDataResponse = null;
try { try {
@@ -179,8 +179,6 @@ public class JournalEntriesStepDef extends AbstractStepDef {
return journalEntryDataResponse.getPageItems(); return journalEntryDataResponse.getPageItems();
}).collect(Collectors.toList()); }).collect(Collectors.toList());
return journalLinesActualList;
} }
@Then("Loan Transactions tab has {int} a {string} transactions with date {string} which has the following Journal entries:") @Then("Loan Transactions tab has {int} a {string} transactions with date {string} which has the following Journal entries:")
@@ -29,7 +29,6 @@ import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse; 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 io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
@@ -93,9 +92,8 @@ public class ExternalAssetOwnersApiResource {
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = ExternalAssetOwnerRequest.class))) @RequestBody(required = true, content = @Content(schema = @Schema(implementation = ExternalAssetOwnerRequest.class)))
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ExternalAssetOwnersApiResourceSwagger.PostInitiateTransferResponse.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ExternalAssetOwnersApiResourceSwagger.PostInitiateTransferResponse.class))), @ApiResponse(responseCode = "403", description = "Transfer cannot be initiated")
@ApiResponse(responseCode = "403", description = "Transfer cannot be initiated") })
public CommandProcessingResult transferRequestWithLoanId(@PathParam("loanId") final Long loanId, public CommandProcessingResult transferRequestWithLoanId(@PathParam("loanId") final Long loanId,
@Parameter ExternalAssetOwnerRequest assetOwnerReq, @Parameter ExternalAssetOwnerRequest assetOwnerReq,
@QueryParam(COMMAND_PARAM) @Parameter(description = COMMAND_PARAM) final String commandParam) { @QueryParam(COMMAND_PARAM) @Parameter(description = COMMAND_PARAM) final String commandParam) {
@@ -111,9 +109,8 @@ public class ExternalAssetOwnersApiResource {
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = ExternalAssetOwnerRequest.class))) @RequestBody(required = true, content = @Content(schema = @Schema(implementation = ExternalAssetOwnerRequest.class)))
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ExternalAssetOwnersApiResourceSwagger.PostInitiateTransferResponse.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ExternalAssetOwnersApiResourceSwagger.PostInitiateTransferResponse.class))), @ApiResponse(responseCode = "403", description = "Transfer cannot be initiated")
@ApiResponse(responseCode = "403", description = "Transfer cannot be initiated") })
public CommandProcessingResult transferRequestWithLoanExternalId(@PathParam("loanExternalId") final String externalLoanId, public CommandProcessingResult transferRequestWithLoanExternalId(@PathParam("loanExternalId") final String externalLoanId,
@Parameter ExternalAssetOwnerRequest assetOwnerReq, @Parameter ExternalAssetOwnerRequest assetOwnerReq,
@QueryParam(COMMAND_PARAM) @Parameter(description = COMMAND_PARAM) final String commandParam) { @QueryParam(COMMAND_PARAM) @Parameter(description = COMMAND_PARAM) final String commandParam) {
@@ -130,9 +127,8 @@ public class ExternalAssetOwnersApiResource {
@Path("/transfers/{id}") @Path("/transfers/{id}")
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ExternalAssetOwnersApiResourceSwagger.PostInitiateTransferResponse.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ExternalAssetOwnersApiResourceSwagger.PostInitiateTransferResponse.class))), @ApiResponse(responseCode = "403", description = "Transfer cannot be initiated")
@ApiResponse(responseCode = "403", description = "Transfer cannot be initiated") })
public CommandProcessingResult transferRequestWithId(@PathParam("id") final Long id, public CommandProcessingResult transferRequestWithId(@PathParam("id") final Long id,
@QueryParam(COMMAND_PARAM) @Parameter(description = COMMAND_PARAM) final String commandParam) { @QueryParam(COMMAND_PARAM) @Parameter(description = COMMAND_PARAM) final String commandParam) {
platformUserRightsContext.isAuthenticated(); platformUserRightsContext.isAuthenticated();
@@ -145,9 +141,8 @@ public class ExternalAssetOwnersApiResource {
@Path("/transfers/external-id/{externalId}") @Path("/transfers/external-id/{externalId}")
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ExternalAssetOwnersApiResourceSwagger.PostInitiateTransferResponse.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ExternalAssetOwnersApiResourceSwagger.PostInitiateTransferResponse.class))), @ApiResponse(responseCode = "403", description = "Transfer cannot be initiated")
@ApiResponse(responseCode = "403", description = "Transfer cannot be initiated") })
public CommandProcessingResult transferRequestWithId(@PathParam("externalId") final String externalId, public CommandProcessingResult transferRequestWithId(@PathParam("externalId") final String externalId,
@QueryParam(COMMAND_PARAM) @Parameter(description = COMMAND_PARAM) final String commandParam) { @QueryParam(COMMAND_PARAM) @Parameter(description = COMMAND_PARAM) final String commandParam) {
platformUserRightsContext.isAuthenticated(); platformUserRightsContext.isAuthenticated();
@@ -223,7 +223,7 @@ public class ExternalAssetOwnersWriteServiceImpl implements ExternalAssetOwnersW
List<ExternalAssetOwnerTransfer> effectiveTransfers = externalAssetOwnerTransferRepository List<ExternalAssetOwnerTransfer> effectiveTransfers = externalAssetOwnerTransferRepository
.findEffectiveTransfersOrderByIdDesc(loanDataForExternalTransfer.getId(), DateUtils.getBusinessLocalDate()); .findEffectiveTransfersOrderByIdDesc(loanDataForExternalTransfer.getId(), DateUtils.getBusinessLocalDate());
if (effectiveTransfers.size() == 0) { if (effectiveTransfers.isEmpty()) {
throw new ExternalAssetOwnerInitiateTransferException( throw new ExternalAssetOwnerInitiateTransferException(
"This loan cannot be bought back, it is not owned by an external asset owner"); "This loan cannot be bought back, it is not owned by an external asset owner");
} else if (effectiveTransfers.size() == 2) { } else if (effectiveTransfers.size() == 2) {
@@ -55,12 +55,9 @@ public class LoanTransferabilityServiceImpl implements LoanTransferabilityServic
return true; return true;
} }
if (ExternalTransferStatus.PENDING_INTERMEDIATE == externalAssetOwnerTransfer.getStatus()) { // When delayed settlement is enabled and asset is sold to intermediate. Need to validate.
// When delayed settlement is enabled and asset is sold to intermediate. Need to validate. return ExternalTransferStatus.PENDING_INTERMEDIATE == externalAssetOwnerTransfer.getStatus();
return true;
}
// When delayed settlement is enabled and asset is sold from intermediate to investor. No need to validate. // When delayed settlement is enabled and asset is sold from intermediate to investor. No need to validate.
return false;
} }
} }
@@ -63,9 +63,8 @@ public class InvestorBusinessEventSerializer extends AbstractBusinessEventWithCu
private static CurrencyDataV1 getCurrencyFromEvent(InvestorBusinessEvent event) { private static CurrencyDataV1 getCurrencyFromEvent(InvestorBusinessEvent event) {
MonetaryCurrency loanCurrency = event.getLoan().getCurrency(); MonetaryCurrency loanCurrency = event.getLoan().getCurrency();
CurrencyDataV1 currency = CurrencyDataV1.newBuilder().setCode(loanCurrency.getCode()) return CurrencyDataV1.newBuilder().setCode(loanCurrency.getCode()).setDecimalPlaces(loanCurrency.getDigitsAfterDecimal())
.setDecimalPlaces(loanCurrency.getDigitsAfterDecimal()).setInMultiplesOf(loanCurrency.getInMultiplesOf()).build(); .setInMultiplesOf(loanCurrency.getInMultiplesOf()).build();
return currency;
} }
@Override @Override
@@ -56,7 +56,7 @@ public enum AdHocJsonInputParams {
@Override @Override
public String toString() { public String toString() {
return name().toString().replaceAll("_", " "); return name().replace("_", " ");
} }
public String getValue() { public String getValue() {
@@ -31,18 +31,11 @@ public enum AccountAssociationType {
private final String code; private final String code;
public static AccountAssociationType fromInt(final Integer statusValue) { public static AccountAssociationType fromInt(final Integer statusValue) {
return switch (statusValue) {
AccountAssociationType enumeration = AccountAssociationType.INVALID; case 1 -> AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION;
switch (statusValue) { case 2 -> AccountAssociationType.GUARANTOR_ACCOUNT_ASSOCIATION;
case 1: default -> AccountAssociationType.INVALID;
enumeration = AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION; };
break;
case 2:
enumeration = AccountAssociationType.GUARANTOR_ACCOUNT_ASSOCIATION;
break;
}
return enumeration;
} }
AccountAssociationType(final Integer value, final String code) { AccountAssociationType(final Integer value, final String code) {
@@ -31,17 +31,11 @@ public enum AccountTransferRecurrenceType {
private final String code; private final String code;
public static AccountTransferRecurrenceType fromInt(final Integer statusValue) { public static AccountTransferRecurrenceType fromInt(final Integer statusValue) {
return switch (statusValue) {
AccountTransferRecurrenceType enumeration = AccountTransferRecurrenceType.INVALID; case 1 -> AccountTransferRecurrenceType.PERIODIC;
switch (statusValue) { case 2 -> AccountTransferRecurrenceType.AS_PER_DUES;
case 1: default -> AccountTransferRecurrenceType.INVALID;
enumeration = AccountTransferRecurrenceType.PERIODIC; };
break;
case 2:
enumeration = AccountTransferRecurrenceType.AS_PER_DUES;
break;
}
return enumeration;
} }
AccountTransferRecurrenceType(final Integer value, final String code) { AccountTransferRecurrenceType(final Integer value, final String code) {
@@ -34,26 +34,14 @@ public enum AccountTransferType {
private final String code; private final String code;
public static AccountTransferType fromInt(final Integer statusValue) { public static AccountTransferType fromInt(final Integer statusValue) {
return switch (statusValue) {
AccountTransferType enumeration = AccountTransferType.INVALID; case 1 -> AccountTransferType.ACCOUNT_TRANSFER;
switch (statusValue) { case 2 -> AccountTransferType.LOAN_REPAYMENT;
case 1: case 3 -> AccountTransferType.CHARGE_PAYMENT;
enumeration = AccountTransferType.ACCOUNT_TRANSFER; case 4 -> AccountTransferType.INTEREST_TRANSFER;
break; case 5 -> AccountTransferType.LOAN_DOWN_PAYMENT;
case 2: default -> AccountTransferType.INVALID;
enumeration = AccountTransferType.LOAN_REPAYMENT; };
break;
case 3:
enumeration = AccountTransferType.CHARGE_PAYMENT;
break;
case 4:
enumeration = AccountTransferType.INTEREST_TRANSFER;
break;
case 5:
enumeration = AccountTransferType.LOAN_DOWN_PAYMENT;
break;
}
return enumeration;
} }
AccountTransferType(final Integer value, final String code) { AccountTransferType(final Integer value, final String code) {
@@ -26,7 +26,6 @@ import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse; 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 io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE; import jakarta.ws.rs.DELETE;
@@ -112,11 +111,19 @@ public class FixedDepositAccountsApiResource {
@Path("template") @Path("template")
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Retrieve Fixed Deposit Account Template", description = "This is a convenience resource. It can be useful when building maintenance user interface screens for fixed deposit applications. The template data returned consists of any or all of:\n\n" @Operation(summary = "Retrieve Fixed Deposit Account Template", description = """
+ "\n\n" + "Field Defaults\n\n" + "Allowed Value Lists" + "Example Requests:\n\n" + "\n\n" This is a convenience resource. It can be useful when building maintenance user interface screens for fixed deposit applications. The template data returned consists of any or all of:
+ "fixeddepositaccounts/template?clientId=1")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.GetFixedDepositAccountsTemplateResponse.class))) })
Field Defaults
Allowed Value ListsExample Requests:
fixeddepositaccounts/template?clientId=1""")
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.GetFixedDepositAccountsTemplateResponse.class)))
public String template(@QueryParam("clientId") @Parameter(description = "clientId") final Long clientId, public String template(@QueryParam("clientId") @Parameter(description = "clientId") final Long clientId,
@QueryParam("groupId") @Parameter(description = "groupId") final Long groupId, @QueryParam("groupId") @Parameter(description = "groupId") final Long groupId,
@QueryParam("productId") @Parameter(description = "productId") final Long productId, @QueryParam("productId") @Parameter(description = "productId") final Long productId,
@@ -135,10 +142,19 @@ public class FixedDepositAccountsApiResource {
@GET @GET
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "List Fixed deposit applications/accounts", description = "Lists Fixed Deposit Accounts\n\n" @Operation(summary = "List Fixed deposit applications/accounts", description = """
+ "Example Requests:\n\n" + "\n\n" + "fixeddepositaccounts\n\n" + "\n\n" + "fixeddepositaccounts?fields=name") Lists Fixed Deposit Accounts
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.GetFixedDepositAccountsResponse.class)))) }) Example Requests:
fixeddepositaccounts
fixeddepositaccounts?fields=name""")
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.GetFixedDepositAccountsResponse.class))))
public String retrieveAll(@Context final UriInfo uriInfo, @QueryParam("paged") @Parameter(description = "paged") final Boolean paged, public String retrieveAll(@Context final UriInfo uriInfo, @QueryParam("paged") @Parameter(description = "paged") final Boolean paged,
@QueryParam("offset") @Parameter(description = "offset") final Integer offset, @QueryParam("offset") @Parameter(description = "offset") final Integer offset,
@QueryParam("limit") @Parameter(description = "limit") final Integer limit, @QueryParam("limit") @Parameter(description = "limit") final Integer limit,
@@ -168,12 +184,13 @@ public class FixedDepositAccountsApiResource {
@POST @POST
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Submit new fixed deposit application", description = "Submits a new fixed deposit application" @Operation(summary = "Submit new fixed deposit application", description = """
+ "Mandatory Fields: clientId or groupId, productId, submittedOnDate, depositAmount, depositPeriod, depositPeriodFrequencyId\n\n" Submits a new fixed deposit application
+ "Optional Fields: accountNo, externalId, fieldOfficerId,linkAccountId(if provided initial deposit amount will be collected from this account),transferInterestToSavings(By enabling this flag all interest postings will be transferred to linked saving account )") Mandatory Fields: clientId or groupId, productId, submittedOnDate, depositAmount, depositPeriod, depositPeriodFrequencyId
Optional Fields: accountNo, externalId, fieldOfficerId,linkAccountId(if provided initial deposit amount will be collected from this account),transferInterestToSavings(By enabling this flag all interest postings will be transferred to linked saving account )""")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.PostFixedDepositAccountsRequest.class))) @RequestBody(required = true, content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.PostFixedDepositAccountsRequest.class)))
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.PostFixedDepositAccountsResponse.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.PostFixedDepositAccountsResponse.class))) })
public String submitApplication(@Parameter(hidden = true) final String apiRequestBodyAsJson) { public String submitApplication(@Parameter(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createFixedDepositAccount().withJson(apiRequestBodyAsJson) final CommandWrapper commandRequest = new CommandWrapperBuilder().createFixedDepositAccount().withJson(apiRequestBodyAsJson)
@@ -188,10 +205,17 @@ public class FixedDepositAccountsApiResource {
@Path("{accountId}") @Path("{accountId}")
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Retrieve a fixed deposit application/account", description = "Retrieves a fixed deposit application/account\n\n" @Operation(summary = "Retrieve a fixed deposit application/account", description = """
+ "Example Requests :\n\n" + "\n\n" + "fixeddepositaccounts/1" + "\n\n" + "fixeddepositaccounts/1?associations=all") Retrieves a fixed deposit application/account
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.GetFixedDepositAccountsAccountIdResponse.class))) }) Example Requests :
fixeddepositaccounts/1
fixeddepositaccounts/1?associations=all""")
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.GetFixedDepositAccountsAccountIdResponse.class)))
public String retrieveOne(@PathParam("accountId") @Parameter(description = "accountId") final Long accountId, public String retrieveOne(@PathParam("accountId") @Parameter(description = "accountId") final Long accountId,
@DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") @Parameter(description = "staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly, @DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") @Parameter(description = "staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly,
@DefaultValue("all") @QueryParam("chargeStatus") @Parameter(description = "chargeStatus") final String chargeStatus, @DefaultValue("all") @QueryParam("chargeStatus") @Parameter(description = "chargeStatus") final String chargeStatus,
@@ -220,8 +244,7 @@ public class FixedDepositAccountsApiResource {
@Path("calculate-fd-interest") @Path("calculate-fd-interest")
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.CalculateFixedDepositInterestResponse.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.CalculateFixedDepositInterestResponse.class))) })
public String calculateFixedDepositInterest(@Context final UriInfo uriInfo, public String calculateFixedDepositInterest(@Context final UriInfo uriInfo,
@QueryParam("principalAmount") @Parameter(description = "BigDecimal principalAmount") final BigDecimal principalAmount, @QueryParam("principalAmount") @Parameter(description = "BigDecimal principalAmount") final BigDecimal principalAmount,
@QueryParam("annualInterestRate") @Parameter(description = "annualInterestRate") final BigDecimal annualInterestRate, @QueryParam("annualInterestRate") @Parameter(description = "annualInterestRate") final BigDecimal annualInterestRate,
@@ -320,8 +343,7 @@ public class FixedDepositAccountsApiResource {
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Modify a fixed deposit application", description = "Fixed deposit application can only be modified when in 'Submitted and pending approval' state. Once the application is approved, the details cannot be changed using this method. Specific api endpoints will be created to allow change of interest detail such as rate, compounding period, posting period etc") @Operation(summary = "Modify a fixed deposit application", description = "Fixed deposit application can only be modified when in 'Submitted and pending approval' state. Once the application is approved, the details cannot be changed using this method. Specific api endpoints will be created to allow change of interest detail such as rate, compounding period, posting period etc")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.PutFixedDepositAccountsAccountIdRequest.class))) @RequestBody(required = true, content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.PutFixedDepositAccountsAccountIdRequest.class)))
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.PutFixedDepositAccountsAccountIdResponse.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.PutFixedDepositAccountsAccountIdResponse.class))) })
public String update(@PathParam("accountId") @Parameter(description = "accountId") final Long accountId, public String update(@PathParam("accountId") @Parameter(description = "accountId") final Long accountId,
@Parameter(hidden = true) final String apiRequestBodyAsJson) { @Parameter(hidden = true) final String apiRequestBodyAsJson) {
@@ -357,8 +379,7 @@ public class FixedDepositAccountsApiResource {
+ "Calculates and Posts interest earned on a fixed deposit account based on today's date and whether an interest posting or crediting event is due.\n\n" + "Calculates and Posts interest earned on a fixed deposit account based on today's date and whether an interest posting or crediting event is due.\n\n"
+ "Showing request/response for Calculate Interest on Fixed Deposit Account") + "Showing request/response for Calculate Interest on Fixed Deposit Account")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.PostFixedDepositAccountsAccountIdRequest.class))) @RequestBody(required = true, content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.PostFixedDepositAccountsAccountIdRequest.class)))
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.PostFixedDepositAccountsAccountIdResponse.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.PostFixedDepositAccountsAccountIdResponse.class))) })
public String handleCommands(@PathParam("accountId") @Parameter(description = "accountId") final Long accountId, public String handleCommands(@PathParam("accountId") @Parameter(description = "accountId") final Long accountId,
@QueryParam("command") @Parameter(description = "command") final String commandParam, @Context final UriInfo uriInfo, @QueryParam("command") @Parameter(description = "command") final String commandParam, @Context final UriInfo uriInfo,
@Parameter(hidden = true) final String apiRequestBodyAsJson) { @Parameter(hidden = true) final String apiRequestBodyAsJson) {
@@ -426,8 +447,7 @@ public class FixedDepositAccountsApiResource {
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Delete a fixed deposit application", description = "At present we support hard delete of fixed deposit application so long as its in 'Submitted and pending approval' state. One the application is moves past this state, it is not possible to do a 'hard' delete of the application or the account. An API endpoint will be added to close/de-activate the fixed deposit account.") @Operation(summary = "Delete a fixed deposit application", description = "At present we support hard delete of fixed deposit application so long as its in 'Submitted and pending approval' state. One the application is moves past this state, it is not possible to do a 'hard' delete of the application or the account. An API endpoint will be added to close/de-activate the fixed deposit account.")
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.DeleteFixedDepositAccountsAccountIdResponse.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositAccountsApiResourceSwagger.DeleteFixedDepositAccountsAccountIdResponse.class))) })
public String delete(@PathParam("accountId") @Parameter(description = "accountId") final Long accountId) { public String delete(@PathParam("accountId") @Parameter(description = "accountId") final Long accountId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteFixedDepositAccount(accountId).build(); final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteFixedDepositAccount(accountId).build();
@@ -25,7 +25,6 @@ import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse; 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 io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE; import jakarta.ws.rs.DELETE;
@@ -86,9 +85,12 @@ import org.springframework.util.CollectionUtils;
@Path("/v1/fixeddepositproducts") @Path("/v1/fixeddepositproducts")
@Component @Component
@Tag(name = "Fixed Deposit Product", description = "This is one of the advanced term deposit product offered by MFI's. The Fixed Deposit Products (aka FD) product offerings are modeled using this API.\n" @Tag(name = "Fixed Deposit Product", description = """
+ "\n" + "The FD products are deposit accounts which are held for a fixed term – like 1 year, 2 years etc.\n" + "\n" This is one of the advanced term deposit product offered by MFI's. The Fixed Deposit Products (aka FD) product offerings are modeled using this API.
+ "When creating fixed deposit accounts, the details from the fixed deposit product are used to auto fill details of the fixed deposit account application process.")
The FD products are deposit accounts which are held for a fixed term – like 1 year, 2 years etc.
When creating fixed deposit accounts, the details from the fixed deposit product are used to auto fill details of the fixed deposit account application process.""")
@RequiredArgsConstructor @RequiredArgsConstructor
public class FixedDepositProductsApiResource { public class FixedDepositProductsApiResource {
@@ -112,14 +114,17 @@ public class FixedDepositProductsApiResource {
@POST @POST
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Create a Fixed Deposit Product", description = "Creates a Fixed Deposit Product\n\n" @Operation(summary = "Create a Fixed Deposit Product", description = """
+ "Mandatory Fields: name, shortName, description, currencyCode, digitsAfterDecimal,inMultiplesOf, interestCompoundingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minDepositTerm, minDepositTermTypeId, accountingRule\n\n" Creates a Fixed Deposit Product
+ "Optional Fields: lockinPeriodFrequency, lockinPeriodFrequencyType, maxDepositTerm, maxDepositTermTypeId, inMultiplesOfDepositTerm, inMultiplesOfDepositTermTypeId, preClosurePenalApplicable, preClosurePenalInterest, preClosurePenalInterestOnTypeId, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, charges, charts, , withHoldTax, taxGroupId\n\n"
+ "\n" Mandatory Fields: name, shortName, description, currencyCode, digitsAfterDecimal,inMultiplesOf, interestCompoundingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minDepositTerm, minDepositTermTypeId, accountingRule
+ "Mandatory Fields for Cash based accounting (accountingRule = 2): savingsReferenceAccountId, savingsControlAccountId, interestOnSavingsAccountId, incomeFromFeeAccountId, transfersInSuspenseAccountId, incomeFromPenaltyAccountId")
Optional Fields: lockinPeriodFrequency, lockinPeriodFrequencyType, maxDepositTerm, maxDepositTermTypeId, inMultiplesOfDepositTerm, inMultiplesOfDepositTermTypeId, preClosurePenalApplicable, preClosurePenalInterest, preClosurePenalInterestOnTypeId, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, charges, charts, , withHoldTax, taxGroupId
Mandatory Fields for Cash based accounting (accountingRule = 2): savingsReferenceAccountId, savingsControlAccountId, interestOnSavingsAccountId, incomeFromFeeAccountId, transfersInSuspenseAccountId, incomeFromPenaltyAccountId""")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = FixedDepositProductsApiResourceSwagger.PostFixedDepositProductsRequest.class))) @RequestBody(required = true, content = @Content(schema = @Schema(implementation = FixedDepositProductsApiResourceSwagger.PostFixedDepositProductsRequest.class)))
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositProductsApiResourceSwagger.PostFixedDepositProductsResponse.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositProductsApiResourceSwagger.PostFixedDepositProductsResponse.class))) })
public String create(@Parameter(hidden = true) final String apiRequestBodyAsJson) { public String create(@Parameter(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createFixedDepositProduct().withJson(apiRequestBodyAsJson) final CommandWrapper commandRequest = new CommandWrapperBuilder().createFixedDepositProduct().withJson(apiRequestBodyAsJson)
@@ -136,8 +141,7 @@ public class FixedDepositProductsApiResource {
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Update a Fixed Deposit Product", description = "Updates a Fixed Deposit Product") @Operation(summary = "Update a Fixed Deposit Product", description = "Updates a Fixed Deposit Product")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = FixedDepositProductsApiResourceSwagger.PutFixedDepositProductsProductIdRequest.class))) @RequestBody(required = true, content = @Content(schema = @Schema(implementation = FixedDepositProductsApiResourceSwagger.PutFixedDepositProductsProductIdRequest.class)))
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositProductsApiResourceSwagger.PutFixedDepositProductsProductIdResponse.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositProductsApiResourceSwagger.PutFixedDepositProductsProductIdResponse.class))) })
public String update(@PathParam("productId") @Parameter(description = "productId") final Long productId, public String update(@PathParam("productId") @Parameter(description = "productId") final Long productId,
@Parameter(hidden = true) final String apiRequestBodyAsJson) { @Parameter(hidden = true) final String apiRequestBodyAsJson) {
@@ -153,10 +157,17 @@ public class FixedDepositProductsApiResource {
@GET @GET
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "List Fixed Deposit Products", description = "Lists Fixed Deposit Products\n\n" + "Example Requests:\n" + "\n" @Operation(summary = "List Fixed Deposit Products", description = """
+ "fixeddepositproducts\n" + "\n" + "\n" + "fixeddepositproducts?fields=name") Lists Fixed Deposit Products
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = FixedDepositProductsApiResourceSwagger.GetFixedDepositProductsResponse.class)))) }) Example Requests:
fixeddepositproducts
fixeddepositproducts?fields=name""")
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = FixedDepositProductsApiResourceSwagger.GetFixedDepositProductsResponse.class))))
public String retrieveAll(@Context final UriInfo uriInfo) { public String retrieveAll(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.FIXED_DEPOSIT_PRODUCT_RESOURCE_NAME); this.context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.FIXED_DEPOSIT_PRODUCT_RESOURCE_NAME);
@@ -173,11 +184,19 @@ public class FixedDepositProductsApiResource {
@Path("{productId}") @Path("{productId}")
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Retrieve a Fixed Deposit Product", description = "Retrieves a Fixed Deposit Product\n\n" + "Example Requests:\n" @Operation(summary = "Retrieve a Fixed Deposit Product", description = """
+ "\n" + "fixeddepositproducts/1\n" + "\n" + "\n" + "fixeddepositproducts/1?template=true\n" + "\n" + "\n" Retrieves a Fixed Deposit Product
+ "fixeddepositproducts/1?fields=name,description")
@ApiResponses({ Example Requests:
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositProductsApiResourceSwagger.GetFixedDepositProductsProductIdResponse.class))) })
fixeddepositproducts/1
fixeddepositproducts/1?template=true
fixeddepositproducts/1?fields=name,description""")
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositProductsApiResourceSwagger.GetFixedDepositProductsProductIdResponse.class)))
public String retrieveOne(@PathParam("productId") @Parameter(description = "productId") final Long productId, public String retrieveOne(@PathParam("productId") @Parameter(description = "productId") final Long productId,
@Context final UriInfo uriInfo) { @Context final UriInfo uriInfo) {
@@ -320,8 +339,7 @@ public class FixedDepositProductsApiResource {
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Delete a Fixed Deposit Product", description = "Deletes a Fixed Deposit Product") @Operation(summary = "Delete a Fixed Deposit Product", description = "Deletes a Fixed Deposit Product")
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositProductsApiResourceSwagger.DeleteFixedDepositProductsProductIdResponse.class)))
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = FixedDepositProductsApiResourceSwagger.DeleteFixedDepositProductsProductIdResponse.class))) })
public String delete(@PathParam("productId") @Parameter(description = "productId") final Long productId) { public String delete(@PathParam("productId") @Parameter(description = "productId") final Long productId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteFixedDepositProduct(productId).build(); final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteFixedDepositProduct(productId).build();