Merge branch 'dev-latest' of https://git.lincpay.tech/CBSNexora/cbsnexora-backend into feature/advanceLoanProduct
This commit is contained in:
+1
@@ -270,6 +270,7 @@ public final class AccountingConstants {
|
||||
INCOME_FROM_INTEREST(12), //
|
||||
LOSSES_WRITTEN_OFF(13), //
|
||||
ESCHEAT_LIABILITY(14), //
|
||||
INTEREST_PAYABLE(17), //
|
||||
/**
|
||||
* Where the paise dropped from a cash closure are absorbed.
|
||||
*
|
||||
|
||||
+111
@@ -756,6 +756,14 @@ public class CommandWrapperBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder deleteFund(final Long fundId) {
|
||||
this.actionName = "DELETE";
|
||||
this.entityName = "FUND";
|
||||
this.entityId = fundId;
|
||||
this.href = "/funds/" + fundId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder createReport() {
|
||||
this.actionName = "CREATE";
|
||||
this.entityName = "REPORT";
|
||||
@@ -884,6 +892,70 @@ public class CommandWrapperBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder createPaymentType() {
|
||||
this.actionName = "CREATE";
|
||||
this.entityName = "PAYMENTTYPE";
|
||||
this.entityId = null;
|
||||
this.href = "/paymenttypes/template";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updatePaymentType(final Long paymentTypeId) {
|
||||
this.actionName = "UPDATE";
|
||||
this.entityName = "PAYMENTTYPE";
|
||||
this.entityId = paymentTypeId;
|
||||
this.href = "/paymenttypes/" + paymentTypeId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder deletePaymentType(final Long paymentTypeId) {
|
||||
this.actionName = "DELETE";
|
||||
this.entityName = "PAYMENTTYPE";
|
||||
this.entityId = paymentTypeId;
|
||||
this.href = "/paymenttypes/" + paymentTypeId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder createSponsorBank() {
|
||||
this.actionName = "CREATE";
|
||||
this.entityName = "SPONSORBANK";
|
||||
this.entityId = null;
|
||||
this.href = "/sponsorbanks";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateSponsorBank(final Long sponsorBankId) {
|
||||
this.actionName = "UPDATE";
|
||||
this.entityName = "SPONSORBANK";
|
||||
this.entityId = sponsorBankId;
|
||||
this.href = "/sponsorbanks/" + sponsorBankId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateSponsorDdGlMapping() {
|
||||
this.actionName = "UPDATE";
|
||||
this.entityName = "SPONSORDDGLMAPPING";
|
||||
this.entityId = null;
|
||||
this.href = "/sponsordd/gl-mapping";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateInstitutionProfile() {
|
||||
this.actionName = "UPDATE";
|
||||
this.entityName = "INSTITUTIONPROFILE";
|
||||
this.entityId = null;
|
||||
this.href = "/institutionprofile";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateBranchProfile(final Long officeId) {
|
||||
this.actionName = "UPDATE";
|
||||
this.entityName = "BRANCHPROFILE";
|
||||
this.entityId = officeId;
|
||||
this.href = "/branchprofile/" + officeId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder createLoanProduct() {
|
||||
this.actionName = "CREATE";
|
||||
this.entityName = "LOANPRODUCT";
|
||||
@@ -3398,6 +3470,13 @@ public class CommandWrapperBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateCurrency() {
|
||||
this.actionName = "UPDATE";
|
||||
this.entityName = "CURRENCY";
|
||||
this.href = "/currencies";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateExternalServiceProperties(final String externalServiceName) {
|
||||
this.actionName = "UPDATE";
|
||||
this.entityName = "EXTERNALSERVICES";
|
||||
@@ -4738,4 +4817,36 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/loans/" + loanId + "/originators/" + originatorId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder createSurvey() {
|
||||
this.actionName = "CREATE";
|
||||
this.entityName = "SURVEY";
|
||||
this.entityId = null;
|
||||
this.href = "/surveys";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateSurvey(final Long surveyId) {
|
||||
this.actionName = "UPDATE";
|
||||
this.entityName = "SURVEY";
|
||||
this.entityId = surveyId;
|
||||
this.href = "/surveys/" + surveyId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder activateSurvey(final Long surveyId) {
|
||||
this.actionName = "ACTIVATE";
|
||||
this.entityName = "SURVEY";
|
||||
this.entityId = surveyId;
|
||||
this.href = "/surveys/" + surveyId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder deactivateSurvey(final Long surveyId) {
|
||||
this.actionName = "DEACTIVATE";
|
||||
this.entityName = "SURVEY";
|
||||
this.entityId = surveyId;
|
||||
this.href = "/surveys/" + surveyId;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -43,6 +43,7 @@ public enum JobName {
|
||||
UPDATE_SAVINGS_DORMANT_ACCOUNTS("Update Savings Dormant Accounts"), //
|
||||
APPLY_KYC_EXPIRY_RESTRICTIONS("Apply KYC Expiry Restrictions"), //
|
||||
SAVINGS_DAILY_INTEREST("Savings Daily Interest Accrual And Posting"), //
|
||||
SAVINGS_INTEREST_POSTING_REPORT("Generate Savings Interest Posting Report"), //
|
||||
ADD_PERIODIC_ACCRUAL_ENTRIES_FOR_LOANS_WITH_INCOME_POSTED_AS_TRANSACTIONS(
|
||||
"Add Accrual Transactions For Loans With Income Posted As Transactions"), //
|
||||
EXECUTE_REPORT_MAILING_JOBS("Execute Report Mailing Jobs"), //
|
||||
@@ -73,6 +74,7 @@ public enum JobName {
|
||||
CTR_REPORT_GENERATION("AML Monthly CTR Report Generation"), //
|
||||
AML_STR_WEEKLY_DIGEST("AML STR Weekly Digest"), //
|
||||
CLIENT_BEHAVIOUR_WINDOW("Client Behaviour Window Computation"), //
|
||||
SAVE_RBI_FORM_A_RETURN("Save RBI Form A Return"), //
|
||||
; //
|
||||
|
||||
private final String name;
|
||||
|
||||
+12
-11
@@ -27,13 +27,14 @@ import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.function.Supplier;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.command.core.CommandPipeline;
|
||||
import org.apache.fineract.organisation.monetary.command.CurrencyUpdateCommand;
|
||||
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.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyConfigurationData;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyUpdateRequest;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyUpdateResponse;
|
||||
import org.apache.fineract.organisation.monetary.service.OrganisationCurrencyReadPlatformService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -44,7 +45,8 @@ import org.springframework.stereotype.Component;
|
||||
public class CurrenciesApiResource {
|
||||
|
||||
private final OrganisationCurrencyReadPlatformService readPlatformService;
|
||||
private final CommandPipeline commandPipeline;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final DefaultToApiJsonSerializer<CurrencyUpdateRequest> toApiJsonSerializer;
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@@ -65,13 +67,12 @@ public class CurrenciesApiResource {
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Update Currency Configuration", description = "Updates the list of currencies permitted for use.")
|
||||
public CurrencyUpdateResponse updateCurrencies(@Valid CurrencyUpdateRequest request) {
|
||||
final var command = new CurrencyUpdateCommand();
|
||||
public String updateCurrencies(@Valid final CurrencyUpdateRequest request) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateCurrency()
|
||||
.withJson(toApiJsonSerializer.serialize(request)).build();
|
||||
|
||||
command.setPayload(request);
|
||||
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
final Supplier<CurrencyUpdateResponse> response = commandPipeline.send(command);
|
||||
|
||||
return response.get();
|
||||
return toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
}
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 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.organisation.monetary.handler;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyUpdateRequest;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyUpdateResponse;
|
||||
import org.apache.fineract.organisation.monetary.service.CurrencyWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "CURRENCY", action = "UPDATE")
|
||||
public class UpdateCurrencyCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final CurrencyWritePlatformService writePlatformService;
|
||||
|
||||
@Autowired
|
||||
public UpdateCurrencyCommandHandler(final CurrencyWritePlatformService writePlatformService) {
|
||||
this.writePlatformService = writePlatformService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
|
||||
final String[] currencyCodes = command.arrayValueOfParameterNamed("currencies");
|
||||
final List<String> currencies = currencyCodes == null ? List.of() : Arrays.asList(currencyCodes);
|
||||
|
||||
final CurrencyUpdateRequest request = CurrencyUpdateRequest.builder().currencies(currencies).build();
|
||||
|
||||
final CurrencyUpdateResponse response = this.writePlatformService.updateAllowedCurrencies(request);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.with(Map.of("currencies", response.getCurrencies())) //
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+15
-4
@@ -24,7 +24,10 @@ public enum PortfolioProductType {
|
||||
SAVING(2, "productType.saving"), //
|
||||
CLIENT(5, "productType.client"), //
|
||||
PROVISIONING(3, "productType.provisioning"), //
|
||||
SHARES(4, "productType.shares"); //
|
||||
SHARES(4, "productType.shares"), //
|
||||
// Current products map their GLs under their own type: sharing SAVING with savings products let a savings
|
||||
// product and a current product with the same id read each other's GL rows.
|
||||
CURRENT(6, "productType.current"); //
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
@@ -52,17 +55,25 @@ public enum PortfolioProductType {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Matched against each constant's own declared value above, not its declaration position --
|
||||
// those two orderings diverge (CLIENT is declared 3rd but its value is 5), so a switch written
|
||||
// by position silently mapped every id past SAVING to the wrong type: 3 (really PROVISIONING)
|
||||
// returned CLIENT, 4 (really SHARES) returned PROVISIONING, 5 (really CLIENT) returned SHARES,
|
||||
// and 6 (CURRENT) fell through to null -- a live NPE the moment a Current-product GL entry
|
||||
// (entity_type_enum=6) reached this on the Journal Entries screen.
|
||||
switch (v) {
|
||||
case 1:
|
||||
return LOAN;
|
||||
case 2:
|
||||
return SAVING;
|
||||
case 3:
|
||||
return CLIENT;
|
||||
case 4:
|
||||
return PROVISIONING;
|
||||
case 5:
|
||||
case 4:
|
||||
return SHARES;
|
||||
case 5:
|
||||
return CLIENT;
|
||||
case 6:
|
||||
return CURRENT;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
+19
-29
@@ -31,20 +31,15 @@ import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.command.core.CommandPipeline;
|
||||
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.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.portfolio.paymenttype.command.PaymentTypeCreateCommand;
|
||||
import org.apache.fineract.portfolio.paymenttype.command.PaymentTypeDeleteCommand;
|
||||
import org.apache.fineract.portfolio.paymenttype.command.PaymentTypeUpdateCommand;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeCreateRequest;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeCreateResponse;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeDeleteRequest;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeDeleteResponse;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeUpdateRequest;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeUpdateResponse;
|
||||
import org.apache.fineract.portfolio.paymenttype.service.PaymentTypeReadService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -55,7 +50,7 @@ import org.springframework.stereotype.Component;
|
||||
public class PaymentTypeApiResource {
|
||||
|
||||
private final PaymentTypeReadService readPlatformService;
|
||||
private final CommandPipeline commandPipeline;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final DefaultToApiJsonSerializer<PaymentTypeData> jsonSerializer;
|
||||
|
||||
@GET
|
||||
@@ -79,14 +74,13 @@ public class PaymentTypeApiResource {
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Create a Payment Type", description = "Creates a new Payment type")
|
||||
public PaymentTypeCreateResponse createPaymentType(PaymentTypeCreateRequest request) {
|
||||
final var command = new PaymentTypeCreateCommand();
|
||||
public String createPaymentType(final PaymentTypeCreateRequest request) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createPaymentType()
|
||||
.withJson(jsonSerializer.serialize(request)).build();
|
||||
|
||||
command.setPayload(request);
|
||||
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
final Supplier<PaymentTypeCreateResponse> response = commandPipeline.send(command);
|
||||
|
||||
return response.get();
|
||||
return jsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@@ -94,18 +88,16 @@ public class PaymentTypeApiResource {
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Update a Payment Type", description = "Updates a Payment Type")
|
||||
public PaymentTypeUpdateResponse updatePaymentType(@PathParam("paymentTypeId") final Long paymentTypeId,
|
||||
final PaymentTypeUpdateRequest request) {
|
||||
public String updatePaymentType(@PathParam("paymentTypeId") final Long paymentTypeId, final PaymentTypeUpdateRequest request) {
|
||||
|
||||
request.setId(paymentTypeId);
|
||||
|
||||
final var command = new PaymentTypeUpdateCommand();
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updatePaymentType(paymentTypeId)
|
||||
.withJson(jsonSerializer.serialize(request)).build();
|
||||
|
||||
command.setPayload(request);
|
||||
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
final Supplier<PaymentTypeUpdateResponse> response = commandPipeline.send(command);
|
||||
|
||||
return response.get();
|
||||
return jsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@@ -113,14 +105,12 @@ public class PaymentTypeApiResource {
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Delete a Payment Type", description = "Deletes payment type")
|
||||
public PaymentTypeDeleteResponse deleteCode(@PathParam("paymentTypeId") final Long paymentTypeId) {
|
||||
public String deleteCode(@PathParam("paymentTypeId") final Long paymentTypeId) {
|
||||
|
||||
final var command = new PaymentTypeDeleteCommand();
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().deletePaymentType(paymentTypeId).build();
|
||||
|
||||
command.setPayload(PaymentTypeDeleteRequest.builder().id(paymentTypeId).build());
|
||||
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
final Supplier<PaymentTypeDeleteResponse> response = commandPipeline.send(command);
|
||||
|
||||
return response.get();
|
||||
return jsonSerializer.serialize(result);
|
||||
}
|
||||
}
|
||||
|
||||
+34
-17
@@ -18,33 +18,50 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.paymenttype.handler;
|
||||
|
||||
import io.github.resilience4j.retry.annotation.Retry;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.command.core.Command;
|
||||
import org.apache.fineract.command.core.CommandHandler;
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeCreateRequest;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeCreateResponse;
|
||||
import org.apache.fineract.portfolio.paymenttype.service.PaymentTypeWriteService;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class PaymentTypeCreateCommandHandler implements CommandHandler<PaymentTypeCreateRequest, PaymentTypeCreateResponse> {
|
||||
@Service
|
||||
@CommandType(entity = "PAYMENTTYPE", action = "CREATE")
|
||||
public class PaymentTypeCreateCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final PaymentTypeWriteService paymentTypeWriteService;
|
||||
|
||||
@Retry(name = "commandPaymentTypeCreate", fallbackMethod = "fallback")
|
||||
@Override
|
||||
@Transactional
|
||||
public PaymentTypeCreateResponse handle(Command<PaymentTypeCreateRequest> command) {
|
||||
return paymentTypeWriteService.createPaymentType(command.getPayload());
|
||||
@Autowired
|
||||
public PaymentTypeCreateCommandHandler(final PaymentTypeWriteService paymentTypeWriteService) {
|
||||
this.paymentTypeWriteService = paymentTypeWriteService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public PaymentTypeCreateResponse fallback(Command<PaymentTypeCreateRequest> command, Throwable t) {
|
||||
return CommandHandler.super.fallback(command, t);
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
|
||||
final Boolean isSystemDefined = command.booleanObjectValueOfParameterNamed("isSystemDefined");
|
||||
|
||||
final PaymentTypeCreateRequest request = PaymentTypeCreateRequest.builder()
|
||||
.name(command.stringValueOfParameterNamed("name"))
|
||||
.description(command.stringValueOfParameterNamed("description"))
|
||||
.isCashPayment(command.booleanObjectValueOfParameterNamed("isCashPayment"))
|
||||
.position(command.longValueOfParameterNamed("position"))
|
||||
.codeName(command.stringValueOfParameterNamed("codeName"))
|
||||
.isSystemDefined(isSystemDefined != null ? isSystemDefined : Boolean.FALSE)
|
||||
.build();
|
||||
|
||||
final PaymentTypeCreateResponse response = this.paymentTypeWriteService.createPaymentType(request);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(response.getResourceId()) //
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+25
-17
@@ -18,33 +18,41 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.paymenttype.handler;
|
||||
|
||||
import io.github.resilience4j.retry.annotation.Retry;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.command.core.Command;
|
||||
import org.apache.fineract.command.core.CommandHandler;
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeDeleteRequest;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeDeleteResponse;
|
||||
import org.apache.fineract.portfolio.paymenttype.service.PaymentTypeWriteService;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class PaymentTypeDeleteCommandHandler implements CommandHandler<PaymentTypeDeleteRequest, PaymentTypeDeleteResponse> {
|
||||
@Service
|
||||
@CommandType(entity = "PAYMENTTYPE", action = "DELETE")
|
||||
public class PaymentTypeDeleteCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final PaymentTypeWriteService paymentTypeWriteService;
|
||||
|
||||
@Retry(name = "commandPaymentTypeDelete", fallbackMethod = "fallback")
|
||||
@Override
|
||||
@Transactional
|
||||
public PaymentTypeDeleteResponse handle(Command<PaymentTypeDeleteRequest> command) {
|
||||
return paymentTypeWriteService.deletePaymentType(command.getPayload());
|
||||
@Autowired
|
||||
public PaymentTypeDeleteCommandHandler(final PaymentTypeWriteService paymentTypeWriteService) {
|
||||
this.paymentTypeWriteService = paymentTypeWriteService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public PaymentTypeDeleteResponse fallback(Command<PaymentTypeDeleteRequest> command, Throwable t) {
|
||||
return CommandHandler.super.fallback(command, t);
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
|
||||
final PaymentTypeDeleteRequest request = PaymentTypeDeleteRequest.builder().id(command.entityId()).build();
|
||||
|
||||
final PaymentTypeDeleteResponse response = this.paymentTypeWriteService.deletePaymentType(request);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(response.getResourceId()) //
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+35
-17
@@ -18,33 +18,51 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.paymenttype.handler;
|
||||
|
||||
import io.github.resilience4j.retry.annotation.Retry;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.command.core.Command;
|
||||
import org.apache.fineract.command.core.CommandHandler;
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeUpdateRequest;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeUpdateResponse;
|
||||
import org.apache.fineract.portfolio.paymenttype.service.PaymentTypeWriteService;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class PaymentTypeUpdateCommandHandler implements CommandHandler<PaymentTypeUpdateRequest, PaymentTypeUpdateResponse> {
|
||||
@Service
|
||||
@CommandType(entity = "PAYMENTTYPE", action = "UPDATE")
|
||||
public class PaymentTypeUpdateCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final PaymentTypeWriteService paymentTypeWriteService;
|
||||
|
||||
@Retry(name = "commandPaymentTypeUpdate", fallbackMethod = "fallback")
|
||||
@Override
|
||||
@Transactional
|
||||
public PaymentTypeUpdateResponse handle(Command<PaymentTypeUpdateRequest> command) {
|
||||
return paymentTypeWriteService.updatePaymentType(command.getPayload());
|
||||
@Autowired
|
||||
public PaymentTypeUpdateCommandHandler(final PaymentTypeWriteService paymentTypeWriteService) {
|
||||
this.paymentTypeWriteService = paymentTypeWriteService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public PaymentTypeUpdateResponse fallback(Command<PaymentTypeUpdateRequest> command, Throwable t) {
|
||||
return CommandHandler.super.fallback(command, t);
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
|
||||
final Boolean isSystemDefined = command.booleanObjectValueOfParameterNamed("isSystemDefined");
|
||||
|
||||
final PaymentTypeUpdateRequest request = PaymentTypeUpdateRequest.builder()
|
||||
.id(command.entityId())
|
||||
.name(command.stringValueOfParameterNamed("name"))
|
||||
.description(command.stringValueOfParameterNamed("description"))
|
||||
.isCashPayment(command.booleanObjectValueOfParameterNamed("isCashPayment"))
|
||||
.position(command.longValueOfParameterNamed("position"))
|
||||
.codeName(command.stringValueOfParameterNamed("codeName"))
|
||||
.isSystemDefined(isSystemDefined != null ? isSystemDefined : Boolean.FALSE)
|
||||
.build();
|
||||
|
||||
final PaymentTypeUpdateResponse response = this.paymentTypeWriteService.updatePaymentType(request);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(response.getResourceId()) //
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
-1
@@ -32,7 +32,8 @@ public enum DepositAccountOnClosureType {
|
||||
TRANSFER_TO_SAVINGS(200, "depositAccountClosureType.transferToSavings"), //
|
||||
REINVEST_PRINCIPAL_AND_INTEREST(300, "depositAccountClosureType.reinvestPrincipalAndInterest"), //
|
||||
REINVEST_PRINCIPAL_ONLY(400, "depositAccountClosureType.reinvestPrincipalOnly"), //
|
||||
PARTIAL_REINVEST(500, "depositAccountClosureType.partialReinvest"); //
|
||||
PARTIAL_REINVEST(500, "depositAccountClosureType.partialReinvest"), //
|
||||
TRANSFER_TO_GL(600, "depositAccountClosureType.transferToGl"); //
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
@@ -53,6 +54,7 @@ public enum DepositAccountOnClosureType {
|
||||
case 300 -> REINVEST_PRINCIPAL_AND_INTEREST;
|
||||
case 400 -> REINVEST_PRINCIPAL_ONLY;
|
||||
case 500 -> PARTIAL_REINVEST;
|
||||
case 600 -> TRANSFER_TO_GL;
|
||||
default -> INVALID;
|
||||
};
|
||||
}
|
||||
@@ -91,6 +93,17 @@ public enum DepositAccountOnClosureType {
|
||||
return this.equals(PARTIAL_REINVEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pays the closure proceeds into a GL account the maker picks, instead of a savings account or cash.
|
||||
* Only the fixed-deposit premature-closure handler implements it -- see
|
||||
* DepositAccountDomainServiceJpa#handleFDAccountPreMatureClosure; every other closure path rejects it
|
||||
* in DepositAccountTransactionDataValidator#validateClosing rather than falling through to the
|
||||
* terminal "pay the balance out in cash" branch.
|
||||
*/
|
||||
public boolean isTransferToGl() {
|
||||
return this.equals(TRANSFER_TO_GL);
|
||||
}
|
||||
|
||||
// TODO: do we really need this?!?
|
||||
public static Object[] integerValues() {
|
||||
return Arrays.stream(values()).filter(value -> !INVALID.equals(value)).map(value -> value.value).toList().toArray();
|
||||
|
||||
+23
-3
@@ -143,6 +143,9 @@ public final class DepositsApiConstants {
|
||||
public static final String inMultiplesOfDepositTermParamName = "inMultiplesOfDepositTerm";
|
||||
public static final String inMultiplesOfDepositTermTypeIdParamName = "inMultiplesOfDepositTermTypeId";
|
||||
public static final String inMultiplesOfDepositTermType = "inMultiplesOfDepositTermType";
|
||||
// Days after maturity a depositor still has to walk in and renew at the original maturity date --
|
||||
// null/0 means this product keeps the instant, same-night auto-renewal every FD product had before.
|
||||
public static final String renewalGracePeriodDaysParamName = "renewalGracePeriodDays";
|
||||
|
||||
public static final String depositAmountParamName = "depositAmount";
|
||||
public static final String depositMinAmountParamName = "minDepositAmount";
|
||||
@@ -209,7 +212,18 @@ public final class DepositsApiConstants {
|
||||
public static final String onAccountClosureIdParamName = "onAccountClosureId";
|
||||
public static final String transferDescriptionParamName = "transferDescription";
|
||||
public static final String toSavingsAccountIdParamName = "toSavingsAccountId";
|
||||
// Destination GL account for DepositAccountOnClosureType.TRANSFER_TO_GL -- the closure proceeds are
|
||||
// credited straight to this GL instead of a savings account or cash.
|
||||
public static final String toGlAccountIdParamName = "toGlAccountId";
|
||||
public static final String reinvestAmountParamName = "reinvestAmount";
|
||||
// Lets a maker waive the product's configured pre-closure penalty for one premature closure --
|
||||
// see FixedDepositAccount#waivePreClosurePenaltyForThisRequest for why this is a transient
|
||||
// per-request flag rather than a stored account field.
|
||||
public static final String waivePreClosurePenaltyParamName = "waivePreClosurePenalty";
|
||||
// Why the deposit was closed before maturity -- see PrematureClosureReasonType. Persisted (unlike
|
||||
// waivePreClosurePenaltyParamName above) as the RBI audit trail of which closures waived their
|
||||
// penalty and why.
|
||||
public static final String prematureClosureReasonIdParamName = "prematureClosureReasonId";
|
||||
public static final String savingsAccounts = "savingsAccounts";
|
||||
public static final String maturityInstructionIdParamName = "maturityInstructionId";
|
||||
public static final String transferToSavingsIdParamName = "transferToSavingsId";
|
||||
@@ -238,7 +252,7 @@ public final class DepositsApiConstants {
|
||||
SavingProductAccountingParams.PENALTY_INCOME_ACCOUNT_MAPPING.getValue(),
|
||||
SavingProductAccountingParams.INTEREST_PAYABLE.getValue(), SavingProductAccountingParams.PENALTIES_RECEIVABLE.getValue(),
|
||||
SavingProductAccountingParams.FEES_RECEIVABLE.getValue(), chartsParamName, SavingsApiConstants.withHoldTaxParamName,
|
||||
SavingsApiConstants.taxGroupIdParamName));
|
||||
SavingsApiConstants.taxGroupIdParamName, SavingsApiConstants.otherGlMappingsParamName));
|
||||
|
||||
private static final Set<String> PRECLOSURE_REQUEST_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(preClosurePenalApplicableParamName, preClosurePenalInterestParamName, preClosurePenalInterestOnTypeIdParamName));
|
||||
@@ -248,11 +262,13 @@ public final class DepositsApiConstants {
|
||||
|
||||
private static final Set<String> DEPOSIT_TERM_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(minDepositTermParamName,
|
||||
maxDepositTermParamName, minDepositTermTypeIdParamName, maxDepositTermTypeIdParamName, inMultiplesOfDepositTermParamName,
|
||||
inMultiplesOfDepositTermTypeIdParamName, depositAmountParamName, depositMinAmountParamName, depositMaxAmountParamName));
|
||||
inMultiplesOfDepositTermTypeIdParamName, depositAmountParamName, depositMinAmountParamName, depositMaxAmountParamName,
|
||||
renewalGracePeriodDaysParamName));
|
||||
|
||||
private static final Set<String> DEPOSIT_TERM_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList(minDepositTermParamName,
|
||||
maxDepositTermParamName, minDepositTermType, maxDepositTermType, inMultiplesOfDepositTermParamName,
|
||||
inMultiplesOfDepositTermType, depositAmountParamName, depositMinAmountParamName, depositMaxAmountParamName));
|
||||
inMultiplesOfDepositTermType, depositAmountParamName, depositMinAmountParamName, depositMaxAmountParamName,
|
||||
renewalGracePeriodDaysParamName));
|
||||
|
||||
private static final Set<String> RECURRING_DETAILS_REQUEST_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(mandatoryRecommendedDepositAmountParamName, isMandatoryDepositParamName, allowWithdrawalParamName,
|
||||
@@ -374,6 +390,8 @@ public final class DepositsApiConstants {
|
||||
fixedDepositRequestData.add("paymentChannelToFundSourceMappings");
|
||||
fixedDepositRequestData.add("feeToIncomeAccountMappings");
|
||||
fixedDepositRequestData.add("penaltyToIncomeAccountMappings");
|
||||
fixedDepositRequestData.add(SavingsApiConstants.otherGlMappingsParamName);
|
||||
fixedDepositRequestData.add("otherGlMappingsMap");
|
||||
return fixedDepositRequestData;
|
||||
}
|
||||
|
||||
@@ -485,6 +503,8 @@ public final class DepositsApiConstants {
|
||||
recurringDepositRequestData.add("paymentChannelToFundSourceMappings");
|
||||
recurringDepositRequestData.add("feeToIncomeAccountMappings");
|
||||
recurringDepositRequestData.add("penaltyToIncomeAccountMappings");
|
||||
recurringDepositRequestData.add(SavingsApiConstants.otherGlMappingsParamName);
|
||||
recurringDepositRequestData.add("otherGlMappingsMap");
|
||||
return recurringDepositRequestData;
|
||||
}
|
||||
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 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.savings;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Why a Fixed/Recurring Deposit was closed before maturity -- captured on every premature closure, not
|
||||
* just the ones that waive the penalty, so the audit trail always shows a reason rather than only
|
||||
* recording one when it happens to matter. {@link #isAutoWaived()} is the RBI-driven business rule this
|
||||
* type exists to encode: a maker cannot leave the platform's own penalty-waiver decision to memory or a
|
||||
* free-text note for these four reasons -- picking the reason IS the waiver decision, enforced on the
|
||||
* server regardless of what a client happened to also send for the plain waive-penalty flag.
|
||||
*/
|
||||
@Getter
|
||||
public enum PrematureClosureReasonType {
|
||||
|
||||
INVALID(0, "prematureClosureReasonType.invalid", false), //
|
||||
NORMAL(100, "prematureClosureReasonType.normal", false), //
|
||||
PREMATURE_EXTENSION(200, "prematureClosureReasonType.prematureExtension", true), //
|
||||
CONVERSION_TO_ANOTHER_TD(300, "prematureClosureReasonType.conversionToAnotherTd", true), //
|
||||
DECEASED_SETTLEMENT(400, "prematureClosureReasonType.deceasedSettlement", true), //
|
||||
NOMINEE_LEGAL_HEIR_CLOSURE(500, "prematureClosureReasonType.nomineeLegalHeirClosure", true); //
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
/** True when this reason, by itself, waives the pre-closure penalty regardless of any manual
|
||||
* waive-penalty flag also sent -- see the class javadoc. */
|
||||
private final boolean autoWaived;
|
||||
|
||||
PrematureClosureReasonType(final Integer value, final String code, final boolean autoWaived) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
this.autoWaived = autoWaived;
|
||||
}
|
||||
|
||||
public static PrematureClosureReasonType fromInt(final Integer v) {
|
||||
if (v == null) {
|
||||
return INVALID;
|
||||
}
|
||||
return switch (v) {
|
||||
case 100 -> NORMAL;
|
||||
case 200 -> PREMATURE_EXTENSION;
|
||||
case 300 -> CONVERSION_TO_ANOTHER_TD;
|
||||
case 400 -> DECEASED_SETTLEMENT;
|
||||
case 500 -> NOMINEE_LEGAL_HEIR_CLOSURE;
|
||||
default -> INVALID;
|
||||
};
|
||||
}
|
||||
|
||||
public boolean isInvalid() {
|
||||
return this.equals(INVALID);
|
||||
}
|
||||
}
|
||||
+9
@@ -286,6 +286,15 @@ public class SavingsApiConstants {
|
||||
public static final String avgBalanceCalcPeriodParamName = "avgBalanceCalcPeriod";
|
||||
public static final String validForPeriodParamName = "validForPeriod";
|
||||
public static final String odAccountClosedZeroBalanceInDayClosingParamName = "odAccountClosedZeroBalanceInDayClosing";
|
||||
// Overdraft scheme rules a sanction on an account is held to: overdraftLimit is the ceiling (an
|
||||
// amount), odMinLimit the floor, odSecurityType whether the limit may be clean, secured, or either.
|
||||
public static final String odMinLimitParamName = "odMinLimit";
|
||||
public static final String odSecurityTypeParamName = "odSecurityType";
|
||||
// Excess drawing: whether an account may go past its sanctioned limit, by how much (a percentage of the
|
||||
// limit), and the penal charge (% p.a.) levied on the excess alone for the days it stays excess.
|
||||
public static final String odExcessAllowedParamName = "odExcessAllowed";
|
||||
public static final String odExcessLimitPercentParamName = "odExcessLimitPercent";
|
||||
public static final String odPenalRateParamName = "odPenalRate";
|
||||
|
||||
// Status of Account fields
|
||||
public static final String accountStatusParamName = "accountStatus";
|
||||
|
||||
+10
@@ -152,6 +152,11 @@ public final class SavingsProductData implements Serializable {
|
||||
@Getter @Setter private String avgBalanceCalcPeriod;
|
||||
@Getter @Setter private String validForPeriod;
|
||||
@Getter @Setter private Boolean odAccountClosedZeroBalanceInDayClosing;
|
||||
@Getter @Setter private BigDecimal odMinLimit;
|
||||
@Getter @Setter private String odSecurityType;
|
||||
@Getter @Setter private Boolean odExcessAllowed;
|
||||
@Getter @Setter private BigDecimal odExcessLimitPercent;
|
||||
@Getter @Setter private BigDecimal odPenalRate;
|
||||
|
||||
// Complex objects wrapped as Maps/Lists so Jackson converts them into the exact JSON your UI expects
|
||||
@Getter @Setter private Map<String, Object> accountFacilityConfig;
|
||||
@@ -382,6 +387,11 @@ public final class SavingsProductData implements Serializable {
|
||||
target.setAvgBalanceCalcPeriod(source.getAvgBalanceCalcPeriod());
|
||||
target.setValidForPeriod(source.getValidForPeriod());
|
||||
target.setOdAccountClosedZeroBalanceInDayClosing(source.getOdAccountClosedZeroBalanceInDayClosing());
|
||||
target.setOdMinLimit(source.getOdMinLimit());
|
||||
target.setOdSecurityType(source.getOdSecurityType());
|
||||
target.setOdExcessAllowed(source.getOdExcessAllowed());
|
||||
target.setOdExcessLimitPercent(source.getOdExcessLimitPercent());
|
||||
target.setOdPenalRate(source.getOdPenalRate());
|
||||
target.setOtherGlMappingsMap(source.getOtherGlMappingsMap());
|
||||
target.setAccountFacilityConfig(source.getAccountFacilityConfig());
|
||||
target.setAccountFacilityLimits(source.getAccountFacilityLimits());
|
||||
|
||||
+4
@@ -801,6 +801,10 @@ public final class SavingsEnumerations {
|
||||
optionData = new EnumOptionData(DepositAccountOnClosureType.PARTIAL_REINVEST.getValue().longValue(),
|
||||
DepositAccountOnClosureType.PARTIAL_REINVEST.getCode(), "Partial Re-Invest");
|
||||
break;
|
||||
case TRANSFER_TO_GL:
|
||||
optionData = new EnumOptionData(DepositAccountOnClosureType.TRANSFER_TO_GL.getValue().longValue(),
|
||||
DepositAccountOnClosureType.TRANSFER_TO_GL.getCode(), "Transfer to GL Account");
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user