From 61ff3e37a24e84e40cfbb4ff8356f2fda2d8065d Mon Sep 17 00:00:00 2001 From: Aleksandar Vidakovic Date: Mon, 18 May 2026 18:49:06 +0200 Subject: [PATCH] FINERACT-2612: New command processing - tax --- .../AccountMappingOptionsAdapterImpl.java | 32 +- .../GLAccountTypeOptionsAdapterImpl.java | 26 +- .../portfolio/charge/domain/Charge.java | 2 +- .../command/core/CommandConstants.java | 7 +- .../command/hook/ValidationCommandHook.java | 57 +++ .../resources/application-test.properties | 1 + .../adapter/AccountMappingOptionsAdapter.java | 19 +- .../adapter/GLAccountTypeOptionsAdapter.java | 28 ++ .../service/CommandWrapperBuilder.java | 104 ----- .../portfolio/tax/data/TaxComponentData.java | 110 ++--- .../tax/data/TaxComponentHistoryData.java | 33 +- .../portfolio/tax/data/TaxDetailsData.java | 18 +- .../portfolio/tax/data/TaxGroupData.java | 40 +- .../tax/data/TaxGroupMappingsData.java | 45 +-- .../core/config/SecurityConfig.java | 18 + .../api/WorkingDaysApiResourceSwagger.java | 88 ---- .../ChargeReadPlatformServiceImpl.java | 6 +- .../charge/starter/ChargeConfiguration.java | 4 +- .../api/FixedDepositProductsApiResource.java | 4 +- .../RecurringDepositProductsApiResource.java | 4 +- .../api/SavingsProductsApiResource.java | 4 +- ...DepositAccountReadPlatformServiceImpl.java | 4 +- ...DepositProductReadPlatformServiceImpl.java | 2 +- ...SavingsAccountReadPlatformServiceImpl.java | 8 +- ...ccountTemplateReadPlatformServiceImpl.java | 2 +- ...SavingsProductReadPlatformServiceImpl.java | 2 +- .../portfolio/tax/service/TaxAssembler.java | 156 -------- .../service/TaxWritePlatformServiceImpl.java | 99 ----- .../tax/starter/TaxConfiguration.java | 68 ---- .../src/main/resources/application.properties | 29 ++ .../resources/application-test.properties | 1 + fineract-tax/dependencies.gradle | 1 + .../tax/api/TaxComponentApiResource.java | 105 +++-- .../api/TaxComponentApiResourceSwagger.java | 151 ------- .../tax/api/TaxGroupApiResource.java | 110 ++--- .../tax/api/TaxGroupApiResourceSwagger.java | 155 -------- .../command/TaxComponentCreateCommand.java | 28 ++ .../command/TaxComponentUpdateCommand.java | 28 ++ .../tax/command/TaxGroupCreateCommand.java | 28 ++ .../tax/command/TaxGroupUpdateCommand.java | 28 ++ .../tax/data/TaxComponentCreateRequest.java | 83 ++++ .../tax/data/TaxComponentCreateResponse.java | 22 +- .../tax/data/TaxComponentUpdateRequest.java | 78 ++++ .../tax/data/TaxComponentUpdateResponse.java | 31 +- .../TaxGroupComponentData.java} | 41 +- .../tax/data/TaxGroupCreateRequest.java | 50 +++ .../tax/data/TaxGroupCreateResponse.java | 19 +- .../tax/data/TaxGroupUpdateRequest.java | 103 +++++ .../tax/data/TaxGroupUpdateResponse.java | 42 ++ .../portfolio/tax/domain/TaxComponent.java | 117 ++---- .../tax/domain/TaxComponentHistory.java | 37 +- .../portfolio/tax/domain/TaxGroup.java | 83 +--- .../tax/domain/TaxGroupMappings.java | 70 +--- .../tax/domain/TaxGroupRepositoryWrapper.java | 12 +- .../handler/CreateTaxGroupCommandHandler.java | 41 -- .../TaxComponentCreateCommandHandler.java | 50 +++ .../TaxComponentUpdateCommandHandler.java | 50 +++ .../handler/TaxGroupCreateCommandHandler.java | 50 +++ .../handler/TaxGroupUpdateCommandHandler.java | 50 +++ .../UpdateTaxComponentCommandHandler.java | 41 -- .../handler/UpdateTaxGroupCommandHandler.java | 41 -- .../TaxComponentCreateRequestMapper.java | 73 ++++ .../mapper/TaxGroupCreateRequestMapper.java | 87 ++++ .../tax/serialization/TaxValidator.java | 376 ------------------ .../service/ChargeTaxApplicationService.java | 2 + .../ChargeTaxApplicationServiceImpl.java | 8 +- ...atformService.java => TaxReadService.java} | 2 +- .../tax/service/TaxReadServiceImpl.java | 33 +- .../portfolio/tax/service/TaxUtils.java | 94 ++--- .../tax/service/TaxWriteService.java | 39 ++ .../tax/service/TaxWriteServiceImpl.java | 157 ++++++++ .../resources/ValidationMessages.properties | 24 ++ .../integrationtests/ChargesTest.java | 26 +- .../ClientSavingsIntegrationTest.java | 18 +- .../integrationtests/FixedDepositTest.java | 23 +- .../LoanChargeTaxIntegrationTest.java | 83 ++-- .../RecurringDepositTest.java | 20 +- .../fineract/integrationtests/TaxesTest.java | 43 +- .../helpers/FeignTaxComponentHelper.java | 10 +- .../feign/helpers/FeignTaxGroupHelper.java | 16 +- .../common/TaxComponentHelper.java | 10 +- .../common/TaxGroupHelper.java | 14 +- 82 files changed, 1740 insertions(+), 2184 deletions(-) rename fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxApiConstants.java => fineract-accounting/src/main/java/org/apache/fineract/accounting/adapter/AccountMappingOptionsAdapterImpl.java (51%) rename fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponentRepositoryWrapper.java => fineract-accounting/src/main/java/org/apache/fineract/accounting/adapter/GLAccountTypeOptionsAdapterImpl.java (57%) create mode 100644 fineract-command/src/main/java/org/apache/fineract/command/hook/ValidationCommandHook.java rename fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWritePlatformService.java => fineract-core/src/main/java/org/apache/fineract/accounting/adapter/AccountMappingOptionsAdapter.java (60%) create mode 100644 fineract-core/src/main/java/org/apache/fineract/accounting/adapter/GLAccountTypeOptionsAdapter.java delete mode 100644 fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/api/WorkingDaysApiResourceSwagger.java delete mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/service/TaxAssembler.java delete mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWritePlatformServiceImpl.java delete mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/starter/TaxConfiguration.java delete mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxComponentApiResourceSwagger.java delete mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxGroupApiResourceSwagger.java create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/command/TaxComponentCreateCommand.java create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/command/TaxComponentUpdateCommand.java create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/command/TaxGroupCreateCommand.java create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/command/TaxGroupUpdateCommand.java create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentCreateRequest.java rename fineract-core/src/main/java/org/apache/fineract/portfolio/tax/request/TaxGroupRequest.java => fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentCreateResponse.java (75%) create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentUpdateRequest.java rename fineract-core/src/main/java/org/apache/fineract/portfolio/tax/request/TaxComponentRequest.java => fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentUpdateResponse.java (62%) rename fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/{handler/CreateTaxComponentCommandHandler.java => data/TaxGroupComponentData.java} (50%) create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupCreateRequest.java rename fineract-core/src/main/java/org/apache/fineract/portfolio/tax/request/TaxGroupComponent.java => fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupCreateResponse.java (75%) create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupUpdateRequest.java create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupUpdateResponse.java delete mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/CreateTaxGroupCommandHandler.java create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/TaxComponentCreateCommandHandler.java create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/TaxComponentUpdateCommandHandler.java create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/TaxGroupCreateCommandHandler.java create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/TaxGroupUpdateCommandHandler.java delete mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/UpdateTaxComponentCommandHandler.java delete mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/UpdateTaxGroupCommandHandler.java create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/mapper/TaxComponentCreateRequestMapper.java create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/mapper/TaxGroupCreateRequestMapper.java delete mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/serialization/TaxValidator.java rename fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/{TaxReadPlatformService.java => TaxReadService.java} (97%) rename fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/service/TaxReadPlatformServiceImpl.java => fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxReadServiceImpl.java (63%) create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWriteService.java create mode 100644 fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWriteServiceImpl.java diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxApiConstants.java b/fineract-accounting/src/main/java/org/apache/fineract/accounting/adapter/AccountMappingOptionsAdapterImpl.java similarity index 51% rename from fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxApiConstants.java rename to fineract-accounting/src/main/java/org/apache/fineract/accounting/adapter/AccountMappingOptionsAdapterImpl.java index 7487a5d9418..0c5dc70c466 100644 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxApiConstants.java +++ b/fineract-accounting/src/main/java/org/apache/fineract/accounting/adapter/AccountMappingOptionsAdapterImpl.java @@ -16,23 +16,25 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.fineract.portfolio.tax.api; +package org.apache.fineract.accounting.adapter; -public interface TaxApiConstants { +import java.util.List; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.accounting.common.AccountingDropdownReadPlatformService; +import org.apache.fineract.accounting.glaccount.data.GLAccountData; +import org.springframework.stereotype.Component; - String nameParamName = "name"; - String percentageParamName = "percentage"; - String debitAccountTypeParamName = "debitAccountType"; - String debitAccountIdParamName = "debitAccountId"; - String creditAccountTypeParamName = "creditAccountType"; - String creditAccountIdParamName = "creditAccountId"; +@Slf4j +@RequiredArgsConstructor +@Component +public class AccountMappingOptionsAdapterImpl implements AccountMappingOptionsAdapter { - String startDateParamName = "startDate"; - String endDateParamName = "endDate"; - - String chargeIncludesTaxParamName = "chargeIncludesTax"; - String taxComponentsParamName = "taxComponents"; - String idParamName = "id"; - String taxComponentIdParamName = "taxComponentId"; + private final AccountingDropdownReadPlatformService accountingDropdownReadPlatformService; + @Override + public Map> retrieve() { + return accountingDropdownReadPlatformService.retrieveAccountMappingOptions(); + } } diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponentRepositoryWrapper.java b/fineract-accounting/src/main/java/org/apache/fineract/accounting/adapter/GLAccountTypeOptionsAdapterImpl.java similarity index 57% rename from fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponentRepositoryWrapper.java rename to fineract-accounting/src/main/java/org/apache/fineract/accounting/adapter/GLAccountTypeOptionsAdapterImpl.java index 7ea021fc3a6..4ccd3848bbc 100644 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponentRepositoryWrapper.java +++ b/fineract-accounting/src/main/java/org/apache/fineract/accounting/adapter/GLAccountTypeOptionsAdapterImpl.java @@ -16,24 +16,24 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.fineract.portfolio.tax.domain; +package org.apache.fineract.accounting.adapter; -import org.apache.fineract.portfolio.tax.exception.TaxComponentNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.accounting.common.AccountingDropdownReadPlatformService; +import org.apache.fineract.infrastructure.core.data.EnumOptionData; import org.springframework.stereotype.Component; +@Slf4j +@RequiredArgsConstructor @Component -public class TaxComponentRepositoryWrapper { +public class GLAccountTypeOptionsAdapterImpl implements GLAccountTypeOptionsAdapter { - private final TaxComponentRepository repository; + private final AccountingDropdownReadPlatformService accountingDropdownReadPlatformService; - @Autowired - public TaxComponentRepositoryWrapper(final TaxComponentRepository repository) { - this.repository = repository; + @Override + public List retrieve() { + return accountingDropdownReadPlatformService.retrieveGLAccountTypeOptions(); } - - public TaxComponent findOneWithNotFoundDetection(final Long id) { - return this.repository.findById(id).orElseThrow(() -> new TaxComponentNotFoundException(id)); - } - } diff --git a/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java b/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java index 4a6d513d351..1d668c4525b 100644 --- a/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java +++ b/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java @@ -655,7 +655,7 @@ public ChargeData toData() { } TaxGroupData taxGroupData = null; if (this.taxGroup != null) { - taxGroupData = TaxGroupData.lookup(taxGroup.getId(), taxGroup.getName()); + taxGroupData = TaxGroupData.builder().id(taxGroup.getId()).name(taxGroup.getName()).build(); } PaymentTypeData paymentTypeData = null; diff --git a/fineract-command/src/main/java/org/apache/fineract/command/core/CommandConstants.java b/fineract-command/src/main/java/org/apache/fineract/command/core/CommandConstants.java index 35f9c1db86f..1bd121b47a1 100644 --- a/fineract-command/src/main/java/org/apache/fineract/command/core/CommandConstants.java +++ b/fineract-command/src/main/java/org/apache/fineract/command/core/CommandConstants.java @@ -26,7 +26,8 @@ private CommandConstants() {} public static final String COMMAND_HTTP_HEADER_REQUEST_ID = "x-fineract-request-id"; public static final String COMMAND_HTTP_HEADER_TENANT_ID = "Fineract-Platform-TenantId"; public static final String COMMAND_HTTP_HEADER_IP = "IP"; - public static final int COMMAND_HOOK_ORDER_HEADERS = 10; - public static final int COMMAND_HOOK_ORDER_TIMESTAMP = 11; - public static final int COMMAND_HOOK_ORDER_USERNAME = 12; + public static final int COMMAND_HOOK_ORDER_VALIDATION = 10; + public static final int COMMAND_HOOK_ORDER_HEADERS = 11; + public static final int COMMAND_HOOK_ORDER_TIMESTAMP = 12; + public static final int COMMAND_HOOK_ORDER_USERNAME = 13; } diff --git a/fineract-command/src/main/java/org/apache/fineract/command/hook/ValidationCommandHook.java b/fineract-command/src/main/java/org/apache/fineract/command/hook/ValidationCommandHook.java new file mode 100644 index 00000000000..94f09700251 --- /dev/null +++ b/fineract-command/src/main/java/org/apache/fineract/command/hook/ValidationCommandHook.java @@ -0,0 +1,57 @@ +/** + * 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.command.hook; + +import static org.apache.fineract.command.core.CommandConstants.COMMAND_HOOK_ORDER_VALIDATION; + +import jakarta.validation.Validator; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.command.core.Command; +import org.apache.fineract.command.core.CommandHookBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@Slf4j +@RequiredArgsConstructor +@Component +@Order(COMMAND_HOOK_ORDER_VALIDATION) +@ConditionalOnProperty(value = "fineract.command.hooks.validation-pre", havingValue = "true") +final class ValidationCommandHook implements CommandHookBefore { + + private final Validator validator; + + @Override + public void onBefore(Command command) { + if (command.getPayload() != null) { + var violations = validator.validate(command.getPayload()); + + if (!violations.isEmpty()) { + // TODO: enable when all packages are migrated to new command processing and remove all @Valid + // annotations + // handle validation errors, throw Exceptions, to legacy exceptions and add localized messages? + + if (log.isDebugEnabled()) { + log.debug("Validation errors: {}", violations); + } + } + } + } +} diff --git a/fineract-command/src/test/resources/application-test.properties b/fineract-command/src/test/resources/application-test.properties index 6b548107d11..bf2c7c35b3d 100644 --- a/fineract-command/src/test/resources/application-test.properties +++ b/fineract-command/src/test/resources/application-test.properties @@ -26,3 +26,4 @@ fineract.command.enabled=true fineract.command.hooks.servlet-header-pre=${FINERACT_COMMAND_PROCESSORS_SERVLET_HEADER_PRE:true} fineract.command.hooks.timestamp-pre=${FINERACT_COMMAND_PROCESSORS_TIMESTAMP_PRE:true} fineract.command.hooks.username-pre=${FINERACT_COMMAND_PROCESSORS_USERNAME_PRE:true} +fineract.command.hooks.validation-pre=${FINERACT_COMMAND_PROCESSORS_VALIDATION_PRE:false} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWritePlatformService.java b/fineract-core/src/main/java/org/apache/fineract/accounting/adapter/AccountMappingOptionsAdapter.java similarity index 60% rename from fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWritePlatformService.java rename to fineract-core/src/main/java/org/apache/fineract/accounting/adapter/AccountMappingOptionsAdapter.java index 0d96b18fa07..318070fa696 100644 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWritePlatformService.java +++ b/fineract-core/src/main/java/org/apache/fineract/accounting/adapter/AccountMappingOptionsAdapter.java @@ -16,19 +16,14 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.fineract.portfolio.tax.service; +package org.apache.fineract.accounting.adapter; -import org.apache.fineract.infrastructure.core.api.JsonCommand; -import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import java.util.List; +import java.util.Map; +import org.apache.fineract.accounting.glaccount.data.GLAccountData; -public interface TaxWritePlatformService { - - CommandProcessingResult createTaxComponent(JsonCommand command); - - CommandProcessingResult updateTaxComponent(Long id, JsonCommand command); - - CommandProcessingResult createTaxGroup(JsonCommand command); - - CommandProcessingResult updateTaxGroup(Long id, JsonCommand command); +@FunctionalInterface +public interface AccountMappingOptionsAdapter { + Map> retrieve(); } diff --git a/fineract-core/src/main/java/org/apache/fineract/accounting/adapter/GLAccountTypeOptionsAdapter.java b/fineract-core/src/main/java/org/apache/fineract/accounting/adapter/GLAccountTypeOptionsAdapter.java new file mode 100644 index 00000000000..718a479b1da --- /dev/null +++ b/fineract-core/src/main/java/org/apache/fineract/accounting/adapter/GLAccountTypeOptionsAdapter.java @@ -0,0 +1,28 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.accounting.adapter; + +import java.util.List; +import org.apache.fineract.infrastructure.core.data.EnumOptionData; + +@FunctionalInterface +public interface GLAccountTypeOptionsAdapter { + + List retrieve(); +} diff --git a/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java b/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java index 8b07bfa0e88..f97f29c36d2 100644 --- a/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java +++ b/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java @@ -162,7 +162,6 @@ import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_CHARGE; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_CLIENT; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_CLIENTIDENTIFIER; -import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_CLIENT_COLLATERAL_PRODUCT; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_CODE; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_CODEVALUE; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_COLLATERAL; @@ -205,14 +204,12 @@ import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_LOANCHARGE; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_LOANPRODUCT; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_LOAN_AVAILABLE_DISBURSEMENT_AMOUNT; -import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_LOAN_COLLATERAL_PRODUCT; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_LOAN_ORIGINATOR; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_OFFICE; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_OFFICETRANSACTION; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_ORGANISATIONCREDITBUREAU; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_PERIODICACCRUALACCOUNTING; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_PERMISSION; -import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_PRODUCTMIX; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_PROVISIONCATEGORY; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_PROVISIONCRITERIA; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_PROVISIONENTRIES; @@ -232,8 +229,6 @@ import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_SMSCAMPAIGN; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_STANDINGINSTRUCTION; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_SURVEY; -import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_TAXCOMPONENT; -import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_TAXGROUP; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_TELLER; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_TWOFACTOR_ACCESSTOKEN; import static org.apache.fineract.commands.domain.CommandWrapperConstants.ENTITY_TWOFACTOR_CONFIGURATION; @@ -2276,24 +2271,6 @@ public CommandWrapperBuilder updateCollateral(final Long loanId, final Long coll return this; } - public CommandWrapperBuilder updateClientCollateralProduct(final Long clientId, final Long collateralId) { - this.actionName = ACTION_UPDATE; - this.entityName = ENTITY_CLIENT_COLLATERAL_PRODUCT; - this.entityId = collateralId; - this.clientId = clientId; - this.href = "/clients/" + clientId + "/collateral/" + collateralId; - return this; - } - - public CommandWrapperBuilder deleteLoanCollateral(final Long loanId, final Long collateralId) { - this.actionName = ACTION_DELETE; - this.entityName = ENTITY_LOAN_COLLATERAL_PRODUCT; - this.entityId = collateralId; - this.loanId = loanId; - this.href = "/loans/" + loanId + "/collateral/" + collateralId; - return this; - } - public CommandWrapperBuilder deleteCollateral(final Long loanId, final Long collateralId) { this.actionName = ACTION_DELETE; this.entityName = ENTITY_COLLATERAL; @@ -2303,23 +2280,6 @@ public CommandWrapperBuilder deleteCollateral(final Long loanId, final Long coll return this; } - public CommandWrapperBuilder deleteClientCollateralProduct(final Long collateralId, final Long clientId) { - this.actionName = ACTION_DELETE; - this.entityName = ENTITY_CLIENT_COLLATERAL_PRODUCT; - this.entityId = collateralId; - this.clientId = clientId; - this.href = "/clients/" + clientId + "/collateral-management/" + collateralId; - return this; - } - - public CommandWrapperBuilder addClientCollateralProduct(final Long clientId) { - this.actionName = ACTION_CREATE; - this.entityName = ENTITY_CLIENT_COLLATERAL_PRODUCT; - this.clientId = clientId; - this.href = "/clients/" + clientId + "/collateral-management"; - return this; - } - public CommandWrapperBuilder createCenter() { this.actionName = ACTION_CREATE; this.entityName = ENTITY_CENTER; @@ -2498,38 +2458,6 @@ public CommandWrapperBuilder updateClientSavingsAccount(final Long clientId) { return this; } - public CommandWrapperBuilder createProductMix(final Long productId) { - this.actionName = ACTION_CREATE; - this.entityName = ENTITY_PRODUCTMIX; - this.entityId = null; - this.productId = productId; - this.href = "/loanproducts/" + productId + "/productmix"; - return this; - } - - public CommandWrapperBuilder updateProductMix(final Long productId) { - this.actionName = ACTION_UPDATE; - this.entityName = ENTITY_PRODUCTMIX; - this.entityId = null; - this.productId = productId; - this.href = "/loanproducts/" + productId + "/productmix"; - return this; - } - - public CommandWrapperBuilder deleteProductMix(final Long productId) { - this.actionName = ACTION_DELETE; - this.entityName = ENTITY_PRODUCTMIX; - this.entityId = null; - this.productId = productId; - this.href = "/loanproducts/" + productId + "/productmix"; - return this; - } - - public CommandWrapperBuilder withProduct(final Long productId) { - this.productId = productId; - return this; - } - public CommandWrapperBuilder updateJobDetail(final Long jobId) { this.actionName = ACTION_UPDATE; this.entityName = ENTITY_SCHEDULER; @@ -3339,38 +3267,6 @@ public CommandWrapperBuilder createAccountCommand(String accountType, final Long return this; } - public CommandWrapperBuilder createTaxComponent() { - this.actionName = ACTION_CREATE; - this.entityName = ENTITY_TAXCOMPONENT; - this.entityId = null; - this.href = "/taxes/component"; - return this; - } - - public CommandWrapperBuilder updateTaxComponent(final Long taxComponentId) { - this.actionName = ACTION_UPDATE; - this.entityName = ENTITY_TAXCOMPONENT; - this.entityId = taxComponentId; - this.href = "/taxes/component/" + taxComponentId; - return this; - } - - public CommandWrapperBuilder createTaxGroup() { - this.actionName = ACTION_CREATE; - this.entityName = ENTITY_TAXGROUP; - this.entityId = null; - this.href = "/taxes/group"; - return this; - } - - public CommandWrapperBuilder updateTaxGroup(final Long taxGroupId) { - this.actionName = ACTION_UPDATE; - this.entityName = ENTITY_TAXGROUP; - this.entityId = taxGroupId; - this.href = "/taxes/group/" + taxGroupId; - return this; - } - public CommandWrapperBuilder updateWithHoldTax(final Long accountId) { this.actionName = ACTION_UPDATEWITHHOLDTAX; this.entityName = ENTITY_SAVINGSACCOUNT; diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentData.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentData.java index e7dbaedc031..28e40ffc104 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentData.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentData.java @@ -18,6 +18,7 @@ */ package org.apache.fineract.portfolio.tax.data; +import java.io.Serial; import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDate; @@ -25,104 +26,47 @@ import java.util.List; import java.util.Map; import lombok.AllArgsConstructor; -import lombok.Getter; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; import org.apache.fineract.accounting.glaccount.data.GLAccountData; import org.apache.fineract.infrastructure.core.data.EnumOptionData; import org.apache.fineract.infrastructure.core.service.DateUtils; +@Builder +@Data +@NoArgsConstructor @AllArgsConstructor -@Getter public final class TaxComponentData implements Serializable { - private final Long id; - private final String name; - private final BigDecimal percentage; - private final EnumOptionData debitAccountType; - private final GLAccountData debitAccount; - private final EnumOptionData creditAccountType; - private final GLAccountData creditAccount; - private final LocalDate startDate; - private final Collection taxComponentHistories; + @Serial + private static final long serialVersionUID = 1L; + private Long id; + private String name; + private BigDecimal percentage; + private EnumOptionData debitAccountType; + private GLAccountData debitAccount; + private EnumOptionData creditAccountType; + private GLAccountData creditAccount; + private LocalDate startDate; + private Collection taxComponentHistories; // template options - private final Map> glAccountOptions; - private final Collection glAccountTypeOptions; - - public static TaxComponentData instance(final Long id, final String name, final BigDecimal percentage, - final EnumOptionData debitAccountType, final GLAccountData debitAccount, final EnumOptionData creditAccountType, - final GLAccountData creditAccount, final LocalDate startDate, final Collection taxComponentHistories) { - final Map> glAccountOptions = null; - final Collection glAccountTypeOptions = null; - return new TaxComponentData(id, name, percentage, debitAccountType, debitAccount, creditAccountType, creditAccount, startDate, - taxComponentHistories, glAccountOptions, glAccountTypeOptions); - } - - public static TaxComponentData lookup(final Long id, final String name) { - final BigDecimal percentage = null; - final EnumOptionData debitAccountType = null; - final GLAccountData debitAccount = null; - final EnumOptionData creditAccountType = null; - final GLAccountData creditAccount = null; - final LocalDate startDate = null; - final Collection taxComponentHistories = null; - final Map> glAccountOptions = null; - final Collection glAccountTypeOptions = null; - return new TaxComponentData(id, name, percentage, debitAccountType, debitAccount, creditAccountType, creditAccount, startDate, - taxComponentHistories, glAccountOptions, glAccountTypeOptions); - } - - public static TaxComponentData template(final Map> glAccountOptions, - final Collection glAccountTypeOptions) { - final Long id = null; - final String name = null; - final BigDecimal percentage = null; - final EnumOptionData debitAccountType = null; - final GLAccountData debitAccount = null; - final EnumOptionData creditAccountType = null; - final GLAccountData creditAccount = null; - final LocalDate startDate = null; - final Collection taxComponentHistories = null; - return new TaxComponentData(id, name, percentage, debitAccountType, debitAccount, creditAccountType, creditAccount, startDate, - taxComponentHistories, glAccountOptions, glAccountTypeOptions); - } - - private TaxComponentData(final Long id, final BigDecimal percentage, final GLAccountData debitAccount, - final GLAccountData creditAccount) { - this.id = id; - this.percentage = percentage; - this.name = null; - this.debitAccountType = null; - this.debitAccount = debitAccount; - this.creditAccountType = null; - this.creditAccount = creditAccount; - this.startDate = null; - this.taxComponentHistories = null; - this.glAccountOptions = null; - this.glAccountTypeOptions = null; - } - - public static TaxComponentData createTaxComponent(final Long id, final BigDecimal percentage, final GLAccountData debitAccount, - final GLAccountData creditAccount) { - return new TaxComponentData(id, percentage, debitAccount, creditAccount); - } + private Map> glAccountOptions; + private Collection glAccountTypeOptions; public BigDecimal getApplicablePercentage(final LocalDate date) { - BigDecimal percentage = null; - if (occursOnDayFrom(date)) { - percentage = getPercentage(); + if (DateUtils.isAfter(date, startDate)) { + return getPercentage(); } else { - for (TaxComponentHistoryData componentHistory : this.taxComponentHistories) { - if (componentHistory.occursOnDayFromAndUpToAndIncluding(date)) { - percentage = componentHistory.getPercentage(); - break; + for (var componentHistory : this.taxComponentHistories) { + if (DateUtils.isAfter(date, getStartDate()) + && (componentHistory.getEndDate() == null || !DateUtils.isAfter(date, componentHistory.getEndDate()))) { + return componentHistory.getPercentage(); } } } - return percentage; - } - private boolean occursOnDayFrom(final LocalDate target) { - return DateUtils.isAfter(target, getStartDate()); + return null; } - } diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentHistoryData.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentHistoryData.java index 17b9f18d0c2..d7f2b42a661 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentHistoryData.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentHistoryData.java @@ -18,30 +18,25 @@ */ package org.apache.fineract.portfolio.tax.data; +import java.io.Serial; import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDate; -import lombok.Getter; -import org.apache.fineract.infrastructure.core.service.DateUtils; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; -@Getter +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor public class TaxComponentHistoryData implements Serializable { - @SuppressWarnings("unused") - private final BigDecimal percentage; - @SuppressWarnings("unused") - private final LocalDate startDate; - @SuppressWarnings("unused") - private final LocalDate endDate; - - public TaxComponentHistoryData(final BigDecimal percentage, final LocalDate startDate, final LocalDate endDate) { - this.percentage = percentage; - this.startDate = startDate; - this.endDate = endDate; - } - - public boolean occursOnDayFromAndUpToAndIncluding(final LocalDate target) { - return DateUtils.isAfter(target, getStartDate()) && (endDate == null || !DateUtils.isAfter(target, getEndDate())); - } + @Serial + private static final long serialVersionUID = 1L; + private BigDecimal percentage; + private LocalDate startDate; + private LocalDate endDate; } diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxDetailsData.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxDetailsData.java index 9184475aaa8..0c060c47478 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxDetailsData.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxDetailsData.java @@ -18,19 +18,23 @@ */ package org.apache.fineract.portfolio.tax.data; +import java.io.Serial; +import java.io.Serializable; import java.math.BigDecimal; import lombok.AllArgsConstructor; -import lombok.Getter; +import lombok.Builder; +import lombok.Data; import lombok.NoArgsConstructor; -import lombok.Setter; -@Getter -@AllArgsConstructor +@Builder +@Data @NoArgsConstructor -public class TaxDetailsData { +@AllArgsConstructor +public class TaxDetailsData implements Serializable { - private TaxComponentData taxComponent; + @Serial + private static final long serialVersionUID = 1L; - @Setter + private TaxComponentData taxComponent; private BigDecimal amount; } diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupData.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupData.java index 5f9804536f6..05d24deb17c 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupData.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupData.java @@ -18,38 +18,26 @@ */ package org.apache.fineract.portfolio.tax.data; +import java.io.Serial; import java.io.Serializable; import java.util.Collection; import lombok.AllArgsConstructor; -import lombok.Getter; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +@Builder +@Data +@NoArgsConstructor @AllArgsConstructor -@Getter public final class TaxGroupData implements Serializable { - private final Long id; - private final String name; - private final Collection taxAssociations; - - // Template options - @SuppressWarnings("unused") - private final Collection taxComponents; - - public static TaxGroupData lookup(final Long id, final String name) { - final Collection taxComponents = null; - final Collection taxAssociations = null; - return new TaxGroupData(id, name, taxAssociations, taxComponents); - } - - public static TaxGroupData template(final Collection taxComponents) { - final Long id = null; - final String name = null; - final Collection taxAssociations = null; - return new TaxGroupData(id, name, taxAssociations, taxComponents); - } - - public static TaxGroupData template(final TaxGroupData taxGroupData, final Collection taxComponents) { - return new TaxGroupData(taxGroupData.id, taxGroupData.name, taxGroupData.taxAssociations, taxComponents); - } + @Serial + private static final long serialVersionUID = 1L; + private Long id; + private String name; + private Collection taxAssociations; + // template options + private Collection taxComponents; } diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupMappingsData.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupMappingsData.java index 643a89eebbf..cf20e02de8d 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupMappingsData.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupMappingsData.java @@ -18,44 +18,25 @@ */ package org.apache.fineract.portfolio.tax.data; +import java.io.Serial; import java.io.Serializable; import java.time.LocalDate; import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; -import org.apache.fineract.infrastructure.core.service.DateUtils; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +@Builder +@Data +@NoArgsConstructor @AllArgsConstructor -@Getter -@Setter public class TaxGroupMappingsData implements Serializable { - @SuppressWarnings("unused") - private final Long id; - @SuppressWarnings("unused") - private final TaxComponentData taxComponent; - @SuppressWarnings("unused") - private final LocalDate startDate; - @SuppressWarnings("unused") - private final LocalDate endDate; + @Serial + private static final long serialVersionUID = 1L; - public boolean occursOnDayFromAndUpToAndIncluding(final LocalDate target) { - return DateUtils.isAfter(target, startDate()) && (endDate == null || !DateUtils.isAfter(target, endDate())); - } - - public LocalDate startDate() { - LocalDate startDate = null; - if (this.startDate != null) { - startDate = this.startDate; - } - return startDate; - } - - public LocalDate endDate() { - LocalDate endDate = null; - if (this.endDate != null) { - endDate = this.endDate; - } - return endDate; - } + private Long id; + private TaxComponentData taxComponent; + private LocalDate startDate; + private LocalDate endDate; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java index 3b578df6398..3cf0ab5158d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java @@ -409,6 +409,24 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "UPDATE_TEMPLATE") .requestMatchers(API_MATCHER.matcher(HttpMethod.DELETE, "/api/*/templates/*")) .hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "DELETE_TEMPLATE") + // tax component + .requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/taxes/component/*")) + .hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_TAXCOMPONENT") + .requestMatchers(API_MATCHER.matcher(HttpMethod.POST, "/api/*/taxes/component/*")) + .hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "CREATE_TAXCOMPONENT") + .requestMatchers(API_MATCHER.matcher(HttpMethod.PUT, "/api/*/taxes/component/*")) + .hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "UPDATE_TAXCOMPONENT") + .requestMatchers(API_MATCHER.matcher(HttpMethod.DELETE, "/api/*/taxes/component/*")) + .hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "DELETE_TAXCOMPONENT") + // tax group + .requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/taxes/group/*")) + .hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_TAXGROUP") + .requestMatchers(API_MATCHER.matcher(HttpMethod.POST, "/api/*/taxes/group/*")) + .hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "CREATE_TAXGROUP") + .requestMatchers(API_MATCHER.matcher(HttpMethod.PUT, "/api/*/taxes/group/*")) + .hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "UPDATE_TAXGROUP") + .requestMatchers(API_MATCHER.matcher(HttpMethod.DELETE, "/api/*/taxes/group/*")) + .hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "DELETE_TAXGROUP") .requestMatchers(API_MATCHER.matcher(HttpMethod.DELETE, "/api/*/loan-collateral-management/*")) .hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "DELETE_LOAN_COLLATERAL_PRODUCT") diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/api/WorkingDaysApiResourceSwagger.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/api/WorkingDaysApiResourceSwagger.java deleted file mode 100644 index 1da807591e9..00000000000 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/workingdays/api/WorkingDaysApiResourceSwagger.java +++ /dev/null @@ -1,88 +0,0 @@ -/** - * 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.workingdays.api; - -import io.swagger.v3.oas.annotations.media.Schema; -import java.util.Collection; -import org.apache.fineract.infrastructure.core.data.EnumOptionData; - -/** - * Created by sanyam on 19/8/17. - */ - -final class WorkingDaysApiResourceSwagger { - - private WorkingDaysApiResourceSwagger() { - - } - - @Schema(description = "GetWorkingDaysResponse") - public static final class GetWorkingDaysResponse { - - private GetWorkingDaysResponse() { - - } - - @Schema(example = "1") - public Long id; - @Schema(example = "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR") - public String recurrence; - public EnumOptionData repaymentRescheduleType; - @Schema(example = "true") - public Boolean extendTermForDailyRepayments; - } - - @Schema(description = "GetWorkingDaysTemplateResponse") - public static final class GetWorkingDaysTemplateResponse { - - private GetWorkingDaysTemplateResponse() { - - } - - public Collection repaymentRescheduleOptions; - } - - @Schema(description = "PutWorkingDaysRequest") - public static final class PutWorkingDaysRequest { - - private PutWorkingDaysRequest() { - - } - - @Schema(example = "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR") - public String recurrence; - @Schema(example = "en") - public String locale; - @Schema(example = "4") - public EnumOptionData repaymentRescheduleType; - @Schema(example = "true") - public Boolean extendTermForDailyRepayments; - } - - @Schema(description = "PutWorkingDaysResponse") - public static final class PutWorkingDaysResponse { - - private PutWorkingDaysResponse() { - - } - - @Schema(example = "1") - public Long resourceId; - } -} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java index 60eb1deb18b..e9953027a1d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java @@ -45,7 +45,7 @@ import org.apache.fineract.portfolio.common.service.DropdownReadPlatformService; import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData; import org.apache.fineract.portfolio.tax.data.TaxGroupData; -import org.apache.fineract.portfolio.tax.service.TaxReadPlatformService; +import org.apache.fineract.portfolio.tax.service.TaxReadService; import org.springframework.cache.annotation.Cacheable; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; @@ -65,7 +65,7 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService private final DropdownReadPlatformService dropdownReadPlatformService; private final FineractEntityAccessUtil fineractEntityAccessUtil; private final AccountingDropdownReadPlatformService accountingDropdownReadPlatformService; - private final TaxReadPlatformService taxReadPlatformService; + private final TaxReadService taxReadPlatformService; private final ConfigurationDomainServiceJpa configurationDomainServiceJpa; private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; @@ -375,7 +375,7 @@ public ChargeData mapRow(final ResultSet rs, @SuppressWarnings("unused") final i final String taxGroupName = rs.getString("taxGroupName"); TaxGroupData taxGroupData = null; if (taxGroupId != null) { - taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName); + taxGroupData = TaxGroupData.builder().id(taxGroupId).name(taxGroupName).build(); } final boolean isFreeWithdrawal = rs.getBoolean("isFreeWithdrawal"); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/starter/ChargeConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/starter/ChargeConfiguration.java index ca1185f2cf9..9fec7d59323 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/starter/ChargeConfiguration.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/starter/ChargeConfiguration.java @@ -36,7 +36,7 @@ import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository; import org.apache.fineract.portfolio.paymenttype.domain.PaymentTypeRepositoryWrapper; import org.apache.fineract.portfolio.tax.domain.TaxGroupRepositoryWrapper; -import org.apache.fineract.portfolio.tax.service.TaxReadPlatformService; +import org.apache.fineract.portfolio.tax.service.TaxReadService; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -57,7 +57,7 @@ public ChargeDropdownReadPlatformService chargeDropdownReadPlatformService() { public ChargeReadPlatformService chargeReadPlatformService(CurrencyReadPlatformService currencyReadPlatformService, ChargeDropdownReadPlatformService chargeDropdownReadPlatformService, JdbcTemplate jdbcTemplate, DropdownReadPlatformService dropdownReadPlatformService, FineractEntityAccessUtil fineractEntityAccessUtil, - AccountingDropdownReadPlatformService accountingDropdownReadPlatformService, TaxReadPlatformService taxReadPlatformService, + AccountingDropdownReadPlatformService accountingDropdownReadPlatformService, TaxReadService taxReadPlatformService, ConfigurationDomainServiceJpa configurationDomainServiceJpa, NamedParameterJdbcTemplate namedParameterJdbcTemplate) { return new ChargeReadPlatformServiceImpl(currencyReadPlatformService, chargeDropdownReadPlatformService, jdbcTemplate, dropdownReadPlatformService, fineractEntityAccessUtil, accountingDropdownReadPlatformService, taxReadPlatformService, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/FixedDepositProductsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/FixedDepositProductsApiResource.java index 870cfafc068..94fa140a159 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/FixedDepositProductsApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/FixedDepositProductsApiResource.java @@ -79,7 +79,7 @@ import org.apache.fineract.portfolio.savings.service.SavingsDropdownReadPlatformService; import org.apache.fineract.portfolio.savings.service.SavingsEnumerations; import org.apache.fineract.portfolio.tax.data.TaxGroupData; -import org.apache.fineract.portfolio.tax.service.TaxReadPlatformService; +import org.apache.fineract.portfolio.tax.service.TaxReadService; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; @@ -109,7 +109,7 @@ public class FixedDepositProductsApiResource { private final DepositsDropdownReadPlatformService depositsDropdownReadPlatformService; private final DropdownReadPlatformService dropdownReadPlatformService; private final PaymentTypeReadService paymentTypeReadPlatformService; - private final TaxReadPlatformService taxReadPlatformService; + private final TaxReadService taxReadPlatformService; @POST @Consumes({ MediaType.APPLICATION_JSON }) diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/RecurringDepositProductsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/RecurringDepositProductsApiResource.java index 4347c2fc677..e97cf6c17b8 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/RecurringDepositProductsApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/RecurringDepositProductsApiResource.java @@ -80,7 +80,7 @@ import org.apache.fineract.portfolio.savings.service.SavingsDropdownReadPlatformService; import org.apache.fineract.portfolio.savings.service.SavingsEnumerations; import org.apache.fineract.portfolio.tax.data.TaxGroupData; -import org.apache.fineract.portfolio.tax.service.TaxReadPlatformService; +import org.apache.fineract.portfolio.tax.service.TaxReadService; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; @@ -109,7 +109,7 @@ public class RecurringDepositProductsApiResource { private final DepositsDropdownReadPlatformService depositsDropdownReadPlatformService; private final DropdownReadPlatformService dropdownReadPlatformService; private final PaymentTypeReadService paymentTypeReadPlatformService; - private final TaxReadPlatformService taxReadPlatformService; + private final TaxReadService taxReadPlatformService; @POST @Consumes({ MediaType.APPLICATION_JSON }) diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsProductsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsProductsApiResource.java index a0ceb51a91f..56c17f5bb45 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsProductsApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsProductsApiResource.java @@ -75,7 +75,7 @@ import org.apache.fineract.portfolio.savings.service.SavingsEnumerations; import org.apache.fineract.portfolio.savings.service.SavingsProductReadPlatformService; import org.apache.fineract.portfolio.tax.data.TaxGroupData; -import org.apache.fineract.portfolio.tax.service.TaxReadPlatformService; +import org.apache.fineract.portfolio.tax.service.TaxReadService; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; @@ -97,7 +97,7 @@ public class SavingsProductsApiResource { private final ProductToGLAccountMappingReadPlatformService accountMappingReadPlatformService; private final ChargeReadPlatformService chargeReadPlatformService; private final PaymentTypeReadService paymentTypeReadPlatformService; - private final TaxReadPlatformService taxReadPlatformService; + private final TaxReadService taxReadPlatformService; private final ConfigurationDomainService configurationDomainService; @POST diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountReadPlatformServiceImpl.java index 5f9aceb03b4..c4f368fcf0c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositAccountReadPlatformServiceImpl.java @@ -808,7 +808,7 @@ public DepositAccountData mapRow(final ResultSet rs) throws SQLException { final String taxGroupName = rs.getString(TAX_GROUP_NAME); TaxGroupData taxGroupData = null; if (taxGroupId != null) { - taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName); + taxGroupData = TaxGroupData.builder().id(taxGroupId).name(taxGroupName).build(); } final BigDecimal availableBalance = null; @@ -1353,7 +1353,7 @@ public DepositAccountData mapRow(final ResultSet rs) throws SQLException { final String taxGroupName = rs.getString(TAX_GROUP_NAME); TaxGroupData taxGroupData = null; if (taxGroupId != null) { - taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName); + taxGroupData = TaxGroupData.builder().id(taxGroupId).name(taxGroupName).build(); } return DepositAccountData.instance(null, null, null, groupId, groupName, clientId, clientName, productId, productName, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositProductReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositProductReadPlatformServiceImpl.java index 9b8319d9a16..b9c70544c64 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositProductReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositProductReadPlatformServiceImpl.java @@ -203,7 +203,7 @@ public DepositProductData mapRow(final ResultSet rs) throws SQLException { final String taxGroupName = rs.getString("taxGroupName"); TaxGroupData taxGroupData = null; if (taxGroupId != null) { - taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName); + taxGroupData = TaxGroupData.builder().id(taxGroupId).name(taxGroupName).build(); } return DepositProductData.instance(id, name, shortName, description, currency, nominalAnnualInterestRate, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java index 7fdfbd35670..e257e882427 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java @@ -526,7 +526,7 @@ public List extractData(final ResultSet rs) throws SQLExcept final Long taxGroupId = JdbcSupport.getLongDefaultToNullIfZero(rs, "taxGroupId"); TaxGroupData taxGroupData = null; if (taxGroupId != null) { - taxGroupData = TaxGroupData.lookup(taxGroupId, null); + taxGroupData = TaxGroupData.builder().id(taxGroupId).build(); } final BigDecimal nominalAnnualInterestRate = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, @@ -666,8 +666,8 @@ public List extractData(final ResultSet rs) throws SQLExcept final GLAccountData creditAccount = GLAccountData.createFrom(creditId); if (taxComponentId != null) { - final TaxComponentData taxComponent = TaxComponentData.createTaxComponent(taxComponentId, percentage, debitAccount, - creditAccount); + final TaxComponentData taxComponent = TaxComponentData.builder().id(taxComponentId).percentage(percentage) + .debitAccount(debitAccount).creditAccount(creditAccount).build(); savingsAccountTransactionData.setTaxDetails(new TaxDetailsData(taxComponent, amount)); } @@ -976,7 +976,7 @@ public SavingsAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final String taxGroupName = rs.getString("taxGroupName"); TaxGroupData taxGroupData = null; if (taxGroupId != null) { - taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName); + taxGroupData = TaxGroupData.builder().id(taxGroupId).name(taxGroupName).build(); } return SavingsAccountData.instance(id, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountTemplateReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountTemplateReadPlatformServiceImpl.java index 8d9b95c9b5a..9a72d63dafe 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountTemplateReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountTemplateReadPlatformServiceImpl.java @@ -353,7 +353,7 @@ public SavingsAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final String taxGroupName = rs.getString("taxGroupName"); TaxGroupData taxGroupData = null; if (taxGroupId != null) { - taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName); + taxGroupData = TaxGroupData.builder().id(taxGroupId).name(taxGroupName).build(); } Long clientId = null; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java index 9c3e18d7812..6fcc877c54c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java @@ -205,7 +205,7 @@ public SavingsProductData mapRow(final ResultSet rs, @SuppressWarnings("unused") final String taxGroupName = rs.getString("taxGroupName"); TaxGroupData taxGroupData = null; if (taxGroupId != null) { - taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName); + taxGroupData = TaxGroupData.builder().id(taxGroupId).name(taxGroupName).build(); } final Boolean isDormancyTrackingActive = rs.getBoolean("isDormancyTrackingActive"); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/service/TaxAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/service/TaxAssembler.java deleted file mode 100644 index 8b558e80722..00000000000 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/service/TaxAssembler.java +++ /dev/null @@ -1,156 +0,0 @@ -/** - * 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.tax.service; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import java.math.BigDecimal; -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Set; -import lombok.RequiredArgsConstructor; -import org.apache.fineract.accounting.glaccount.domain.GLAccount; -import org.apache.fineract.accounting.glaccount.domain.GLAccountRepositoryWrapper; -import org.apache.fineract.accounting.glaccount.domain.GLAccountType; -import org.apache.fineract.infrastructure.core.api.JsonCommand; -import org.apache.fineract.infrastructure.core.data.ApiParameterError; -import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; -import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; -import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; -import org.apache.fineract.infrastructure.core.service.DateUtils; -import org.apache.fineract.portfolio.tax.api.TaxApiConstants; -import org.apache.fineract.portfolio.tax.domain.TaxComponent; -import org.apache.fineract.portfolio.tax.domain.TaxComponentRepositoryWrapper; -import org.apache.fineract.portfolio.tax.domain.TaxGroup; -import org.apache.fineract.portfolio.tax.domain.TaxGroupMappings; - -@RequiredArgsConstructor -public class TaxAssembler { - - private final FromJsonHelper fromApiJsonHelper; - private final GLAccountRepositoryWrapper glAccountRepositoryWrapper; - private final TaxComponentRepositoryWrapper taxComponentRepositoryWrapper; - - public TaxComponent assembleTaxComponentFrom(final JsonCommand command) { - final JsonElement element = command.parsedJson(); - - final List dataValidationErrors = new ArrayList<>(); - final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("tax.component"); - - final String name = this.fromApiJsonHelper.extractStringNamed(TaxApiConstants.nameParamName, element); - final BigDecimal percentage = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(TaxApiConstants.percentageParamName, element); - final Integer debitAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(TaxApiConstants.debitAccountTypeParamName, - element); - final Long debitAccountId = this.fromApiJsonHelper.extractLongNamed(TaxApiConstants.debitAccountIdParamName, element); - GLAccountType debitGlAccountType = null; - if (debitAccountType != null) { - debitGlAccountType = GLAccountType.fromInt(debitAccountType); - } - GLAccount debitGlAccount = null; - if (debitAccountId != null) { - debitGlAccount = this.glAccountRepositoryWrapper.findOneWithNotFoundDetection(debitAccountId); - if (!debitGlAccount.getType().equals(debitAccountType) || debitGlAccount.isHeaderAccount()) { - baseDataValidator.parameter(TaxApiConstants.debitAccountIdParamName).value(debitAccountId) - .failWithCode("not.a.valid.account"); - } - } - - final Integer creditAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(TaxApiConstants.creditAccountTypeParamName, - element); - GLAccountType creditGlAccountType = null; - if (creditAccountType != null) { - creditGlAccountType = GLAccountType.fromInt(creditAccountType); - } - final Long creditAccountId = this.fromApiJsonHelper.extractLongNamed(TaxApiConstants.creditAccountIdParamName, element); - GLAccount creditGlAccount = null; - if (creditAccountId != null) { - creditGlAccount = this.glAccountRepositoryWrapper.findOneWithNotFoundDetection(creditAccountId); - if (!creditGlAccount.getType().equals(creditAccountType) || creditGlAccount.isHeaderAccount()) { - baseDataValidator.parameter(TaxApiConstants.creditAccountIdParamName).value(creditAccountId) - .failWithCode("not.a.valid.account"); - } - } - throwExceptionIfValidationWarningsExist(dataValidationErrors); - LocalDate startDate = this.fromApiJsonHelper.extractLocalDateNamed(TaxApiConstants.startDateParamName, element); - if (startDate == null) { - startDate = DateUtils.getBusinessLocalDate(); - } - - return TaxComponent.createTaxComponent(name, percentage, debitGlAccountType, debitGlAccount, creditGlAccountType, creditGlAccount, - startDate); - } - - public TaxGroup assembleTaxGroupFrom(final JsonCommand command) { - final JsonElement element = command.parsedJson(); - - final String name = this.fromApiJsonHelper.extractStringNamed(TaxApiConstants.nameParamName, element); - boolean isUpdate = false; - final Set groupMappings = assembleTaxGroupMappingsFrom(command, isUpdate); - return TaxGroup.createTaxGroup(name, groupMappings); - } - - public Set assembleTaxGroupMappingsFrom(final JsonCommand command, boolean isUpdate) { - Set groupMappings = new HashSet<>(); - final JsonElement element = command.parsedJson(); - - final JsonObject topLevelJsonElement = element.getAsJsonObject(); - final String dateFormat = this.fromApiJsonHelper.extractDateFormatParameter(topLevelJsonElement); - final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement); - - if (topLevelJsonElement.get(TaxApiConstants.taxComponentsParamName).isJsonArray()) { - final JsonArray array = topLevelJsonElement.get(TaxApiConstants.taxComponentsParamName).getAsJsonArray(); - for (int i = 0; i < array.size(); i++) { - final JsonObject taxComponent = array.get(i).getAsJsonObject(); - final Long mappingId = this.fromApiJsonHelper.extractLongNamed(TaxApiConstants.idParamName, taxComponent); - final Long taxComponentId = this.fromApiJsonHelper.extractLongNamed(TaxApiConstants.taxComponentIdParamName, taxComponent); - TaxComponent component = null; - if (taxComponentId != null) { - component = this.taxComponentRepositoryWrapper.findOneWithNotFoundDetection(taxComponentId); - } - LocalDate startDate = this.fromApiJsonHelper.extractLocalDateNamed(TaxApiConstants.startDateParamName, taxComponent, - dateFormat, locale); - final LocalDate endDate = this.fromApiJsonHelper.extractLocalDateNamed(TaxApiConstants.endDateParamName, taxComponent, - dateFormat, locale); - if (endDate == null && startDate == null) { - startDate = DateUtils.getBusinessLocalDate(); - } - TaxGroupMappings mappings = null; - if (isUpdate && mappingId != null) { - mappings = TaxGroupMappings.createTaxGroupMappings(mappingId, component, endDate); - } else { - mappings = TaxGroupMappings.createTaxGroupMappings(component, startDate); - } - groupMappings.add(mappings); - - } - } - - return groupMappings; - } - - private void throwExceptionIfValidationWarningsExist(final List dataValidationErrors) { - if (!dataValidationErrors.isEmpty()) { - throw new PlatformApiDataValidationException(dataValidationErrors); - } - } -} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWritePlatformServiceImpl.java deleted file mode 100644 index a606846d322..00000000000 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWritePlatformServiceImpl.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * 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.tax.service; - -import java.util.Map; -import java.util.Set; -import lombok.RequiredArgsConstructor; -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.tax.domain.TaxComponent; -import org.apache.fineract.portfolio.tax.domain.TaxComponentRepository; -import org.apache.fineract.portfolio.tax.domain.TaxComponentRepositoryWrapper; -import org.apache.fineract.portfolio.tax.domain.TaxGroup; -import org.apache.fineract.portfolio.tax.domain.TaxGroupMappings; -import org.apache.fineract.portfolio.tax.domain.TaxGroupRepository; -import org.apache.fineract.portfolio.tax.domain.TaxGroupRepositoryWrapper; -import org.apache.fineract.portfolio.tax.serialization.TaxValidator; - -@RequiredArgsConstructor -public class TaxWritePlatformServiceImpl implements TaxWritePlatformService { - - private final TaxValidator validator; - private final TaxAssembler taxAssembler; - private final TaxComponentRepository taxComponentRepository; - private final TaxComponentRepositoryWrapper taxComponentRepositoryWrapper; - private final TaxGroupRepository taxGroupRepository; - private final TaxGroupRepositoryWrapper taxGroupRepositoryWrapper; - - @Override - public CommandProcessingResult createTaxComponent(final JsonCommand command) { - this.validator.validateForTaxComponentCreate(command.json()); - TaxComponent taxComponent = this.taxAssembler.assembleTaxComponentFrom(command); - this.taxComponentRepository.saveAndFlush(taxComponent); - return new CommandProcessingResultBuilder() // - .withCommandId(command.commandId()) // - .withEntityId(taxComponent.getId()) // - .build(); - } - - @Override - public CommandProcessingResult updateTaxComponent(final Long id, final JsonCommand command) { - this.validator.validateForTaxComponentUpdate(command.json()); - final TaxComponent taxComponent = this.taxComponentRepositoryWrapper.findOneWithNotFoundDetection(id); - this.validator.validateStartDate(taxComponent.startDate(), command); - Map changes = taxComponent.update(command); - this.validator.validateTaxComponentForUpdate(taxComponent); - this.taxComponentRepository.saveAndFlush(taxComponent); - return new CommandProcessingResultBuilder() // - .withEntityId(id) // - .with(changes) // - .build(); - } - - @Override - public CommandProcessingResult createTaxGroup(final JsonCommand command) { - this.validator.validateForTaxGroupCreate(command.json()); - final TaxGroup taxGroup = this.taxAssembler.assembleTaxGroupFrom(command); - this.validator.validateTaxGroup(taxGroup); - this.taxGroupRepository.saveAndFlush(taxGroup); - return new CommandProcessingResultBuilder() // - .withCommandId(command.commandId()) // - .withEntityId(taxGroup.getId()) // - .build(); - } - - @Override - public CommandProcessingResult updateTaxGroup(final Long id, final JsonCommand command) { - this.validator.validateForTaxGroupUpdate(command.json()); - final TaxGroup taxGroup = this.taxGroupRepositoryWrapper.findOneWithNotFoundDetection(id); - final boolean isUpdate = true; - Set groupMappings = this.taxAssembler.assembleTaxGroupMappingsFrom(command, isUpdate); - this.validator.validateTaxGroupEndDateAndTaxComponent(taxGroup, groupMappings); - Map changes = taxGroup.update(command, groupMappings); - this.validator.validateTaxGroup(taxGroup); - this.taxGroupRepository.saveAndFlush(taxGroup); - return new CommandProcessingResultBuilder() // - .withEntityId(id) // - .with(changes) // - .build(); - } - -} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/starter/TaxConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/starter/TaxConfiguration.java deleted file mode 100644 index ea566802ec7..00000000000 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/starter/TaxConfiguration.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * 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.tax.starter; - -import org.apache.fineract.accounting.common.AccountingDropdownReadPlatformService; -import org.apache.fineract.accounting.glaccount.domain.GLAccountRepositoryWrapper; -import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; -import org.apache.fineract.portfolio.tax.domain.TaxComponentRepository; -import org.apache.fineract.portfolio.tax.domain.TaxComponentRepositoryWrapper; -import org.apache.fineract.portfolio.tax.domain.TaxGroupRepository; -import org.apache.fineract.portfolio.tax.domain.TaxGroupRepositoryWrapper; -import org.apache.fineract.portfolio.tax.mapper.TaxComponentMapper; -import org.apache.fineract.portfolio.tax.mapper.TaxGroupMapper; -import org.apache.fineract.portfolio.tax.serialization.TaxValidator; -import org.apache.fineract.portfolio.tax.service.TaxAssembler; -import org.apache.fineract.portfolio.tax.service.TaxReadPlatformService; -import org.apache.fineract.portfolio.tax.service.TaxReadPlatformServiceImpl; -import org.apache.fineract.portfolio.tax.service.TaxWritePlatformService; -import org.apache.fineract.portfolio.tax.service.TaxWritePlatformServiceImpl; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class TaxConfiguration { - - @Bean - @ConditionalOnMissingBean(TaxAssembler.class) - public TaxAssembler taxAssembler(FromJsonHelper fromApiJsonHelper, GLAccountRepositoryWrapper glAccountRepositoryWrapper, - TaxComponentRepositoryWrapper taxComponentRepositoryWrapper) { - return new TaxAssembler(fromApiJsonHelper, glAccountRepositoryWrapper, taxComponentRepositoryWrapper); - } - - @Bean - @ConditionalOnMissingBean(TaxReadPlatformService.class) - public TaxReadPlatformService taxReadPlatformService(final TaxComponentRepository taxComponentRepository, - final TaxComponentRepositoryWrapper taxComponentRepositoryWrapper, final TaxComponentMapper taxComponentMapper, - final TaxGroupRepository taxGroupRepository, final TaxGroupRepositoryWrapper taxGroupRepositoryWrapper, - final TaxGroupMapper taxGroupMapper, AccountingDropdownReadPlatformService accountingDropdownReadPlatformService) { - return new TaxReadPlatformServiceImpl(accountingDropdownReadPlatformService, taxComponentRepository, taxComponentRepositoryWrapper, - taxComponentMapper, taxGroupRepository, taxGroupRepositoryWrapper, taxGroupMapper); - } - - @Bean - @ConditionalOnMissingBean(TaxWritePlatformService.class) - public TaxWritePlatformService taxWritePlatformService(TaxValidator validator, TaxAssembler taxAssembler, - TaxComponentRepository taxComponentRepository, TaxGroupRepository taxGroupRepository, - TaxComponentRepositoryWrapper taxComponentRepositoryWrapper, TaxGroupRepositoryWrapper taxGroupRepositoryWrapper) { - return new TaxWritePlatformServiceImpl(validator, taxAssembler, taxComponentRepository, taxComponentRepositoryWrapper, - taxGroupRepository, taxGroupRepositoryWrapper); - } -} diff --git a/fineract-provider/src/main/resources/application.properties b/fineract-provider/src/main/resources/application.properties index cedcc6b3cd9..75413379c26 100644 --- a/fineract-provider/src/main/resources/application.properties +++ b/fineract-provider/src/main/resources/application.properties @@ -774,6 +774,34 @@ resilience4j.retry.instances.commandLoanCollateralDelete.enable-exponential-back resilience4j.retry.instances.commandLoanCollateralDelete.exponential-backoff-multiplier=${FINERACT_COMMAND_LOAN_COLLATERAL_DELETE_RETRY_EXPONENTIAL_BACKOFF_MULTIPLIER:2} resilience4j.retry.instances.commandLoanCollateralDelete.retryExceptions=${FINERACT_COMMAND_LOAN_COLLATERAL_DELETE_RETRY_EXCEPTIONS:org.springframework.dao.ConcurrencyFailureException,org.eclipse.persistence.exceptions.OptimisticLockException,jakarta.persistence.OptimisticLockException,org.springframework.orm.jpa.JpaOptimisticLockingFailureException} +# tax component + +resilience4j.retry.instances.commandTaxComponentCreate.max-attempts=${FINERACT_COMMAND_TAX_COMPONENT_CREATE_RETRY_MAX_ATTEMPTS:3} +resilience4j.retry.instances.commandTaxComponentCreate.wait-duration=${FINERACT_COMMAND_TAX_COMPONENT_CREATE_RETRY_WAIT_DURATION:1s} +resilience4j.retry.instances.commandTaxComponentCreate.enable-exponential-backoff=${FINERACT_COMMAND_TAX_COMPONENT_CREATE_RETRY_ENABLE_EXPONENTIAL_BACKOFF:true} +resilience4j.retry.instances.commandTaxComponentCreate.exponential-backoff-multiplier=${FINERACT_COMMAND_TAX_COMPONENT_CREATE_RETRY_EXPONENTIAL_BACKOFF_MULTIPLIER:2} +resilience4j.retry.instances.commandTaxComponentCreate.retryExceptions=${FINERACT_COMMAND_TAX_COMPONENT_CREATE_RETRY_EXCEPTIONS:org.springframework.dao.ConcurrencyFailureException,org.eclipse.persistence.exceptions.OptimisticLockException,jakarta.persistence.OptimisticLockException,org.springframework.orm.jpa.JpaOptimisticLockingFailureException} + +resilience4j.retry.instances.commandTaxComponentUpdate.max-attempts=${FINERACT_COMMAND_TAX_COMPONENT_UPDATE_RETRY_MAX_ATTEMPTS:3} +resilience4j.retry.instances.commandTaxComponentUpdate.wait-duration=${FINERACT_COMMAND_TAX_COMPONENT_UPDATE_RETRY_WAIT_DURATION:1s} +resilience4j.retry.instances.commandTaxComponentUpdate.enable-exponential-backoff=${FINERACT_COMMAND_TAX_COMPONENT_UPDATE_RETRY_ENABLE_EXPONENTIAL_BACKOFF:true} +resilience4j.retry.instances.commandTaxComponentUpdate.exponential-backoff-multiplier=${FINERACT_COMMAND_TAX_COMPONENT_UPDATE_RETRY_EXPONENTIAL_BACKOFF_MULTIPLIER:2} +resilience4j.retry.instances.commandTaxComponentUpdate.retryExceptions=${FINERACT_COMMAND_TAX_COMPONENT_UPDATE_RETRY_EXCEPTIONS:org.springframework.dao.ConcurrencyFailureException,org.eclipse.persistence.exceptions.OptimisticLockException,jakarta.persistence.OptimisticLockException,org.springframework.orm.jpa.JpaOptimisticLockingFailureException} + +# tax group + +resilience4j.retry.instances.commandTaxGroupCreate.max-attempts=${FINERACT_COMMAND_TAX_GROUP_CREATE_RETRY_MAX_ATTEMPTS:3} +resilience4j.retry.instances.commandTaxGroupCreate.wait-duration=${FINERACT_COMMAND_TAX_GROUP_CREATE_RETRY_WAIT_DURATION:1s} +resilience4j.retry.instances.commandTaxGroupCreate.enable-exponential-backoff=${FINERACT_COMMAND_TAX_GROUP_CREATE_RETRY_ENABLE_EXPONENTIAL_BACKOFF:true} +resilience4j.retry.instances.commandTaxGroupCreate.exponential-backoff-multiplier=${FINERACT_COMMAND_TAX_GROUP_CREATE_RETRY_EXPONENTIAL_BACKOFF_MULTIPLIER:2} +resilience4j.retry.instances.commandTaxGroupCreate.retryExceptions=${FINERACT_COMMAND_TAX_GROUP_CREATE_RETRY_EXCEPTIONS:org.springframework.dao.ConcurrencyFailureException,org.eclipse.persistence.exceptions.OptimisticLockException,jakarta.persistence.OptimisticLockException,org.springframework.orm.jpa.JpaOptimisticLockingFailureException} + +resilience4j.retry.instances.commandTaxGroupUpdate.max-attempts=${FINERACT_COMMAND_TAX_GROUP_UPDATE_RETRY_MAX_ATTEMPTS:3} +resilience4j.retry.instances.commandTaxGroupUpdate.wait-duration=${FINERACT_COMMAND_TAX_GROUP_UPDATE_RETRY_WAIT_DURATION:1s} +resilience4j.retry.instances.commandTaxGroupUpdate.enable-exponential-backoff=${FINERACT_COMMAND_TAX_GROUP_UPDATE_RETRY_ENABLE_EXPONENTIAL_BACKOFF:true} +resilience4j.retry.instances.commandTaxGroupUpdate.exponential-backoff-multiplier=${FINERACT_COMMAND_TAX_GROUP_UPDATE_RETRY_EXPONENTIAL_BACKOFF_MULTIPLIER:2} +resilience4j.retry.instances.commandTaxGroupUpdate.retryExceptions=${FINERACT_COMMAND_TAX_GROUP_UPDATE_RETRY_EXCEPTIONS:org.springframework.dao.ConcurrencyFailureException,org.eclipse.persistence.exceptions.OptimisticLockException,jakarta.persistence.OptimisticLockException,org.springframework.orm.jpa.JpaOptimisticLockingFailureException} + # command fineract.command.enabled=true @@ -787,6 +815,7 @@ fineract.command.hooks.audit-error=${FINERACT_COMMAND_PROCESSORS_AUDIT_ERROR:tru fineract.command.hooks.servlet-header-pre=${FINERACT_COMMAND_PROCESSORS_SERVLET_HEADER_PRE:true} fineract.command.hooks.timestamp-pre=${FINERACT_COMMAND_PROCESSORS_TIMESTAMP_PRE:true} fineract.command.hooks.username-pre=${FINERACT_COMMAND_PROCESSORS_USERNAME_PRE:true} +fineract.command.hooks.validation-pre=${FINERACT_COMMAND_PROCESSORS_VALIDATION_PRE:false} # TODO: move to separate module # this is duplicated on purpose to keep fineract-command independent; once all modules are migrated we clean up fineract.command.idempotency-key-header-name=${FINERACT_IDEMPOTENCY_KEY_HEADER_NAME:Idempotency-Key} diff --git a/fineract-provider/src/test/resources/application-test.properties b/fineract-provider/src/test/resources/application-test.properties index d6235bd7610..f2f3e0cd04d 100644 --- a/fineract-provider/src/test/resources/application-test.properties +++ b/fineract-provider/src/test/resources/application-test.properties @@ -319,3 +319,4 @@ fineract.command.hooks.audit-error=true fineract.command.hooks.servlet-header-pre=true fineract.command.hooks.timestamp-pre=true fineract.command.hooks.username-pre=true +fineract.command.hooks.validation-pre=false diff --git a/fineract-tax/dependencies.gradle b/fineract-tax/dependencies.gradle index bd2a15867e5..048a0123a8d 100644 --- a/fineract-tax/dependencies.gradle +++ b/fineract-tax/dependencies.gradle @@ -25,6 +25,7 @@ dependencies { // implementation dependencies are directly used (compiled against) in src/main (and src/test) // implementation(project(path: ':fineract-core')) + implementation(project(path: ':fineract-command')) implementation( 'org.springframework.boot:spring-boot-starter-web', diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxComponentApiResource.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxComponentApiResource.java index 11e6fe2abd7..3df6073c47a 100644 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxComponentApiResource.java +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxComponentApiResource.java @@ -18,14 +18,11 @@ */ package org.apache.fineract.portfolio.tax.api; +import static java.util.Objects.requireNonNull; + import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.GET; @@ -36,91 +33,93 @@ import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; import java.util.List; +import java.util.function.Supplier; import lombok.RequiredArgsConstructor; -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.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.command.core.CommandDispatcher; +import org.apache.fineract.portfolio.tax.command.TaxComponentCreateCommand; +import org.apache.fineract.portfolio.tax.command.TaxComponentUpdateCommand; +import org.apache.fineract.portfolio.tax.data.TaxComponentCreateRequest; +import org.apache.fineract.portfolio.tax.data.TaxComponentCreateResponse; import org.apache.fineract.portfolio.tax.data.TaxComponentData; -import org.apache.fineract.portfolio.tax.request.TaxComponentRequest; -import org.apache.fineract.portfolio.tax.service.TaxReadPlatformService; +import org.apache.fineract.portfolio.tax.data.TaxComponentUpdateRequest; +import org.apache.fineract.portfolio.tax.data.TaxComponentUpdateResponse; +import org.apache.fineract.portfolio.tax.service.TaxReadService; import org.springframework.stereotype.Component; @Path("/v1/taxes/component") +@Consumes({ MediaType.APPLICATION_JSON }) +@Produces({ MediaType.APPLICATION_JSON }) @Component @Tag(name = "Tax Components", description = "This defines the Tax Components") @RequiredArgsConstructor public class TaxComponentApiResource { - private static final String RESOURCE_NAME_FOR_PERMISSIONS = "TAXCOMPONENT"; - - private final PlatformSecurityContext context; - private final TaxReadPlatformService readPlatformService; - private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; - private final DefaultToApiJsonSerializer toApiJsonSerializer; + private final TaxReadService readPlatformService; + private final CommandDispatcher dispatcher; @GET - @Produces({ MediaType.APPLICATION_JSON }) @Operation(summary = "List Tax Components", operationId = "retrieveAllTaxComponents", description = "List Tax Components") - @ApiResponses({ - @ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = TaxComponentApiResourceSwagger.GetTaxesComponentsResponse.class)))) }) public List retrieveAllTaxComponents() { - context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS); return readPlatformService.retrieveAllTaxComponents(); } @GET @Path("{taxComponentId}") - @Produces({ MediaType.APPLICATION_JSON }) @Operation(summary = "Retrieve Tax Component", operationId = "retrieveOneTaxComponent", description = "Retrieve Tax Component") - @ApiResponses({ - @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TaxComponentApiResourceSwagger.GetTaxesComponentsResponse.class))) }) public TaxComponentData retrieveTaxComponent( @PathParam("taxComponentId") @Parameter(description = "taxComponentId") final Long taxComponentId) { - context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS); return readPlatformService.retrieveTaxComponentData(taxComponentId); } @GET @Path("template") - @Produces({ MediaType.APPLICATION_JSON }) @Operation(summary = "Retrieve Tax Component Template", operationId = "retrieveTemplateTaxComponent") public TaxComponentData retrieveTemplate() { - context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS); return readPlatformService.retrieveTaxComponentTemplate(); } @POST - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - @Operation(summary = "Create a new Tax Component", operationId = "createTaxComponent", description = "Creates a new Tax Component\n\n" - + "Mandatory Fields: name, percentage\n\n" - + "Optional Fields: debitAccountType, debitAccountId, creditAccountType, creditAccountId, startDate") - @RequestBody(required = true, content = @Content(schema = @Schema(implementation = TaxComponentApiResourceSwagger.PostTaxesComponentsRequest.class))) - @ApiResponses({ - @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TaxComponentApiResourceSwagger.PostTaxesComponentsResponse.class))) }) - public CommandProcessingResult createTaxComponent(@Parameter(hidden = true) TaxComponentRequest taxComponentRequest) { - final CommandWrapper commandRequest = new CommandWrapperBuilder().createTaxComponent() - .withJson(toApiJsonSerializer.serialize(taxComponentRequest)).build(); - return commandsSourceWritePlatformService.logCommandSource(commandRequest); + @Operation(summary = "Create a new Tax Component", operationId = "createTaxComponent", description = """ + Creates a new Tax Component + + Mandatory Fields: + + - name + - percentage + + Optional Fields: + + - debitAccountType + - debitAccountId + - creditAccountType + - creditAccountId + - startDate""") + public TaxComponentCreateResponse createTaxComponent(@RequestBody(required = true) TaxComponentCreateRequest request) { + final var command = new TaxComponentCreateCommand(); + command.setPayload(request); + + final Supplier response = dispatcher.dispatch(command); + + return response.get(); } @PUT @Path("{taxComponentId}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - @Operation(summary = "Update Tax Component", operationId = "updateTaxComponent", description = "Updates Tax component. Debit and credit account details cannot be modified. All the future tax components would be replaced with the new percentage.") - @RequestBody(required = true, content = @Content(schema = @Schema(implementation = TaxComponentApiResourceSwagger.PutTaxesComponentsTaxComponentIdRequest.class))) - @ApiResponses({ - @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TaxComponentApiResourceSwagger.PutTaxesComponentsTaxComponentIdResponse.class))) }) - public CommandProcessingResult updateTaxCompoent( + @Operation(summary = "Update Tax Component", operationId = "updateTaxComponent", description = """ + Updates Tax component. Debit and credit account details cannot be modified. + All the future tax components would be replaced with the new percentage.""") + public TaxComponentUpdateResponse updateTaxCompoent( @PathParam("taxComponentId") @Parameter(description = "taxComponentId") final Long taxComponentId, - @Parameter(hidden = true) TaxComponentRequest taxComponentRequest) { - final CommandWrapper commandRequest = new CommandWrapperBuilder().updateTaxComponent(taxComponentId) - .withJson(toApiJsonSerializer.serialize(taxComponentRequest)).build(); - return commandsSourceWritePlatformService.logCommandSource(commandRequest); - } + @RequestBody(required = true) TaxComponentUpdateRequest request) { + requireNonNull(taxComponentId, "taxComponentId is required"); + + request.setId(taxComponentId); + final var command = new TaxComponentUpdateCommand(); + command.setPayload(request); + + final Supplier response = dispatcher.dispatch(command); + + return response.get(); + } } diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxComponentApiResourceSwagger.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxComponentApiResourceSwagger.java deleted file mode 100644 index 9b9bcc78eec..00000000000 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxComponentApiResourceSwagger.java +++ /dev/null @@ -1,151 +0,0 @@ -/** - * 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.tax.api; - -import io.swagger.v3.oas.annotations.media.Schema; -import java.time.LocalDate; -import java.util.Set; - -/** - * Created by Chirag Gupta on 12/20/17. - */ -final class TaxComponentApiResourceSwagger { - - private TaxComponentApiResourceSwagger() {} - - @Schema(description = "GetTaxesComponentsResponse") - public static final class GetTaxesComponentsResponse { - - private GetTaxesComponentsResponse() {} - - static final class GetTaxesComponentsCreditAccountType { - - private GetTaxesComponentsCreditAccountType() {} - - @Schema(example = "2") - public Integer id; - @Schema(example = "accountType.liability") - public String code; - @Schema(example = "LIABILITY") - public String description; - } - - static final class GetTaxesComponentsCreditAccount { - - private GetTaxesComponentsCreditAccount() {} - - @Schema(example = "4") - public Long id; - @Schema(example = "ACCOUNT_NAME_7BR9C") - public String name; - @Schema(example = "LIABILITY_PA1460364665046") - public String glCode; - } - - static final class GetTaxesComponentsHistories { - - private GetTaxesComponentsHistories() {} - } - - @Schema(example = "1") - public Long id; - @Schema(example = "tax component 1") - public String name; - @Schema(example = "10.000000") - public Float percentage; - public GetTaxesComponentsCreditAccountType creditAccountType; - public GetTaxesComponentsCreditAccount creditAccount; - @Schema(example = "[2016, 4, 11]") - public LocalDate startDate; - public Set taxComponentsHistories; - } - - @Schema(description = "PostTaxesComponentsRequest") - public static final class PostTaxesComponentsRequest { - - private PostTaxesComponentsRequest() {} - - @Schema(example = "tax component 1") - public String name; - @Schema(example = "10") - public Float percentage; - @Schema(example = "2") - public Integer debitAccountType; - @Schema(example = "4") - public Long debitAccountId; - @Schema(example = "4") - public Integer creditAccountType; - @Schema(example = "4") - public Long creditAccountId; - @Schema(example = "en") - public String locale; - @Schema(example = "dd MMMM yyyy") - public String dateFormat; - @Schema(example = "11 April 2016") - public String startDate; - } - - @Schema(description = "PostTaxesComponentsResponse") - public static final class PostTaxesComponentsResponse { - - private PostTaxesComponentsResponse() {} - - @Schema(example = "1") - public Long resourceId; - } - - @Schema(description = "PutTaxesComponentsTaxComponentIdRequest") - public static final class PutTaxesComponentsTaxComponentIdRequest { - - private PutTaxesComponentsTaxComponentIdRequest() {} - - @Schema(example = "tax component 2") - public String name; - @Schema(example = "15") - public Float percentage; - @Schema(example = "en") - public String locale; - @Schema(example = "dd MMMM yyyy") - public String dateFormat; - @Schema(example = "15 April 2016") - public String startDate; - } - - @Schema(description = "PutTaxesComponentsTaxComponentIdResponse") - public static final class PutTaxesComponentsTaxComponentIdResponse { - - private PutTaxesComponentsTaxComponentIdResponse() {} - - static final class PutTaxesComponentsChanges { - - private PutTaxesComponentsChanges() {} - - @Schema(example = "15") - public Float percentage; - @Schema(example = "tax component 2") - public String name; - @Schema(example = "[2016, 4, 15]") - public LocalDate startDate; - } - - @Schema(example = "1") - public Long resourceId; - public PutTaxesComponentsChanges changes; - } -} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxGroupApiResource.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxGroupApiResource.java index 4e72ae98bb3..2a7948cabb1 100644 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxGroupApiResource.java +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxGroupApiResource.java @@ -18,110 +18,110 @@ */ package org.apache.fineract.portfolio.tax.api; +import static java.util.Objects.requireNonNull; + import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; -import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.GET; import jakarta.ws.rs.POST; import jakarta.ws.rs.PUT; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.UriInfo; import java.util.List; +import java.util.function.Supplier; import lombok.RequiredArgsConstructor; -import org.apache.fineract.commands.domain.CommandWrapper; -import org.apache.fineract.commands.service.CommandWrapperBuilder; -import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService; -import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper; -import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; -import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings; -import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer; -import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.command.core.CommandDispatcher; +import org.apache.fineract.portfolio.tax.command.TaxGroupCreateCommand; +import org.apache.fineract.portfolio.tax.command.TaxGroupUpdateCommand; +import org.apache.fineract.portfolio.tax.data.TaxGroupCreateRequest; +import org.apache.fineract.portfolio.tax.data.TaxGroupCreateResponse; import org.apache.fineract.portfolio.tax.data.TaxGroupData; -import org.apache.fineract.portfolio.tax.request.TaxGroupRequest; -import org.apache.fineract.portfolio.tax.service.TaxReadPlatformService; +import org.apache.fineract.portfolio.tax.data.TaxGroupUpdateRequest; +import org.apache.fineract.portfolio.tax.data.TaxGroupUpdateResponse; +import org.apache.fineract.portfolio.tax.service.TaxReadService; import org.springframework.stereotype.Component; @Path("/v1/taxes/group") +@Consumes({ MediaType.APPLICATION_JSON }) +@Produces({ MediaType.APPLICATION_JSON }) @Component @Tag(name = "Tax Group", description = "This defines the Tax Group") @RequiredArgsConstructor public class TaxGroupApiResource { - private static final String RESOURCE_NAME_FOR_PERMISSIONS = "TAXGROUP"; - - private final PlatformSecurityContext context; - private final TaxReadPlatformService readPlatformService; - private final DefaultToApiJsonSerializer toApiJsonSerializer; - private final ApiRequestParameterHelper apiRequestParameterHelper; - private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; + private final TaxReadService readPlatformService; + private final CommandDispatcher dispatcher; @GET - @Produces({ MediaType.APPLICATION_JSON }) @Operation(summary = "List Tax Group", operationId = "retrieveAllTaxGroups", description = "List Tax Group") - @ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = TaxGroupApiResourceSwagger.GetTaxesGroupResponse.class)))) public List retrieveAllTaxGroups() { - context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS); return readPlatformService.retrieveAllTaxGroups(); } @GET @Path("{taxGroupId}") - @Produces({ MediaType.APPLICATION_JSON }) @Operation(summary = "Retrieve Tax Group", operationId = "retrieveOneTaxGroup", description = "Retrieve Tax Group") - @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TaxGroupApiResourceSwagger.GetTaxesGroupResponse.class))) public TaxGroupData retrieveTaxGroup(@PathParam("taxGroupId") @Parameter(description = "taxGroupId") final Long taxGroupId, - @Context final UriInfo uriInfo) { - context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS); - final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); - return settings.isTemplate() ? readPlatformService.retrieveTaxGroupWithTemplate(taxGroupId) + @QueryParam("template") @DefaultValue("false") Boolean template) { + return Boolean.TRUE.equals(template) ? readPlatformService.retrieveTaxGroupWithTemplate(taxGroupId) : readPlatformService.retrieveTaxGroupData(taxGroupId); } @GET @Path("template") - @Produces({ MediaType.APPLICATION_JSON }) @Operation(summary = "Retrieve Tax Group Template", operationId = "retrieveTemplateTaxGroup") public TaxGroupData retrieveTemplate() { - context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS); return readPlatformService.retrieveTaxGroupTemplate(); } @POST - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - @Operation(summary = "Create a new Tax Group", operationId = "createTaxGroup", description = "Create a new Tax Group\n" - + "Mandatory Fields: name and taxComponents\n" + "Mandatory Fields in taxComponents: taxComponentId\n" - + "Optional Fields in taxComponents: id, startDate and endDate") - @RequestBody(required = true, content = @Content(schema = @Schema(implementation = TaxGroupApiResourceSwagger.PostTaxesGroupRequest.class))) - @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TaxGroupApiResourceSwagger.PostTaxesGroupResponse.class))) - public CommandProcessingResult createTaxGroup(@Parameter(hidden = true) TaxGroupRequest taxGroupRequest) { - final CommandWrapper commandRequest = new CommandWrapperBuilder().createTaxGroup() - .withJson(toApiJsonSerializer.serialize(taxGroupRequest)).build(); - return commandsSourceWritePlatformService.logCommandSource(commandRequest); + @Operation(summary = "Create a new Tax Group", operationId = "createTaxGroup", description = """ + Create a new Tax Group + + Mandatory Fields: + + - name + - taxComponents + + Mandatory Fields in taxComponents: + + - taxComponentId + + Optional Fields in taxComponents: + + - id + - startDate + - endDate""") + public TaxGroupCreateResponse createTaxGroup(@RequestBody(required = true) TaxGroupCreateRequest request) { + final var command = new TaxGroupCreateCommand(); + command.setPayload(request); + + final Supplier response = dispatcher.dispatch(command); + + return response.get(); } @PUT @Path("{taxGroupId}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) @Operation(summary = "Update Tax Group", operationId = "updateTaxGroup", description = "Updates Tax Group. Only end date can be up-datable and can insert new tax components.") - @RequestBody(required = true, content = @Content(schema = @Schema(implementation = TaxGroupApiResourceSwagger.PutTaxesGroupTaxGroupIdRequest.class))) - @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TaxGroupApiResourceSwagger.PutTaxesGroupTaxGroupIdResponse.class))) - public CommandProcessingResult updateTaxGroup(@PathParam("taxGroupId") @Parameter(description = "taxGroupId") final Long taxGroupId, - @Parameter(hidden = true) TaxGroupRequest taxGroupRequest) { - final CommandWrapper commandRequest = new CommandWrapperBuilder().updateTaxGroup(taxGroupId) - .withJson(toApiJsonSerializer.serialize(taxGroupRequest)).build(); - return commandsSourceWritePlatformService.logCommandSource(commandRequest); - } + public TaxGroupUpdateResponse updateTaxGroup(@PathParam("taxGroupId") @Parameter(description = "taxGroupId") final Long taxGroupId, + @RequestBody(required = true) TaxGroupUpdateRequest request) { + requireNonNull(taxGroupId, "taxGroupId is required"); + + request.setId(taxGroupId); + final var command = new TaxGroupUpdateCommand(); + command.setPayload(request); + + final Supplier response = dispatcher.dispatch(command); + + return response.get(); + } } diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxGroupApiResourceSwagger.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxGroupApiResourceSwagger.java deleted file mode 100644 index fbd67ae75d6..00000000000 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/api/TaxGroupApiResourceSwagger.java +++ /dev/null @@ -1,155 +0,0 @@ -/** - * 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.tax.api; - -import io.swagger.v3.oas.annotations.media.Schema; -import java.time.LocalDate; -import java.util.List; -import java.util.Set; - -/** - * Created by Chirag Gupta on 12/14/17. - */ -final class TaxGroupApiResourceSwagger { - - private TaxGroupApiResourceSwagger() {} - - @Schema(description = "GetTaxesGroupResponse") - public static final class GetTaxesGroupResponse { - - private GetTaxesGroupResponse() {} - - static final class GetTaxesGroupTaxAssociations { - - private GetTaxesGroupTaxAssociations() {} - - static final class GetTaxesGroupTaxComponent { - - private GetTaxesGroupTaxComponent() {} - - @Schema(example = "7") - public Long id; - @Schema(example = "tax component 2") - public String name; - } - - @Schema(example = "7") - public Long id; - public GetTaxesGroupTaxComponent taxComponent; - @Schema(example = "[2016, 4, 11]") - public LocalDate startDate; - } - - @Schema(example = "7") - public Long id; - @Schema(example = "tax group 1") - public String name; - public Set taxAssociations; - } - - @Schema(description = "PostTaxesGroupRequest") - public static final class PostTaxesGroupRequest { - - private PostTaxesGroupRequest() {} - - static final class PostTaxesGroupTaxComponents { - - private PostTaxesGroupTaxComponents() {} - - @Schema(example = "7") - public Long taxComponentId; - @Schema(example = "11 April 2016") - public String startDate; - } - - @Schema(example = "tax group 1") - public String name; - @Schema(example = "en") - public String locale; - public Set taxComponents; - @Schema(example = "dd MMMM yyyy") - public String dateFormat; - } - - @Schema(description = "PostTaxesGroupResponse") - public static final class PostTaxesGroupResponse { - - private PostTaxesGroupResponse() {} - - @Schema(example = "1") - public Long resourceId; - } - - @Schema(description = "PutTaxesGroupTaxGroupIdRequest") - public static final class PutTaxesGroupTaxGroupIdRequest { - - private PutTaxesGroupTaxGroupIdRequest() {} - - static final class PutTaxesGroupTaxComponents { - - private PutTaxesGroupTaxComponents() {} - - @Schema(example = "7") - public Long id; - @Schema(example = "7") - public Long taxComponentId; - @Schema(example = "22 April 2016") - public String endDate; - } - - @Schema(example = "tax group 2") - public String name; - @Schema(example = "en") - public String locale; - public Set taxComponents; - @Schema(example = "dd MMMM yyyy") - public String dateFormat; - } - - @Schema(description = "PutTaxesGroupTaxGroupIdResponse") - public static final class PutTaxesGroupTaxGroupIdResponse { - - private PutTaxesGroupTaxGroupIdResponse() {} - - static final class PutTaxesGroupChanges { - - private PutTaxesGroupChanges() {} - - static final class PutTaxesGroupModifiedComponents { - - private PutTaxesGroupModifiedComponents() {} - - @Schema(example = "Apr 22, 2016 12:00:00 AM") - public String endDate; - @Schema(example = "7") - public Long taxComponentId; - } - - @Schema(example = "[6]") - public List addComponents; - public Set modifiedComponents; - @Schema(example = "tax group 2") - public String name; - } - - @Schema(example = "7") - public Long resourceId; - public PutTaxesGroupChanges changes; - } -} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/command/TaxComponentCreateCommand.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/command/TaxComponentCreateCommand.java new file mode 100644 index 00000000000..f5f8a3a5e4d --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/command/TaxComponentCreateCommand.java @@ -0,0 +1,28 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.tax.command; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.fineract.command.core.Command; +import org.apache.fineract.portfolio.tax.data.TaxComponentCreateRequest; + +@Data +@EqualsAndHashCode(callSuper = true) +public class TaxComponentCreateCommand extends Command {} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/command/TaxComponentUpdateCommand.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/command/TaxComponentUpdateCommand.java new file mode 100644 index 00000000000..575e6931084 --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/command/TaxComponentUpdateCommand.java @@ -0,0 +1,28 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.tax.command; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.fineract.command.core.Command; +import org.apache.fineract.portfolio.tax.data.TaxComponentUpdateRequest; + +@Data +@EqualsAndHashCode(callSuper = true) +public class TaxComponentUpdateCommand extends Command {} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/command/TaxGroupCreateCommand.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/command/TaxGroupCreateCommand.java new file mode 100644 index 00000000000..751dc41645a --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/command/TaxGroupCreateCommand.java @@ -0,0 +1,28 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.tax.command; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.fineract.command.core.Command; +import org.apache.fineract.portfolio.tax.data.TaxGroupCreateRequest; + +@Data +@EqualsAndHashCode(callSuper = true) +public class TaxGroupCreateCommand extends Command {} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/command/TaxGroupUpdateCommand.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/command/TaxGroupUpdateCommand.java new file mode 100644 index 00000000000..8fbb3ed27e0 --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/command/TaxGroupUpdateCommand.java @@ -0,0 +1,28 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.tax.command; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.apache.fineract.command.core.Command; +import org.apache.fineract.portfolio.tax.data.TaxGroupUpdateRequest; + +@Data +@EqualsAndHashCode(callSuper = true) +public class TaxGroupUpdateCommand extends Command {} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentCreateRequest.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentCreateRequest.java new file mode 100644 index 00000000000..83c422d5443 --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentCreateRequest.java @@ -0,0 +1,83 @@ +/** + * 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.tax.data; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.DecimalMax; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.FieldNameConstants; + +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@FieldNameConstants +public class TaxComponentCreateRequest implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @NotBlank(message = "{org.apache.fineract.portfolio.tax.component.name.not-empty}") + private String name; + @NotNull(message = "{org.apache.fineract.portfolio.tax.component.percentage.not-empty}") + @Positive(message = "{org.apache.fineract.portfolio.tax.component.percentage.positive}") + @DecimalMax(value = "100.00", message = "{org.apache.fineract.portfolio.tax.component.percentage.max}") + private BigDecimal percentage; + @Min(value = 1, message = "{org.apache.fineract.portfolio.tax.component.debit-account-type.min}") + @Max(value = 5, message = "{org.apache.fineract.portfolio.tax.component.debit-account-type.max}") + private Integer debitAccountType; + @Positive(message = "{org.apache.fineract.portfolio.tax.component.debit-account-id.positive}") + private Long debitAccountId; + @Min(value = 1, message = "{org.apache.fineract.portfolio.tax.component.credit-account-type.min}") + @Max(value = 5, message = "{org.apache.fineract.portfolio.tax.component.credit-account-type.max}") + private Integer creditAccountType; + @Positive(message = "{org.apache.fineract.portfolio.tax.component.credit-account-id.positive}") + private Long creditAccountId; + private String startDate; + private String dateFormat; + private String locale; + + @JsonIgnore + @AssertTrue(message = "{org.apache.fineract.portfolio.tax.component.debit-account.valid}") + public boolean isDebitAccountPairValid() { + boolean typePresent = debitAccountType != null; + boolean idPresent = debitAccountId != null; + return typePresent == idPresent; // both or neither + } + + @JsonIgnore + @AssertTrue(message = "{org.apache.fineract.portfolio.tax.component.debit-account.valid}") + public boolean isCreditAccountPairValid() { + boolean typePresent = creditAccountType != null; + boolean idPresent = creditAccountId != null; + return typePresent == idPresent; + } +} diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/request/TaxGroupRequest.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentCreateResponse.java similarity index 75% rename from fineract-core/src/main/java/org/apache/fineract/portfolio/tax/request/TaxGroupRequest.java rename to fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentCreateResponse.java index 87dc00d3f85..aec2dbbb7da 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/request/TaxGroupRequest.java +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentCreateResponse.java @@ -16,25 +16,25 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.fineract.portfolio.tax.request; +package org.apache.fineract.portfolio.tax.data; import java.io.Serial; import java.io.Serializable; -import java.util.Set; -import lombok.Getter; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; import lombok.NoArgsConstructor; -import lombok.Setter; +import lombok.experimental.FieldNameConstants; -@Setter -@Getter +@Builder +@Data @NoArgsConstructor -public class TaxGroupRequest implements Serializable { +@AllArgsConstructor +@FieldNameConstants +public class TaxComponentCreateResponse implements Serializable { @Serial private static final long serialVersionUID = 1L; - private String name; - private String locale; - private Set taxComponents; - private String dateFormat; + private Long resourceId; } diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentUpdateRequest.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentUpdateRequest.java new file mode 100644 index 00000000000..f5c4320d842 --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentUpdateRequest.java @@ -0,0 +1,78 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.tax.data; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.DecimalMax; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.FieldNameConstants; +import org.apache.fineract.infrastructure.core.service.DateUtils; + +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@FieldNameConstants +public class TaxComponentUpdateRequest implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + private Long id; + @NotBlank(message = "{org.apache.fineract.portfolio.tax.component.name.not-empty}") + private String name; + @NotNull(message = "{org.apache.fineract.portfolio.tax.component.percentage.not-empty}") + @Positive(message = "{org.apache.fineract.portfolio.tax.component.percentage.positive}") + @DecimalMax(value = "100.00", message = "{org.apache.fineract.portfolio.tax.component.percentage.max}") + private BigDecimal percentage; + private String startDate; + private String dateFormat; + private String locale; + + @JsonIgnore + @AssertTrue(message = "org.apache.fineract.portfolio.tax.component.start-date.valid") + public boolean isStartDateValid() { + if (startDate == null) { + return true; // optional field + } + if (dateFormat == null) { + return false; // need format to parse + } + try { + var formatter = DateTimeFormatter.ofPattern(dateFormat); + var parsedDate = LocalDate.parse(startDate, formatter); + return parsedDate.isAfter(DateUtils.getBusinessLocalDate()); // strictly after + } catch (DateTimeParseException e) { + return false; + } + } +} diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/request/TaxComponentRequest.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentUpdateResponse.java similarity index 62% rename from fineract-core/src/main/java/org/apache/fineract/portfolio/tax/request/TaxComponentRequest.java rename to fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentUpdateResponse.java index 1af6b2f0a4f..e961b75b080 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/request/TaxComponentRequest.java +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxComponentUpdateResponse.java @@ -16,32 +16,27 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.fineract.portfolio.tax.request; +package org.apache.fineract.portfolio.tax.data; -import com.fasterxml.jackson.annotation.JsonInclude; import java.io.Serial; import java.io.Serializable; -import java.math.BigDecimal; -import lombok.Getter; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; import lombok.NoArgsConstructor; -import lombok.Setter; +import lombok.experimental.FieldNameConstants; -@Setter -@Getter +@Builder +@Data @NoArgsConstructor -@JsonInclude(JsonInclude.Include.NON_NULL) -public class TaxComponentRequest implements Serializable { +@AllArgsConstructor +@FieldNameConstants +public class TaxComponentUpdateResponse implements Serializable { @Serial private static final long serialVersionUID = 1L; - private String name; - private BigDecimal percentage; - private Integer debitAccountType; - private Long debitAccountId; - private Integer creditAccountType; - private Long creditAccountId; - private String startDate; - private String dateFormat; - private String locale; + private Long resourceId; + private Map changes; } diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/CreateTaxComponentCommandHandler.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupComponentData.java similarity index 50% rename from fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/CreateTaxComponentCommandHandler.java rename to fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupComponentData.java index 96b045767ff..b0b0c92dc8d 100644 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/CreateTaxComponentCommandHandler.java +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupComponentData.java @@ -16,26 +16,37 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.fineract.portfolio.tax.handler; +package org.apache.fineract.portfolio.tax.data; +import jakarta.validation.constraints.AssertTrue; +import java.io.Serial; +import java.io.Serializable; import lombok.AllArgsConstructor; -import org.apache.fineract.commands.annotation.CommandType; -import org.apache.fineract.commands.handler.NewCommandSourceHandler; -import org.apache.fineract.infrastructure.core.api.JsonCommand; -import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; -import org.apache.fineract.portfolio.tax.service.TaxWritePlatformService; -import org.springframework.stereotype.Service; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.FieldNameConstants; -@Service +@Builder +@Data +@NoArgsConstructor @AllArgsConstructor -@CommandType(entity = "TAXCOMPONENT", action = "CREATE") -public class CreateTaxComponentCommandHandler implements NewCommandSourceHandler { +@FieldNameConstants +public class TaxGroupComponentData implements Serializable { - private final TaxWritePlatformService taxWritePlatformService; + @Serial + private static final long serialVersionUID = 1L; - @Override - public CommandProcessingResult processCommand(JsonCommand jsonCommand) { - return this.taxWritePlatformService.createTaxComponent(jsonCommand); - } + private Long id; + private Long taxComponentId; + private String startDate; + private String endDate; + @AssertTrue(message = "{org.apache.fineract.portfolio.tax.group.tax-component-id.valid}") + public boolean isTaxComponentIdValid() { + if (id == null) { + return taxComponentId != null && taxComponentId > 0; + } + return taxComponentId == null || taxComponentId > 0; + } } diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupCreateRequest.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupCreateRequest.java new file mode 100644 index 00000000000..d66fbff5ef4 --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupCreateRequest.java @@ -0,0 +1,50 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.tax.data; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import java.io.Serial; +import java.io.Serializable; +import java.util.Set; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.FieldNameConstants; + +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@FieldNameConstants +public class TaxGroupCreateRequest implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @NotBlank(message = "{org.apache.fineract.portfolio.tax.group.name.not-empty}") + private String name; + private String locale; + @NotEmpty(message = "{org.apache.fineract.portfolio.tax.group.tax-components.not-empty}") + @Valid + private Set taxComponents; + private String dateFormat; +} diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/request/TaxGroupComponent.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupCreateResponse.java similarity index 75% rename from fineract-core/src/main/java/org/apache/fineract/portfolio/tax/request/TaxGroupComponent.java rename to fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupCreateResponse.java index 258b719ffe0..1edb5e218bc 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/tax/request/TaxGroupComponent.java +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupCreateResponse.java @@ -16,22 +16,25 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.fineract.portfolio.tax.request; +package org.apache.fineract.portfolio.tax.data; import java.io.Serial; import java.io.Serializable; -import lombok.Getter; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; import lombok.NoArgsConstructor; -import lombok.Setter; +import lombok.experimental.FieldNameConstants; -@Setter -@Getter +@Builder +@Data @NoArgsConstructor -public class TaxGroupComponent implements Serializable { +@AllArgsConstructor +@FieldNameConstants +public class TaxGroupCreateResponse implements Serializable { @Serial private static final long serialVersionUID = 1L; - private Long taxComponentId; - private String startDate; + private Long resourceId; } diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupUpdateRequest.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupUpdateRequest.java new file mode 100644 index 00000000000..efee5ad9d54 --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupUpdateRequest.java @@ -0,0 +1,103 @@ +/** + * 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.tax.data; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.validation.Valid; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.NotBlank; +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.Set; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.FieldNameConstants; +import org.apache.fineract.infrastructure.core.service.DateUtils; + +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@FieldNameConstants +public class TaxGroupUpdateRequest implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + private Long id; + @NotBlank(message = "{org.apache.fineract.portfolio.tax.group.name.not-empty}") + private String name; + private String locale; + @Valid + private Set taxComponents; + private String dateFormat; + + @JsonIgnore + @AssertTrue(message = "org.apache.fineract.portfolio.tax.group.component-end-date.valid") + public boolean isComponentsEndDateValid() { + if (taxComponents == null || dateFormat == null) { + return true; + } + + DateTimeFormatter formatter; + + try { + formatter = DateTimeFormatter.ofPattern(dateFormat); + } catch (IllegalArgumentException e) { + return false; + } + + for (TaxGroupComponentData component : taxComponents) { + if (component.getEndDate() != null) { + try { + var parsed = LocalDate.parse(component.getEndDate(), formatter); + + if (!parsed.isAfter(DateUtils.getBusinessLocalDate())) { + return false; + } + } catch (DateTimeParseException e) { + return false; + } + } + } + + return true; + } + + @JsonIgnore + @AssertTrue(message = "org.apache.fineract.portfolio.tax.group.component-start-date.valid") + public boolean isComponentsStartEndDateMutuallyExclusive() { + if (taxComponents == null) { + return true; + } + + for (TaxGroupComponentData component : taxComponents) { + if (component.getStartDate() != null && component.getEndDate() != null) { + return false; + } + } + + return true; + } +} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupUpdateResponse.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupUpdateResponse.java new file mode 100644 index 00000000000..e74da2b2fe0 --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/data/TaxGroupUpdateResponse.java @@ -0,0 +1,42 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.tax.data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.FieldNameConstants; + +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@FieldNameConstants +public class TaxGroupUpdateResponse implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + private Long resourceId; + private Map changes; +} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponent.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponent.java index b15a5f8933f..081ba41d0b3 100644 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponent.java +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponent.java @@ -28,25 +28,24 @@ import jakarta.persistence.Table; import java.math.BigDecimal; import java.time.LocalDate; -import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; import lombok.Getter; +import lombok.Setter; +import lombok.experimental.FieldNameConstants; import org.apache.commons.lang3.StringUtils; import org.apache.fineract.accounting.glaccount.domain.GLAccount; -import org.apache.fineract.accounting.glaccount.domain.GLAccountType; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom; import org.apache.fineract.infrastructure.core.service.DateUtils; -import org.apache.fineract.portfolio.tax.api.TaxApiConstants; @Entity @Getter +@Setter @Table(name = "m_tax_component") +@FieldNameConstants public class TaxComponent extends AbstractAuditableCustom { @Column(name = "name", length = 100) @@ -79,48 +78,27 @@ public class TaxComponent extends AbstractAuditableCustom { @OneToMany(cascade = CascadeType.DETACH, mappedBy = "taxComponent", orphanRemoval = false, fetch = FetchType.EAGER) private Set taxGroupMappings = new HashSet<>(); - protected TaxComponent() { - - } - - private TaxComponent(final String name, final BigDecimal percentage, final GLAccountType debitAccountType, final GLAccount debitAccount, - final GLAccountType creditAccountType, final GLAccount creditAccount, final LocalDate startDate) { - this.name = name; - this.percentage = percentage; - if (debitAccountType != null) { - this.debitAccountType = debitAccountType.getValue(); - } - this.debitAccount = debitAccount; - if (creditAccountType != null) { - this.creditAccountType = creditAccountType.getValue(); - } - this.creditAccount = creditAccount; - this.startDate = startDate; - } - - public static TaxComponent createTaxComponent(final String name, final BigDecimal percentage, final GLAccountType debitAccountType, - final GLAccount debitAccount, final GLAccountType creditAccountType, final GLAccount creditAccount, final LocalDate startDate) { - return new TaxComponent(name, percentage, debitAccountType, debitAccount, creditAccountType, creditAccount, startDate); - } - public Map update(final JsonCommand command) { final Map changes = new HashMap<>(); - if (command.isChangeInStringParameterNamed(TaxApiConstants.nameParamName, this.name)) { - final String newValue = command.stringValueOfParameterNamed(TaxApiConstants.nameParamName); - changes.put(TaxApiConstants.nameParamName, newValue); + if (command.isChangeInStringParameterNamed(Fields.name, this.name)) { + final String newValue = command.stringValueOfParameterNamed(Fields.name); + changes.put(Fields.name, newValue); this.name = StringUtils.defaultIfEmpty(newValue, null); } - if (command.isChangeInBigDecimalParameterNamed(TaxApiConstants.percentageParamName, this.percentage)) { - final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(TaxApiConstants.percentageParamName); - changes.put(TaxApiConstants.percentageParamName, newValue); + if (command.isChangeInBigDecimalParameterNamed(Fields.percentage, this.percentage)) { + final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(Fields.percentage); + changes.put(Fields.percentage, newValue); LocalDate oldStartDate = this.startDate; updateStartDate(command, changes, true); LocalDate newStartDate = this.startDate; - TaxComponentHistory history = TaxComponentHistory.createTaxComponentHistory(this.percentage, oldStartDate, newStartDate); + TaxComponentHistory history = new TaxComponentHistory(); + history.setPercentage(this.percentage); + history.setStartDate(oldStartDate); + history.setStartDate(newStartDate); this.taxComponentHistories.add(history); this.percentage = newValue; @@ -131,78 +109,35 @@ public Map update(final JsonCommand command) { private void updateStartDate(final JsonCommand command, final Map changes, boolean setAsCurrentDate) { LocalDate startDate = DateUtils.getBusinessLocalDate(); - if (command.parameterExists(TaxApiConstants.startDateParamName)) { - LocalDate startDateFromUI = command.localDateValueOfParameterNamed(TaxApiConstants.startDateParamName); + if (command.parameterExists(Fields.startDate)) { + LocalDate startDateFromUI = command.localDateValueOfParameterNamed(Fields.startDate); if (startDateFromUI != null) { startDate = startDateFromUI; } this.startDate = startDate; - changes.put(TaxApiConstants.startDateParamName, startDate); + changes.put(Fields.startDate, startDate); } else if (setAsCurrentDate) { - changes.put(TaxApiConstants.startDateParamName, startDate); + changes.put(Fields.startDate, startDate); this.startDate = startDate; } } - public BigDecimal getPercentage() { - return this.percentage; - } - - public LocalDate startDate() { - return this.startDate; - } - public BigDecimal getApplicablePercentage(final LocalDate date) { - BigDecimal percentage = null; - if (occursOnDayFrom(date)) { - percentage = getPercentage(); + if (DateUtils.isAfter(date, startDate)) { + return getPercentage(); } else { - for (TaxComponentHistory componentHistory : taxComponentHistories) { - if (componentHistory.occursOnDayFromAndUpToAndIncluding(date)) { - percentage = componentHistory.getPercentage(); - break; + for (var componentHistory : taxComponentHistories) { + if (occursOnDayFromAndUpToAndIncluding(componentHistory.getStartDate(), componentHistory.getEndDate(), date)) { + return componentHistory.getPercentage(); } } } - return percentage; - } - - private boolean occursOnDayFrom(final LocalDate target) { - return DateUtils.isAfter(target, startDate()); - } - - public Set getTaxComponentHistories() { - return this.taxComponentHistories; - } - - public Set getTaxGroupMappings() { - return this.taxGroupMappings; - } - - public Collection allStartDates() { - List dates = new ArrayList<>(); - dates.add(startDate()); - for (TaxComponentHistory componentHistory : taxComponentHistories) { - dates.add(componentHistory.startDate()); - } - - return dates; - } - - public Integer getDebitAccountType() { - return this.debitAccountType; - } - - public GLAccount getDebitAccount() { - return this.debitAccount; - } - public Integer getCreditAccountType() { - return this.creditAccountType; + return null; } - public GLAccount getCreditAccount() { - return this.creditAccount; + boolean occursOnDayFromAndUpToAndIncluding(final LocalDate start, final LocalDate end, final LocalDate target) { + return DateUtils.isAfter(target, start) && (end == null || !DateUtils.isAfter(target, end)); } } diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponentHistory.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponentHistory.java index 5330fa14c8e..042bf1680b3 100644 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponentHistory.java +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxComponentHistory.java @@ -23,10 +23,13 @@ import jakarta.persistence.Table; import java.math.BigDecimal; import java.time.LocalDate; +import lombok.Getter; +import lombok.Setter; import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom; -import org.apache.fineract.infrastructure.core.service.DateUtils; @Entity +@Getter +@Setter @Table(name = "m_tax_component_history") public class TaxComponentHistory extends AbstractAuditableCustom { @@ -38,36 +41,4 @@ public class TaxComponentHistory extends AbstractAuditableCustom { @Column(name = "end_date", nullable = false) private LocalDate endDate; - - protected TaxComponentHistory() { - - } - - private TaxComponentHistory(final BigDecimal percentage, final LocalDate startDate, final LocalDate endDate) { - this.percentage = percentage; - this.startDate = startDate; - this.endDate = endDate; - } - - public static TaxComponentHistory createTaxComponentHistory(final BigDecimal percentage, final LocalDate startDate, - final LocalDate endDate) { - return new TaxComponentHistory(percentage, startDate, endDate); - } - - public LocalDate startDate() { - return this.startDate; - } - - public LocalDate endDate() { - return this.endDate; - } - - public boolean occursOnDayFromAndUpToAndIncluding(final LocalDate target) { - return DateUtils.isAfter(target, startDate()) && (endDate == null || !DateUtils.isAfter(target, endDate())); - } - - public BigDecimal getPercentage() { - return this.percentage; - } - } diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroup.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroup.java index b03ceae25ad..e9532c88583 100644 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroup.java +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroup.java @@ -24,20 +24,20 @@ import jakarta.persistence.FetchType; import jakarta.persistence.OneToMany; import jakarta.persistence.Table; -import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; -import java.util.List; -import java.util.Map; import java.util.Set; -import org.apache.commons.lang3.StringUtils; -import org.apache.fineract.infrastructure.core.api.JsonCommand; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.Accessors; import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom; -import org.apache.fineract.portfolio.tax.api.TaxApiConstants; -import org.apache.fineract.portfolio.tax.exception.TaxMappingNotFoundException; @Entity @Table(name = "m_tax_group") +@Getter +@Setter +@NoArgsConstructor +@Accessors(chain = true) public class TaxGroup extends AbstractAuditableCustom { @Column(name = "name", length = 100) @@ -45,71 +45,4 @@ public class TaxGroup extends AbstractAuditableCustom { @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "taxGroup") private Set taxGroupMappings = new HashSet<>(); - - protected TaxGroup() { - - } - - private TaxGroup(final String name, final Set taxGroupMappings) { - this.name = name; - this.taxGroupMappings = taxGroupMappings; - taxGroupMappings.forEach(m -> m.setTaxGroup(this)); - } - - public static TaxGroup createTaxGroup(final String name, final Set taxGroupMappings) { - return new TaxGroup(name, taxGroupMappings); - } - - public Map update(final JsonCommand command, final Set taxGroupMappings) { - final Map changes = new HashMap<>(); - - if (command.isChangeInStringParameterNamed(TaxApiConstants.nameParamName, this.name)) { - final String newValue = command.stringValueOfParameterNamed(TaxApiConstants.nameParamName); - changes.put(TaxApiConstants.nameParamName, newValue); - this.name = StringUtils.defaultIfEmpty(newValue, null); - } - - List taxComponentList = new ArrayList<>(); - final List> modifications = new ArrayList<>(); - - for (TaxGroupMappings groupMappings : taxGroupMappings) { - TaxGroupMappings mappings = findOneBy(groupMappings); - if (mappings == null) { - this.taxGroupMappings.add(groupMappings); - taxComponentList.add(groupMappings.getTaxComponent().getId()); - } else { - mappings.update(groupMappings.getEndDate(), modifications); - } - } - - if (!taxComponentList.isEmpty()) { - changes.put("addComponents", taxComponentList); - } - if (!modifications.isEmpty()) { - changes.put("modifiedComponents", modifications); - } - - return changes; - } - - public TaxGroupMappings findOneBy(final TaxGroupMappings groupMapping) { - if (groupMapping.getId() != null) { - for (TaxGroupMappings groupMappings : this.taxGroupMappings) { - if (groupMappings.getId().equals(groupMapping.getId())) { - return groupMappings; - } - } - throw new TaxMappingNotFoundException(groupMapping.getId()); - } - return null; - } - - public Set getTaxGroupMappings() { - return this.taxGroupMappings; - } - - public String getName() { - return this.name; - } - } diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroupMappings.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroupMappings.java index 181d681ccba..a2c1d768561 100644 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroupMappings.java +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroupMappings.java @@ -24,17 +24,19 @@ import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; import java.time.LocalDate; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.Accessors; import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom; import org.apache.fineract.infrastructure.core.service.DateUtils; -import org.apache.fineract.portfolio.tax.api.TaxApiConstants; @Entity -@Getter @Table(name = "m_tax_group_mappings") +@Getter +@Setter +@NoArgsConstructor +@Accessors(chain = true) public class TaxGroupMappings extends AbstractAuditableCustom { @ManyToOne @@ -51,63 +53,7 @@ public class TaxGroupMappings extends AbstractAuditableCustom { @Column(name = "end_date", nullable = true) private LocalDate endDate; - protected TaxGroupMappings() {} - - private TaxGroupMappings(final TaxComponent taxComponent, final LocalDate startDate, final LocalDate endDate) { - this.taxComponent = taxComponent; - this.startDate = startDate; - this.endDate = endDate; - } - - public static TaxGroupMappings createTaxGroupMappings(final TaxComponent taxComponent, final LocalDate startDate) { - final LocalDate endDate = null; - return new TaxGroupMappings(taxComponent, startDate, endDate); - - } - - public static TaxGroupMappings createTaxGroupMappings(final Long id, final TaxComponent taxComponent, final LocalDate endDate) { - final LocalDate startDate = null; - TaxGroupMappings groupMappings = new TaxGroupMappings(taxComponent, startDate, endDate); - groupMappings.setId(id); - return groupMappings; - - } - - public void update(final LocalDate endDate, final List> changes) { - if (endDate != null && this.endDate == null) { - this.endDate = endDate; - Map map = new HashMap<>(2); - map.put(TaxApiConstants.endDateParamName, endDate); - map.put(TaxApiConstants.taxComponentIdParamName, this.getTaxComponent().getId()); - changes.add(map); - } - } - public boolean occursOnDayFromAndUpToAndIncluding(final LocalDate target) { - return DateUtils.isAfter(target, startDate()) && (endDate == null || !DateUtils.isAfter(target, endDate())); - } - - public TaxComponent getTaxComponent() { - return this.taxComponent; - } - - public LocalDate getEndDate() { - return this.endDate; - } - - public LocalDate startDate() { - return this.startDate; - } - - public LocalDate endDate() { - return this.endDate; - } - - public TaxGroup getTaxGroup() { - return taxGroup; - } - - public void setTaxGroup(TaxGroup taxGroup) { - this.taxGroup = taxGroup; + return DateUtils.isAfter(target, startDate) && (endDate == null || !DateUtils.isAfter(target, endDate)); } } diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroupRepositoryWrapper.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroupRepositoryWrapper.java index 745e7f2ec53..ef697aff099 100644 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroupRepositoryWrapper.java +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/domain/TaxGroupRepositoryWrapper.java @@ -18,20 +18,20 @@ */ package org.apache.fineract.portfolio.tax.domain; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.apache.fineract.portfolio.tax.exception.TaxGroupNotFoundException; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +@Slf4j +@RequiredArgsConstructor @Component +// TODO: we should not expose direct access to storage to any outside package, only via service interfaces! +@Deprecated(forRemoval = true) public class TaxGroupRepositoryWrapper { private final TaxGroupRepository repository; - @Autowired - public TaxGroupRepositoryWrapper(final TaxGroupRepository repository) { - this.repository = repository; - } - public TaxGroup findOneWithNotFoundDetection(final Long id) { return this.repository.findById(id).orElseThrow(() -> new TaxGroupNotFoundException(id)); } diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/CreateTaxGroupCommandHandler.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/CreateTaxGroupCommandHandler.java deleted file mode 100644 index 2da805e27e9..00000000000 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/CreateTaxGroupCommandHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * 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.tax.handler; - -import lombok.AllArgsConstructor; -import org.apache.fineract.commands.annotation.CommandType; -import org.apache.fineract.commands.handler.NewCommandSourceHandler; -import org.apache.fineract.infrastructure.core.api.JsonCommand; -import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; -import org.apache.fineract.portfolio.tax.service.TaxWritePlatformService; -import org.springframework.stereotype.Service; - -@Service -@AllArgsConstructor -@CommandType(entity = "TAXGROUP", action = "CREATE") -public class CreateTaxGroupCommandHandler implements NewCommandSourceHandler { - - private final TaxWritePlatformService taxWritePlatformService; - - @Override - public CommandProcessingResult processCommand(JsonCommand jsonCommand) { - return this.taxWritePlatformService.createTaxGroup(jsonCommand); - } - -} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/TaxComponentCreateCommandHandler.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/TaxComponentCreateCommandHandler.java new file mode 100644 index 00000000000..acdcd83363f --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/TaxComponentCreateCommandHandler.java @@ -0,0 +1,50 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.tax.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.portfolio.tax.data.TaxComponentCreateRequest; +import org.apache.fineract.portfolio.tax.data.TaxComponentCreateResponse; +import org.apache.fineract.portfolio.tax.service.TaxWriteService; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Slf4j +@Component +@RequiredArgsConstructor +public class TaxComponentCreateCommandHandler implements CommandHandler { + + private final TaxWriteService taxWriteService; + + @Retry(name = "commandTaxComponentCreate", fallbackMethod = "fallback") + @Override + @Transactional + public TaxComponentCreateResponse handle(Command command) { + return taxWriteService.createTaxComponent(command.getPayload()); + } + + @Override + public TaxComponentCreateResponse fallback(Command command, Throwable t) { + return CommandHandler.super.fallback(command, t); + } +} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/TaxComponentUpdateCommandHandler.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/TaxComponentUpdateCommandHandler.java new file mode 100644 index 00000000000..769aeab5730 --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/TaxComponentUpdateCommandHandler.java @@ -0,0 +1,50 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.tax.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.portfolio.tax.data.TaxComponentUpdateRequest; +import org.apache.fineract.portfolio.tax.data.TaxComponentUpdateResponse; +import org.apache.fineract.portfolio.tax.service.TaxWriteService; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Slf4j +@Component +@RequiredArgsConstructor +public class TaxComponentUpdateCommandHandler implements CommandHandler { + + private final TaxWriteService taxWriteService; + + @Retry(name = "commandTaxComponentUpdate", fallbackMethod = "fallback") + @Override + @Transactional + public TaxComponentUpdateResponse handle(Command command) { + return taxWriteService.updateTaxComponent(command.getPayload()); + } + + @Override + public TaxComponentUpdateResponse fallback(Command command, Throwable t) { + return CommandHandler.super.fallback(command, t); + } +} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/TaxGroupCreateCommandHandler.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/TaxGroupCreateCommandHandler.java new file mode 100644 index 00000000000..36390b8c21b --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/TaxGroupCreateCommandHandler.java @@ -0,0 +1,50 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.tax.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.portfolio.tax.data.TaxGroupCreateRequest; +import org.apache.fineract.portfolio.tax.data.TaxGroupCreateResponse; +import org.apache.fineract.portfolio.tax.service.TaxWriteService; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Slf4j +@Component +@RequiredArgsConstructor +public class TaxGroupCreateCommandHandler implements CommandHandler { + + private final TaxWriteService taxWriteService; + + @Retry(name = "commandTaxGroupCreate", fallbackMethod = "fallback") + @Override + @Transactional + public TaxGroupCreateResponse handle(Command command) { + return taxWriteService.createTaxGroup(command.getPayload()); + } + + @Override + public TaxGroupCreateResponse fallback(Command command, Throwable t) { + return CommandHandler.super.fallback(command, t); + } +} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/TaxGroupUpdateCommandHandler.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/TaxGroupUpdateCommandHandler.java new file mode 100644 index 00000000000..b8fa22c1e80 --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/TaxGroupUpdateCommandHandler.java @@ -0,0 +1,50 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.tax.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.portfolio.tax.data.TaxGroupUpdateRequest; +import org.apache.fineract.portfolio.tax.data.TaxGroupUpdateResponse; +import org.apache.fineract.portfolio.tax.service.TaxWriteService; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Slf4j +@Component +@RequiredArgsConstructor +public class TaxGroupUpdateCommandHandler implements CommandHandler { + + private final TaxWriteService taxWriteService; + + @Retry(name = "commandTaxGroupUpdate", fallbackMethod = "fallback") + @Override + @Transactional + public TaxGroupUpdateResponse handle(Command command) { + return taxWriteService.updateTaxGroup(command.getPayload()); + } + + @Override + public TaxGroupUpdateResponse fallback(Command command, Throwable t) { + return CommandHandler.super.fallback(command, t); + } +} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/UpdateTaxComponentCommandHandler.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/UpdateTaxComponentCommandHandler.java deleted file mode 100644 index 15d6572052c..00000000000 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/UpdateTaxComponentCommandHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * 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.tax.handler; - -import lombok.AllArgsConstructor; -import org.apache.fineract.commands.annotation.CommandType; -import org.apache.fineract.commands.handler.NewCommandSourceHandler; -import org.apache.fineract.infrastructure.core.api.JsonCommand; -import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; -import org.apache.fineract.portfolio.tax.service.TaxWritePlatformService; -import org.springframework.stereotype.Service; - -@Service -@AllArgsConstructor -@CommandType(entity = "TAXCOMPONENT", action = "UPDATE") -public class UpdateTaxComponentCommandHandler implements NewCommandSourceHandler { - - private final TaxWritePlatformService taxWritePlatformService; - - @Override - public CommandProcessingResult processCommand(JsonCommand jsonCommand) { - return this.taxWritePlatformService.updateTaxComponent(jsonCommand.entityId(), jsonCommand); - } - -} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/UpdateTaxGroupCommandHandler.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/UpdateTaxGroupCommandHandler.java deleted file mode 100644 index d7f11059903..00000000000 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/handler/UpdateTaxGroupCommandHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * 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.tax.handler; - -import lombok.AllArgsConstructor; -import org.apache.fineract.commands.annotation.CommandType; -import org.apache.fineract.commands.handler.NewCommandSourceHandler; -import org.apache.fineract.infrastructure.core.api.JsonCommand; -import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; -import org.apache.fineract.portfolio.tax.service.TaxWritePlatformService; -import org.springframework.stereotype.Service; - -@Service -@AllArgsConstructor -@CommandType(entity = "TAXGROUP", action = "UPDATE") -public class UpdateTaxGroupCommandHandler implements NewCommandSourceHandler { - - private final TaxWritePlatformService taxWritePlatformService; - - @Override - public CommandProcessingResult processCommand(JsonCommand jsonCommand) { - return this.taxWritePlatformService.updateTaxGroup(jsonCommand.entityId(), jsonCommand); - } - -} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/mapper/TaxComponentCreateRequestMapper.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/mapper/TaxComponentCreateRequestMapper.java new file mode 100644 index 00000000000..7bf12b808ad --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/mapper/TaxComponentCreateRequestMapper.java @@ -0,0 +1,73 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.tax.mapper; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Locale; +import org.apache.fineract.accounting.glaccount.domain.GLAccount; +import org.apache.fineract.infrastructure.core.config.MapstructMapperConfig; +import org.apache.fineract.infrastructure.core.service.DateUtils; +import org.apache.fineract.portfolio.tax.data.TaxComponentCreateRequest; +import org.apache.fineract.portfolio.tax.domain.TaxComponent; +import org.mapstruct.AfterMapping; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.Named; + +@Mapper(config = MapstructMapperConfig.class, uses = {}) +public interface TaxComponentCreateRequestMapper { + + @Mapping(target = "id", ignore = true) + @Mapping(target = "createdBy", ignore = true) + @Mapping(target = "createdDate", ignore = true) + @Mapping(target = "lastModifiedBy", ignore = true) + @Mapping(target = "lastModifiedDate", ignore = true) + @Mapping(target = "taxComponentHistories", ignore = true) + @Mapping(target = "taxGroupMappings", ignore = true) + @Mapping(target = "debitAccount", source = "debitAccountId", qualifiedByName = "mapGLAccount") + @Mapping(target = "creditAccount", source = "creditAccountId", qualifiedByName = "mapGLAccount") + @Mapping(target = "startDate", ignore = true) + TaxComponent map(TaxComponentCreateRequest source); + + @Named("mapGLAccount") + default GLAccount mapGLAccount(Long accountId) { + if (accountId == null) { + return null; + } + var account = new GLAccount(); + account.setId(accountId); + return account; + } + + @AfterMapping + default void afterMapping(TaxComponentCreateRequest source, @MappingTarget TaxComponent target) { + var startDate = DateUtils.getBusinessLocalDate(); + + if (source.getStartDate() != null && source.getDateFormat() != null) { + var locale = (source.getLocale() != null && !source.getLocale().isBlank()) ? Locale.forLanguageTag(source.getLocale()) + : Locale.getDefault(); + var formatter = DateTimeFormatter.ofPattern(source.getDateFormat(), locale); + startDate = LocalDate.parse(source.getStartDate(), formatter); + } + + target.setStartDate(startDate); + } +} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/mapper/TaxGroupCreateRequestMapper.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/mapper/TaxGroupCreateRequestMapper.java new file mode 100644 index 00000000000..016638d490c --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/mapper/TaxGroupCreateRequestMapper.java @@ -0,0 +1,87 @@ +/** + * 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.tax.mapper; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Locale; +import java.util.Set; +import java.util.stream.Collectors; +import org.apache.fineract.infrastructure.core.config.MapstructMapperConfig; +import org.apache.fineract.infrastructure.core.service.DateUtils; +import org.apache.fineract.portfolio.tax.data.TaxGroupComponentData; +import org.apache.fineract.portfolio.tax.data.TaxGroupCreateRequest; +import org.apache.fineract.portfolio.tax.domain.TaxComponent; +import org.apache.fineract.portfolio.tax.domain.TaxGroup; +import org.apache.fineract.portfolio.tax.domain.TaxGroupMappings; +import org.mapstruct.AfterMapping; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; + +@Mapper(config = MapstructMapperConfig.class, uses = {}) +public interface TaxGroupCreateRequestMapper { + + @Mapping(target = "id", ignore = true) + @Mapping(target = "createdBy", ignore = true) + @Mapping(target = "createdDate", ignore = true) + @Mapping(target = "lastModifiedBy", ignore = true) + @Mapping(target = "lastModifiedDate", ignore = true) + @Mapping(target = "taxGroupMappings", ignore = true) // handled in @AfterMapping + TaxGroup map(TaxGroupCreateRequest source); + + @AfterMapping + default void afterMapping(TaxGroupCreateRequest source, @MappingTarget TaxGroup target) { + if (source.getTaxComponents() == null || source.getTaxComponents().isEmpty()) { + return; + } + + Locale locale = (source.getLocale() != null && !source.getLocale().isBlank()) ? Locale.forLanguageTag(source.getLocale()) + : Locale.getDefault(); + + Set mappings = source.getTaxComponents().stream() + .map(componentData -> mapComponent(componentData, target, + (source.getDateFormat() != null ? DateTimeFormatter.ofPattern(source.getDateFormat(), locale) : null))) + .collect(Collectors.toSet()); + + target.setTaxGroupMappings(mappings); + } + + default TaxGroupMappings mapComponent(TaxGroupComponentData data, TaxGroup taxGroup, DateTimeFormatter formatter) { + var mapping = new TaxGroupMappings(); + mapping.setTaxGroup(taxGroup); + + // TaxComponent reference by ID + var component = new TaxComponent(); + component.setId(data.getTaxComponentId()); + mapping.setTaxComponent(component); + + // Parse startDate if provided; otherwise default to business date + var startDate = DateUtils.getBusinessLocalDate(); + + if (data.getStartDate() != null && formatter != null) { + startDate = LocalDate.parse(data.getStartDate(), formatter); + } + + mapping.setStartDate(startDate); + mapping.setEndDate(null); + + return mapping; + } +} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/serialization/TaxValidator.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/serialization/TaxValidator.java deleted file mode 100644 index 37898b021f5..00000000000 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/serialization/TaxValidator.java +++ /dev/null @@ -1,376 +0,0 @@ -/** - * 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.tax.serialization; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.reflect.TypeToken; -import java.lang.reflect.Type; -import java.math.BigDecimal; -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import org.apache.commons.lang3.StringUtils; -import org.apache.fineract.accounting.glaccount.domain.GLAccountType; -import org.apache.fineract.infrastructure.core.api.JsonCommand; -import org.apache.fineract.infrastructure.core.data.ApiParameterError; -import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; -import org.apache.fineract.infrastructure.core.exception.InvalidJsonException; -import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; -import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; -import org.apache.fineract.infrastructure.core.service.DateUtils; -import org.apache.fineract.portfolio.tax.api.TaxApiConstants; -import org.apache.fineract.portfolio.tax.domain.TaxComponent; -import org.apache.fineract.portfolio.tax.domain.TaxGroup; -import org.apache.fineract.portfolio.tax.domain.TaxGroupMappings; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Component -public class TaxValidator { - - public static final String DATE_FORMAT = "dateFormat"; - public static final String LOCALE = "locale"; - public static final String TAX_COMPONENT = "tax.component"; - public static final String TAX_GROUP = "tax.group"; - public static final String TOTAL_PERCENTAGE = "total.percentage"; - public static final String GROUP_TOTAL = "group.total."; - public static final String COMPONENT = "component"; - public static final String DATES_ARE_OVERLAPPING = "dates.are.overlapping"; - public static final String COMPONENT_START_DATE = "component.start.date"; - private static final Set SUPPORTED_TAX_COMPONENT_CREATE_PARAMETERS = new HashSet<>( - Arrays.asList(DATE_FORMAT, LOCALE, TaxApiConstants.nameParamName, TaxApiConstants.percentageParamName, - TaxApiConstants.startDateParamName, TaxApiConstants.debitAccountTypeParamName, TaxApiConstants.debitAccountIdParamName, - TaxApiConstants.creditAccountTypeParamName, TaxApiConstants.creditAccountIdParamName)); - private static final Set SUPPORTED_TAX_COMPONENT_UPDATE_PARAMETERS = new HashSet<>(Arrays.asList(DATE_FORMAT, LOCALE, - TaxApiConstants.nameParamName, TaxApiConstants.percentageParamName, TaxApiConstants.startDateParamName)); - private static final Set SUPPORTED_TAX_GROUP_PARAMETERS = new HashSet<>( - Arrays.asList(DATE_FORMAT, LOCALE, TaxApiConstants.nameParamName, TaxApiConstants.taxComponentsParamName)); - private static final Set SUPPORTED_TAX_GROUP_TAX_COMPONENTS_CREATE_PARAMETERS = new HashSet<>( - Arrays.asList(TaxApiConstants.taxComponentIdParamName, TaxApiConstants.startDateParamName)); - private static final Set SUPPORTED_TAX_GROUP_TAX_COMPONENTS_UPDATE_PARAMETERS = new HashSet<>( - Arrays.asList(TaxApiConstants.idParamName, TaxApiConstants.taxComponentIdParamName, TaxApiConstants.startDateParamName, - TaxApiConstants.endDateParamName)); - public static final String DOT = "."; - public static final String AT_INDEX = ".at.index."; - private final FromJsonHelper fromApiJsonHelper; - - @Autowired - public TaxValidator(final FromJsonHelper fromApiJsonHelper) { - this.fromApiJsonHelper = fromApiJsonHelper; - } - - public void validateForTaxComponentCreate(final String json) { - if (StringUtils.isBlank(json)) { - throw new InvalidJsonException(); - } - - final Type typeOfMap = new TypeToken>() { - - }.getType(); - this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, SUPPORTED_TAX_COMPONENT_CREATE_PARAMETERS); - - final List dataValidationErrors = new ArrayList<>(); - final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(TAX_COMPONENT); - - final JsonElement element = this.fromApiJsonHelper.parse(json); - - final String name = this.fromApiJsonHelper.extractStringNamed(TaxApiConstants.nameParamName, element); - baseDataValidator.reset().parameter(TaxApiConstants.nameParamName).value(name).notBlank(); - - final BigDecimal percentage = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(TaxApiConstants.percentageParamName, element); - baseDataValidator.reset().parameter(TaxApiConstants.percentageParamName).value(percentage).notBlank().positiveAmount() - .notGreaterThanMax(BigDecimal.valueOf(100)); - - final Integer debitAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(TaxApiConstants.debitAccountTypeParamName, - element); - baseDataValidator.reset().parameter(TaxApiConstants.debitAccountTypeParamName).value(debitAccountType).ignoreIfNull() - .isOneOfTheseValues(GLAccountType.ASSET.getValue(), GLAccountType.LIABILITY.getValue(), GLAccountType.EQUITY.getValue(), - GLAccountType.INCOME.getValue(), GLAccountType.EXPENSE.getValue()); - - final Long debitAccountId = this.fromApiJsonHelper.extractLongNamed(TaxApiConstants.debitAccountIdParamName, element); - baseDataValidator.reset().parameter(TaxApiConstants.debitAccountIdParamName).value(debitAccountId).longGreaterThanZero(); - if (debitAccountType != null || debitAccountId != null) { - baseDataValidator.reset().parameter(TaxApiConstants.debitAccountTypeParamName).value(debitAccountType).notBlank(); - baseDataValidator.reset().parameter(TaxApiConstants.debitAccountIdParamName).value(debitAccountId).notBlank(); - } - - final Integer creditAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(TaxApiConstants.creditAccountTypeParamName, - element); - baseDataValidator.reset().parameter(TaxApiConstants.creditAccountTypeParamName).value(creditAccountType).ignoreIfNull() - .isOneOfTheseValues(GLAccountType.ASSET.getValue(), GLAccountType.LIABILITY.getValue(), GLAccountType.EQUITY.getValue(), - GLAccountType.INCOME.getValue(), GLAccountType.EXPENSE.getValue()); - - final Long creditAccountId = this.fromApiJsonHelper.extractLongNamed(TaxApiConstants.creditAccountIdParamName, element); - baseDataValidator.reset().parameter(TaxApiConstants.creditAccountIdParamName).value(creditAccountId).longGreaterThanZero(); - if (creditAccountType != null || creditAccountId != null) { - baseDataValidator.reset().parameter(TaxApiConstants.creditAccountIdParamName).value(creditAccountId).notBlank(); - baseDataValidator.reset().parameter(TaxApiConstants.creditAccountTypeParamName).value(creditAccountType).notBlank(); - } - throwExceptionIfValidationWarningsExist(dataValidationErrors); - } - - public void validateForTaxComponentUpdate(final String json) { - if (StringUtils.isBlank(json)) { - throw new InvalidJsonException(); - } - - final Type typeOfMap = new TypeToken>() { - - }.getType(); - this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, SUPPORTED_TAX_COMPONENT_UPDATE_PARAMETERS); - - final List dataValidationErrors = new ArrayList<>(); - final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(TAX_COMPONENT); - - final JsonElement element = this.fromApiJsonHelper.parse(json); - - if (this.fromApiJsonHelper.parameterExists(TaxApiConstants.nameParamName, element)) { - final String name = this.fromApiJsonHelper.extractStringNamed(TaxApiConstants.nameParamName, element); - baseDataValidator.reset().parameter(TaxApiConstants.nameParamName).value(name).notBlank(); - } - - if (this.fromApiJsonHelper.parameterExists(TaxApiConstants.percentageParamName, element)) { - final BigDecimal percentage = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(TaxApiConstants.percentageParamName, - element); - baseDataValidator.reset().parameter(TaxApiConstants.percentageParamName).value(percentage).notBlank().positiveAmount() - .notGreaterThanMax(BigDecimal.valueOf(100)); - } - - if (this.fromApiJsonHelper.parameterExists(TaxApiConstants.startDateParamName, element)) { - final LocalDate startDate = this.fromApiJsonHelper.extractLocalDateNamed(TaxApiConstants.startDateParamName, element); - baseDataValidator.reset().parameter(TaxApiConstants.startDateParamName).value(startDate) - .validateDateAfter(DateUtils.getBusinessLocalDate()); - } - throwExceptionIfValidationWarningsExist(dataValidationErrors); - } - - public void validateForTaxGroupCreate(final String json) { - if (StringUtils.isBlank(json)) { - throw new InvalidJsonException(); - } - - final Type typeOfMap = new TypeToken>() { - - }.getType(); - this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, SUPPORTED_TAX_GROUP_PARAMETERS); - - final List dataValidationErrors = new ArrayList<>(); - final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(TAX_GROUP); - - final JsonElement element = this.fromApiJsonHelper.parse(json); - - final String name = this.fromApiJsonHelper.extractStringNamed(TaxApiConstants.nameParamName, element); - baseDataValidator.reset().parameter(TaxApiConstants.nameParamName).value(name).notBlank(); - - final JsonArray taxComponents = this.fromApiJsonHelper.extractJsonArrayNamed(TaxApiConstants.taxComponentsParamName, element); - baseDataValidator.reset().parameter(TaxApiConstants.taxComponentsParamName).value(taxComponents).notBlank(); - - final JsonObject topLevelJsonElement = element.getAsJsonObject(); - if (topLevelJsonElement.get(TaxApiConstants.taxComponentsParamName).isJsonArray()) { - final JsonArray array = topLevelJsonElement.get(TaxApiConstants.taxComponentsParamName).getAsJsonArray(); - baseDataValidator.reset().parameter(TaxApiConstants.taxComponentsParamName).value(array.size()).integerGreaterThanZero(); - for (int i = 1; i <= array.size(); i++) { - final JsonObject taxComponent = array.get(i - 1).getAsJsonObject(); - final String arrayObjectJson = this.fromApiJsonHelper.toJson(taxComponent); - this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, arrayObjectJson, - SUPPORTED_TAX_GROUP_TAX_COMPONENTS_CREATE_PARAMETERS); - final Long taxComponentId = this.fromApiJsonHelper.extractLongNamed(TaxApiConstants.taxComponentIdParamName, taxComponent); - baseDataValidator.reset().parameter(TaxApiConstants.taxComponentsParamName) - .parameterAtIndexArray(TaxApiConstants.taxComponentIdParamName, i).value(taxComponentId).notNull() - .longGreaterThanZero(); - - } - } - throwExceptionIfValidationWarningsExist(dataValidationErrors); - } - - public void validateForTaxGroupUpdate(final String json) { - if (StringUtils.isBlank(json)) { - throw new InvalidJsonException(); - } - - final Type typeOfMap = new TypeToken>() { - - }.getType(); - this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, SUPPORTED_TAX_GROUP_PARAMETERS); - - final List dataValidationErrors = new ArrayList<>(); - final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(TAX_GROUP); - - final JsonElement element = this.fromApiJsonHelper.parse(json); - - if (this.fromApiJsonHelper.parameterExists(TaxApiConstants.nameParamName, element)) { - final String name = this.fromApiJsonHelper.extractStringNamed(TaxApiConstants.nameParamName, element); - baseDataValidator.reset().parameter(TaxApiConstants.nameParamName).value(name).notBlank(); - } - if (this.fromApiJsonHelper.parameterExists(TaxApiConstants.taxComponentsParamName, element)) { - final JsonArray taxComponents = this.fromApiJsonHelper.extractJsonArrayNamed(TaxApiConstants.taxComponentsParamName, element); - baseDataValidator.reset().parameter(TaxApiConstants.taxComponentsParamName).value(taxComponents).notBlank(); - - final JsonObject topLevelJsonElement = element.getAsJsonObject(); - final String dateFormat = this.fromApiJsonHelper.extractDateFormatParameter(topLevelJsonElement); - final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement); - if (topLevelJsonElement.get(TaxApiConstants.taxComponentsParamName).isJsonArray()) { - final JsonArray array = topLevelJsonElement.get(TaxApiConstants.taxComponentsParamName).getAsJsonArray(); - for (int i = 1; i <= array.size(); i++) { - final JsonObject taxComponent = array.get(i - 1).getAsJsonObject(); - final String arrayObjectJson = this.fromApiJsonHelper.toJson(taxComponent); - this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, arrayObjectJson, - SUPPORTED_TAX_GROUP_TAX_COMPONENTS_UPDATE_PARAMETERS); - final Long taxComponentId = this.fromApiJsonHelper.extractLongNamed(TaxApiConstants.taxComponentIdParamName, - taxComponent); - final Long taxMappingId = this.fromApiJsonHelper.extractLongNamed(TaxApiConstants.taxComponentIdParamName, - taxComponent); - if (taxMappingId == null) { - baseDataValidator.reset().parameter( - TaxApiConstants.taxComponentsParamName + DOT + TaxApiConstants.taxComponentIdParamName + AT_INDEX + i) - .value(taxComponentId).notNull().longGreaterThanZero(); - } else { - baseDataValidator.reset().parameter( - TaxApiConstants.taxComponentsParamName + DOT + TaxApiConstants.taxComponentIdParamName + AT_INDEX + i) - .value(taxComponentId).longGreaterThanZero(); - baseDataValidator.reset() - .parameter(TaxApiConstants.taxComponentsParamName + DOT + TaxApiConstants.idParamName + AT_INDEX + i) - .value(taxMappingId).longGreaterThanZero(); - } - - final LocalDate endDate = this.fromApiJsonHelper.extractLocalDateNamed(TaxApiConstants.endDateParamName, taxComponent, - dateFormat, locale); - baseDataValidator.reset() - .parameter(TaxApiConstants.taxComponentsParamName + DOT + TaxApiConstants.endDateParamName + AT_INDEX + i) - .value(endDate).ignoreIfNull().validateDateAfter(DateUtils.getBusinessLocalDate()); - final LocalDate startDate = this.fromApiJsonHelper.extractLocalDateNamed(TaxApiConstants.startDateParamName, - taxComponent, dateFormat, locale); - if (endDate != null && startDate != null) { - baseDataValidator.reset().parameter(TaxApiConstants.taxComponentsParamName + AT_INDEX + i) - .failWithCode("start.date.end.date.both.should.not.be.present", startDate, endDate); - } - } - } - } - throwExceptionIfValidationWarningsExist(dataValidationErrors); - } - - public void validateTaxGroupEndDateAndTaxComponent(final TaxGroup taxGroup, final Set groupMappings) { - final List dataValidationErrors = new ArrayList<>(); - final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(TAX_GROUP); - - for (TaxGroupMappings mapping : groupMappings) { - if (mapping.getId() != null) { - TaxGroupMappings existing = taxGroup.findOneBy(mapping); - if (existing.endDate() != null && mapping.endDate() != null && !DateUtils.isEqual(existing.endDate(), mapping.endDate())) { - baseDataValidator.reset().parameter(TaxApiConstants.endDateParamName) - .failWithCode("can.not.modify.end.date.once.updated"); - } else { - baseDataValidator.reset().parameter(TaxApiConstants.endDateParamName).value(mapping.endDate()).ignoreIfNull() - .validateDateAfter(existing.startDate()); - } - if (mapping.getTaxComponent() != null && !existing.getTaxComponent().getId().equals(mapping.getTaxComponent().getId())) { - baseDataValidator.reset().parameter(TaxApiConstants.taxComponentIdParamName).failWithCode("update.not.supported"); - } - } else if (mapping.endDate() != null) { - baseDataValidator.reset().parameter(TaxApiConstants.endDateParamName).failWithCode("not.supported.for.new.association"); - } - } - throwExceptionIfValidationWarningsExist(dataValidationErrors); - } - - public void validateTaxGroup(final TaxGroup taxGroup) { - final List dataValidationErrors = new ArrayList<>(); - final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(TAX_GROUP); - Set groupMappings = taxGroup.getTaxGroupMappings(); - validateGroupTotal(groupMappings, baseDataValidator, TOTAL_PERCENTAGE); - validateOverlappingComponents(groupMappings, baseDataValidator); - throwExceptionIfValidationWarningsExist(dataValidationErrors); - } - - public void validateTaxComponentForUpdate(final TaxComponent taxComponent) { - final List dataValidationErrors = new ArrayList<>(); - final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(TAX_COMPONENT); - validateGroupTotal(taxComponent.getTaxGroupMappings(), baseDataValidator, GROUP_TOTAL + TaxApiConstants.percentageParamName); - throwExceptionIfValidationWarningsExist(dataValidationErrors); - } - - public void validateStartDate(final LocalDate existingStartDate, final JsonCommand command) { - final List dataValidationErrors = new ArrayList<>(); - final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(TAX_COMPONENT); - validateStartDate(existingStartDate, command.localDateValueOfParameterNamed(TaxApiConstants.startDateParamName), baseDataValidator); - throwExceptionIfValidationWarningsExist(dataValidationErrors); - } - - private void validateStartDate(final LocalDate existingStartDate, final LocalDate startDate, - final DataValidatorBuilder baseDataValidator) { - baseDataValidator.reset().parameter(TaxApiConstants.startDateParamName).value(startDate).validateDateAfter(existingStartDate); - } - - private void validateOverlappingComponents(final Set taxMappings, final DataValidatorBuilder baseDataValidator) { - for (TaxGroupMappings groupMappingsOne : taxMappings) { - final List mappings = new ArrayList<>(taxMappings); - mappings.remove(groupMappingsOne); - for (TaxGroupMappings groupMappings : mappings) { - if (groupMappingsOne.getTaxComponent().equals(groupMappings.getTaxComponent())) { - if (groupMappingsOne.endDate() == null && groupMappings.endDate() == null) { - baseDataValidator.reset().parameter(COMPONENT).failWithCode(DATES_ARE_OVERLAPPING); - } else if (DateUtils.isAfter(groupMappingsOne.startDate(), groupMappings.startDate())) { - baseDataValidator.reset().parameter(COMPONENT_START_DATE).value(groupMappingsOne.startDate()) - .validateDateAfter(groupMappings.endDate()); - } else { - baseDataValidator.reset().parameter(COMPONENT_START_DATE).value(groupMappings.startDate()) - .validateDateAfter(groupMappingsOne.endDate()); - } - } - } - } - } - - private void validateGroupTotal(final Set taxMappings, final DataValidatorBuilder baseDataValidator, - final String paramenter) { - for (TaxGroupMappings groupMappingsOne : taxMappings) { - Collection dates = groupMappingsOne.getTaxComponent().allStartDates(); - for (LocalDate date : dates) { - LocalDate applicableDate = date.plusDays(1); - BigDecimal total = BigDecimal.ZERO; - for (TaxGroupMappings groupMappings : taxMappings) { - if (groupMappings.occursOnDayFromAndUpToAndIncluding(applicableDate)) { - BigDecimal applicablePercentage = groupMappings.getTaxComponent().getApplicablePercentage(applicableDate); - if (applicablePercentage != null) { - total = total.add(applicablePercentage); - } - } - } - baseDataValidator.reset().parameter(paramenter).value(total).notGreaterThanMax(BigDecimal.valueOf(100)); - } - } - } - - private void throwExceptionIfValidationWarningsExist(final List dataValidationErrors) { - if (!dataValidationErrors.isEmpty()) { - throw new PlatformApiDataValidationException(dataValidationErrors); - } - } - -} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/ChargeTaxApplicationService.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/ChargeTaxApplicationService.java index ca11b2189b9..036841fce1d 100644 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/ChargeTaxApplicationService.java +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/ChargeTaxApplicationService.java @@ -24,6 +24,8 @@ import org.apache.fineract.portfolio.tax.domain.TaxComponent; import org.apache.fineract.portfolio.tax.domain.TaxGroup; +// TODO: migrate all use of this function to TaxUtils.computeTax; leaving for now, too many changes! +@Deprecated(forRemoval = true) public interface ChargeTaxApplicationService { Map computeTax(TaxGroup taxGroup, BigDecimal baseAmount, LocalDate effectiveDate, int scale); diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/ChargeTaxApplicationServiceImpl.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/ChargeTaxApplicationServiceImpl.java index 26264c53d9e..132f1fc16d5 100644 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/ChargeTaxApplicationServiceImpl.java +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/ChargeTaxApplicationServiceImpl.java @@ -20,21 +20,19 @@ import java.math.BigDecimal; import java.time.LocalDate; -import java.util.Collections; import java.util.Map; import org.apache.fineract.portfolio.tax.domain.TaxComponent; import org.apache.fineract.portfolio.tax.domain.TaxGroup; import org.springframework.stereotype.Service; @Service +// TODO: migrate all use of this function to TaxUtils.computeTax; leaving for now, too many changes! +@Deprecated(forRemoval = true) public class ChargeTaxApplicationServiceImpl implements ChargeTaxApplicationService { @Override public Map computeTax(final TaxGroup taxGroup, final BigDecimal baseAmount, final LocalDate effectiveDate, final int scale) { - if (taxGroup == null || baseAmount == null || baseAmount.compareTo(BigDecimal.ZERO) == 0) { - return Collections.emptyMap(); - } - return TaxUtils.splitTax(baseAmount, effectiveDate, taxGroup.getTaxGroupMappings(), scale); + return TaxUtils.computeTax(taxGroup, baseAmount, effectiveDate, scale); } } diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxReadPlatformService.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxReadService.java similarity index 97% rename from fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxReadPlatformService.java rename to fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxReadService.java index 4b61676fb1b..f08bc56191c 100644 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxReadPlatformService.java +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxReadService.java @@ -22,7 +22,7 @@ import org.apache.fineract.portfolio.tax.data.TaxComponentData; import org.apache.fineract.portfolio.tax.data.TaxGroupData; -public interface TaxReadPlatformService { +public interface TaxReadService { TaxComponentData retrieveTaxComponentData(Long id); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/service/TaxReadPlatformServiceImpl.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxReadServiceImpl.java similarity index 63% rename from fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/service/TaxReadPlatformServiceImpl.java rename to fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxReadServiceImpl.java index 9c4bc698a06..df4be04cd8b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/tax/service/TaxReadPlatformServiceImpl.java +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxReadServiceImpl.java @@ -21,25 +21,31 @@ import java.util.Collection; import java.util.List; import lombok.RequiredArgsConstructor; -import org.apache.fineract.accounting.common.AccountingDropdownReadPlatformService; +import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.accounting.adapter.AccountMappingOptionsAdapter; +import org.apache.fineract.accounting.adapter.GLAccountTypeOptionsAdapter; import org.apache.fineract.portfolio.tax.data.TaxComponentData; import org.apache.fineract.portfolio.tax.data.TaxGroupData; import org.apache.fineract.portfolio.tax.domain.TaxComponentRepository; -import org.apache.fineract.portfolio.tax.domain.TaxComponentRepositoryWrapper; import org.apache.fineract.portfolio.tax.domain.TaxGroupRepository; -import org.apache.fineract.portfolio.tax.domain.TaxGroupRepositoryWrapper; +import org.apache.fineract.portfolio.tax.exception.TaxComponentNotFoundException; +import org.apache.fineract.portfolio.tax.exception.TaxGroupNotFoundException; import org.apache.fineract.portfolio.tax.mapper.TaxComponentMapper; import org.apache.fineract.portfolio.tax.mapper.TaxGroupMapper; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.stereotype.Service; +@Slf4j @RequiredArgsConstructor -public class TaxReadPlatformServiceImpl implements TaxReadPlatformService { +@Service +@ConditionalOnMissingBean(value = TaxReadService.class, ignored = TaxReadServiceImpl.class) +public class TaxReadServiceImpl implements TaxReadService { - private final AccountingDropdownReadPlatformService accountingDropdownReadPlatformService; + private final AccountMappingOptionsAdapter accountMappingOptionsAdapter; + private final GLAccountTypeOptionsAdapter glAccountTypeOptionsAdapter; private final TaxComponentRepository taxComponentRepository; - private final TaxComponentRepositoryWrapper taxComponentRepositoryWrapper; private final TaxComponentMapper taxComponentMapper; private final TaxGroupRepository taxGroupRepository; - private final TaxGroupRepositoryWrapper taxGroupRepositoryWrapper; private final TaxGroupMapper taxGroupMapper; @Override @@ -49,13 +55,13 @@ public List retrieveAllTaxComponents() { @Override public TaxComponentData retrieveTaxComponentData(final Long id) { - return taxComponentMapper.map(taxComponentRepositoryWrapper.findOneWithNotFoundDetection(id)); + return taxComponentMapper.map(taxComponentRepository.findById(id).orElseThrow(() -> new TaxComponentNotFoundException(id))); } @Override public TaxComponentData retrieveTaxComponentTemplate() { - return TaxComponentData.template(this.accountingDropdownReadPlatformService.retrieveAccountMappingOptions(), - this.accountingDropdownReadPlatformService.retrieveGLAccountTypeOptions()); + return TaxComponentData.builder().glAccountOptions(accountMappingOptionsAdapter.retrieve()) + .glAccountTypeOptions(glAccountTypeOptionsAdapter.retrieve()).build(); } @Override @@ -65,19 +71,20 @@ public List retrieveAllTaxGroups() { @Override public TaxGroupData retrieveTaxGroupData(final Long id) { - return taxGroupMapper.map(taxGroupRepositoryWrapper.findOneWithNotFoundDetection(id)); + return taxGroupMapper.map(taxGroupRepository.findById(id).orElseThrow(() -> new TaxGroupNotFoundException(id))); } @Override public TaxGroupData retrieveTaxGroupWithTemplate(final Long id) { TaxGroupData taxGroupData = retrieveTaxGroupData(id); - taxGroupData = TaxGroupData.template(taxGroupData, retrieveTaxComponentsForLookUp()); + taxGroupData = TaxGroupData.builder().id(taxGroupData.getId()).name(taxGroupData.getName()) + .taxAssociations(taxGroupData.getTaxAssociations()).taxComponents(retrieveTaxComponentsForLookUp()).build(); return taxGroupData; } @Override public TaxGroupData retrieveTaxGroupTemplate() { - return TaxGroupData.template(retrieveTaxComponentsForLookUp()); + return TaxGroupData.builder().taxComponents(retrieveTaxComponentsForLookUp()).build(); } private Collection retrieveTaxComponentsForLookUp() { diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxUtils.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxUtils.java index ee5b0cd1052..0a84a97dd5d 100644 --- a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxUtils.java +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxUtils.java @@ -20,14 +20,16 @@ import java.math.BigDecimal; import java.time.LocalDate; +import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Set; +import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.organisation.monetary.domain.MoneyHelper; import org.apache.fineract.portfolio.tax.data.TaxComponentData; import org.apache.fineract.portfolio.tax.data.TaxGroupMappingsData; import org.apache.fineract.portfolio.tax.domain.TaxComponent; +import org.apache.fineract.portfolio.tax.domain.TaxGroup; import org.apache.fineract.portfolio.tax.domain.TaxGroupMappings; public final class TaxUtils { @@ -38,62 +40,63 @@ private TaxUtils() { public static Map splitTax(final BigDecimal amount, final LocalDate date, final Set taxGroupMappings, final int scale) { - Map map = new HashMap<>(3); + var map = new HashMap(); + if (amount != null) { - final double amountVal = amount.doubleValue(); - double cent_percentage = Double.parseDouble("100.0"); - for (TaxGroupMappings groupMappings : taxGroupMappings) { + var amountVal = amount.doubleValue(); + var cent_percentage = Double.parseDouble("100.0"); + + for (var groupMappings : taxGroupMappings) { if (groupMappings.occursOnDayFromAndUpToAndIncluding(date)) { - TaxComponent component = groupMappings.getTaxComponent(); - BigDecimal percentage = component.getApplicablePercentage(date); + var component = groupMappings.getTaxComponent(); + var percentage = component.getApplicablePercentage(date); + if (percentage != null) { - double percentageVal = percentage.doubleValue(); - double tax = amountVal * percentageVal / cent_percentage; + var percentageVal = percentage.doubleValue(); + var tax = amountVal * percentageVal / cent_percentage; + map.put(component, BigDecimal.valueOf(tax).setScale(scale, MoneyHelper.getRoundingMode())); } } } } + return map; } public static Map splitTaxData(final BigDecimal amount, final LocalDate date, final Set taxGroupMappings, final int scale) { - Map map = new HashMap<>(3); + var map = new HashMap(); + if (amount != null) { - final double amountVal = amount.doubleValue(); - double cent_percentage = Double.parseDouble("100.0"); - for (TaxGroupMappingsData groupMappings : taxGroupMappings) { - if (groupMappings.occursOnDayFromAndUpToAndIncluding(date)) { - TaxComponentData component = groupMappings.getTaxComponent(); - BigDecimal percentage = component.getApplicablePercentage(date); + var amountVal = amount.doubleValue(); + var centPercentage = Double.parseDouble("100.0"); + + for (var groupMappings : taxGroupMappings) { + if (occursOnDayFromAndUpToAndIncluding(groupMappings.getStartDate(), groupMappings.getEndDate(), date)) { + var component = groupMappings.getTaxComponent(); + var percentage = component.getApplicablePercentage(date); + if (percentage != null) { - double percentageVal = percentage.doubleValue(); - double tax = amountVal * percentageVal / cent_percentage; + var percentageVal = percentage.doubleValue(); + var tax = amountVal * percentageVal / centPercentage; + map.put(component, BigDecimal.valueOf(tax).setScale(scale, MoneyHelper.getRoundingMode())); } } } } - return map; - } - - public static BigDecimal incomeAmount(final BigDecimal amount, final LocalDate date, final Set taxGroupMappings, - final int scale) { - Map map = splitTax(amount, date, taxGroupMappings, scale); - return incomeAmount(amount, map); - } - public static BigDecimal incomeAmount(final BigDecimal amount, final Map map) { - BigDecimal totalTax = totalTaxAmount(map); - return amount.subtract(totalTax); + return map; } public static BigDecimal totalTaxAmount(final Map map) { - BigDecimal totalTax = BigDecimal.ZERO; - for (BigDecimal tax : map.values()) { + var totalTax = BigDecimal.ZERO; + + for (var tax : map.values()) { totalTax = totalTax.add(tax); } + return totalTax; } @@ -105,25 +108,16 @@ public static BigDecimal totalTaxDataAmount(final Map taxGroupMappings, - final int scale) { - BigDecimal totalAmount = null; - if (amount != null && amount.compareTo(BigDecimal.ZERO) > 0) { - double percentageVal = 0; - double amountVal = amount.doubleValue(); - double cent_percentage = Double.parseDouble("100.0"); - for (TaxGroupMappings groupMappings : taxGroupMappings) { - if (groupMappings.occursOnDayFromAndUpToAndIncluding(date)) { - TaxComponent component = groupMappings.getTaxComponent(); - BigDecimal percentage = component.getApplicablePercentage(date); - if (percentage != null) { - percentageVal = percentageVal + percentage.doubleValue(); - } - } - } - double total = amountVal * cent_percentage / (cent_percentage - percentageVal); - totalAmount = BigDecimal.valueOf(total).setScale(scale, MoneyHelper.getRoundingMode()); + public static Map computeTax(final TaxGroup taxGroup, final BigDecimal baseAmount, + final LocalDate effectiveDate, final int scale) { + if (taxGroup == null || baseAmount == null || baseAmount.compareTo(BigDecimal.ZERO) == 0) { + return Collections.emptyMap(); } - return totalAmount; + + return splitTax(baseAmount, effectiveDate, taxGroup.getTaxGroupMappings(), scale); + } + + private static boolean occursOnDayFromAndUpToAndIncluding(final LocalDate startDate, final LocalDate endDate, final LocalDate target) { + return DateUtils.isAfter(target, startDate) && (endDate == null || !DateUtils.isAfter(target, endDate)); } } diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWriteService.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWriteService.java new file mode 100644 index 00000000000..f682badc895 --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWriteService.java @@ -0,0 +1,39 @@ +/** + * 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.tax.service; + +import org.apache.fineract.portfolio.tax.data.TaxComponentCreateRequest; +import org.apache.fineract.portfolio.tax.data.TaxComponentCreateResponse; +import org.apache.fineract.portfolio.tax.data.TaxComponentUpdateRequest; +import org.apache.fineract.portfolio.tax.data.TaxComponentUpdateResponse; +import org.apache.fineract.portfolio.tax.data.TaxGroupCreateRequest; +import org.apache.fineract.portfolio.tax.data.TaxGroupCreateResponse; +import org.apache.fineract.portfolio.tax.data.TaxGroupUpdateRequest; +import org.apache.fineract.portfolio.tax.data.TaxGroupUpdateResponse; + +public interface TaxWriteService { + + TaxComponentCreateResponse createTaxComponent(TaxComponentCreateRequest request); + + TaxComponentUpdateResponse updateTaxComponent(TaxComponentUpdateRequest request); + + TaxGroupCreateResponse createTaxGroup(TaxGroupCreateRequest request); + + TaxGroupUpdateResponse updateTaxGroup(TaxGroupUpdateRequest request); +} diff --git a/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWriteServiceImpl.java b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWriteServiceImpl.java new file mode 100644 index 00000000000..5c6cbc2cdc4 --- /dev/null +++ b/fineract-tax/src/main/java/org/apache/fineract/portfolio/tax/service/TaxWriteServiceImpl.java @@ -0,0 +1,157 @@ +/** + * 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.tax.service; + +import jakarta.validation.Valid; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.fineract.infrastructure.core.service.DateUtils; +import org.apache.fineract.portfolio.tax.data.TaxComponentCreateRequest; +import org.apache.fineract.portfolio.tax.data.TaxComponentCreateResponse; +import org.apache.fineract.portfolio.tax.data.TaxComponentUpdateRequest; +import org.apache.fineract.portfolio.tax.data.TaxComponentUpdateResponse; +import org.apache.fineract.portfolio.tax.data.TaxGroupCreateRequest; +import org.apache.fineract.portfolio.tax.data.TaxGroupCreateResponse; +import org.apache.fineract.portfolio.tax.data.TaxGroupUpdateRequest; +import org.apache.fineract.portfolio.tax.data.TaxGroupUpdateResponse; +import org.apache.fineract.portfolio.tax.domain.TaxComponent; +import org.apache.fineract.portfolio.tax.domain.TaxComponentHistory; +import org.apache.fineract.portfolio.tax.domain.TaxComponentRepository; +import org.apache.fineract.portfolio.tax.domain.TaxGroupMappings; +import org.apache.fineract.portfolio.tax.domain.TaxGroupRepository; +import org.apache.fineract.portfolio.tax.exception.TaxComponentNotFoundException; +import org.apache.fineract.portfolio.tax.exception.TaxGroupNotFoundException; +import org.apache.fineract.portfolio.tax.mapper.TaxComponentCreateRequestMapper; +import org.apache.fineract.portfolio.tax.mapper.TaxGroupCreateRequestMapper; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.stereotype.Service; + +@Slf4j +@RequiredArgsConstructor +@Service +@ConditionalOnMissingBean(value = TaxWriteService.class, ignored = TaxWriteServiceImpl.class) +public class TaxWriteServiceImpl implements TaxWriteService { + + private final TaxComponentRepository taxComponentRepository; + private final TaxGroupRepository taxGroupRepository; + private final TaxGroupCreateRequestMapper taxGroupCreateRequestMapper; + + private final TaxComponentCreateRequestMapper taxComponentCreateRequestMapper; + + @Override + public TaxComponentCreateResponse createTaxComponent(@Valid TaxComponentCreateRequest request) { + var taxComponent = taxComponentCreateRequestMapper.map(request); + + taxComponentRepository.saveAndFlush(taxComponent); + + return TaxComponentCreateResponse.builder().resourceId(taxComponent.getId()).build(); + } + + @Override + public TaxComponentUpdateResponse updateTaxComponent(TaxComponentUpdateRequest request) { + var taxComponent = taxComponentRepository.findById(request.getId()) + .orElseThrow(() -> new TaxComponentNotFoundException(request.getId())); + + final Map changes = new HashMap<>(); + + if (!Objects.equals(taxComponent.getName(), request.getName())) { + taxComponent.setName(request.getName()); + + changes.put(TaxComponent.Fields.startDate, request.getName()); + } + + if (Objects.compare(taxComponent.getPercentage(), request.getPercentage(), (o1, o2) -> { + if (o1 == null) { + o1 = BigDecimal.ZERO; + } + if (o2 == null) { + o2 = BigDecimal.ZERO; + } + + return o1.compareTo(o2); + }) != 0) { + taxComponent.setPercentage(request.getPercentage()); + + changes.put(TaxComponent.Fields.percentage, request.getPercentage()); + + var oldStartDate = taxComponent.getStartDate(); + var newStartDate = StringUtils.isNotEmpty(request.getStartDate()) + ? DateUtils.toLocalDate(request.getLocale(), request.getStartDate(), request.getDateFormat()) + : DateUtils.getBusinessLocalDate(); + + changes.put(TaxComponent.Fields.startDate, newStartDate); + + var history = new TaxComponentHistory(); + history.setPercentage(request.getPercentage()); + history.setStartDate(oldStartDate); + history.setStartDate(newStartDate); + + if (taxComponent.getTaxComponentHistories() != null) { + taxComponent.getTaxComponentHistories().add(history); + } else { + taxComponent.setTaxComponentHistories(Set.of(history)); + } + } + + taxComponentRepository.saveAndFlush(taxComponent); + + return TaxComponentUpdateResponse.builder().resourceId(taxComponent.getId()).changes(changes).build(); + } + + @Override + public TaxGroupCreateResponse createTaxGroup(@Valid TaxGroupCreateRequest request) { + var taxGroup = taxGroupCreateRequestMapper.map(request); + + taxGroupRepository.saveAndFlush(taxGroup); + + return TaxGroupCreateResponse.builder().resourceId(taxGroup.getId()).build(); + } + + @Override + public TaxGroupUpdateResponse updateTaxGroup(@Valid TaxGroupUpdateRequest request) { + var taxGroup = taxGroupRepository.findById(request.getId()).orElseThrow(() -> new TaxGroupNotFoundException(request.getId())); + + // var groupMappings = + request.getTaxComponents().stream() + .map(taxGroupComponentData -> taxComponentRepository.findById(taxGroupComponentData.getTaxComponentId()) + .orElseThrow(() -> new TaxComponentNotFoundException(taxGroupComponentData.getTaxComponentId()))) + .map(taxComponent -> new TaxGroupMappings().setTaxComponent(taxComponent)).collect(Collectors.toSet()); + + final Map changes = new HashMap<>(); + + if (!Objects.equals(taxGroup.getName(), request.getName())) { + taxGroup.setName(request.getName()); + + changes.put(TaxComponent.Fields.name, request.getName()); + } + + // TODO: history + + taxGroupRepository.saveAndFlush(taxGroup); + + return TaxGroupUpdateResponse.builder().resourceId(taxGroup.getId()).changes(changes).build(); + } +} diff --git a/fineract-validation/src/main/resources/ValidationMessages.properties b/fineract-validation/src/main/resources/ValidationMessages.properties index 1e4e9d56fbe..39f786e4d2b 100644 --- a/fineract-validation/src/main/resources/ValidationMessages.properties +++ b/fineract-validation/src/main/resources/ValidationMessages.properties @@ -134,3 +134,27 @@ org.apache.fineract.portfolio.meeting.date-format.not-null=The parameter 'dateFo org.apache.fineract.portfolio.meeting.locale.not-null=The parameter 'locale' is mandatory org.apache.fineract.portfolio.meeting.attendance.client-id.not-null=The parameter 'clientId' is mandatory org.apache.fineract.portfolio.meeting.attendance.attendance-type.not-null=The parameter 'attendanceType' is mandatory + +# tax component + +org.apache.fineract.portfolio.tax.component.name.not-empty=The parameter 'name' cannot be empty +org.apache.fineract.portfolio.tax.component.percentage.not-empty=The parameter 'percentage' cannot be empty +org.apache.fineract.portfolio.tax.component.percentage.positive=The parameter 'percentage' must have a positive value +org.apache.fineract.portfolio.tax.component.percentage.max=The parameter 'percentage' cannot be bigger than 100.0 +org.apache.fineract.portfolio.tax.component.debit-account-type.min=The parameter 'debitAccountType' must have a value between 1 and 5 +org.apache.fineract.portfolio.tax.component.debit-account-type.max=The parameter 'debitAccountType' must have a value between 1 and 5 +org.apache.fineract.portfolio.tax.component.debit-account-id.positive=The parameter 'debitAccountId' must have a positive value +org.apache.fineract.portfolio.tax.component.credit-account-type.min=The parameter 'creditAccountType' must have a value between 1 and 5 +org.apache.fineract.portfolio.tax.component.credit-account-type.max=The parameter 'creditAccountType' must have a value between 1 and 5 +org.apache.fineract.portfolio.tax.component.credit-account-id.positive=The parameter 'creditAccountId' must have a positive value +org.apache.fineract.portfolio.tax.component.debit-account.valid=Both debitAccountType and debitAccountId must be provided if either is present +org.apache.fineract.portfolio.tax.component.credit-account.valid=Both creditAccountType and creditAccountId must be provided if either is present +org.apache.fineract.portfolio.tax.component.start-date.valid=Start date must be after the current business date + +# tax group + +org.apache.fineract.portfolio.tax.group.name.not-empty=The parameter 'name' cannot be empty +org.apache.fineract.portfolio.tax.group.tax-components.not-empty=At least one tax component is required +org.apache.fineract.portfolio.tax.group.tax-component-id.valid=The parameter 'taxComponentId' is required when id is not provided +org.apache.fineract.portfolio.tax.group.component-end-date.valid=endDate must be after the current business date +org.apache.fineract.portfolio.tax.group.component-start-date.valid=startDate and endDate must not both be present in any component diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ChargesTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ChargesTest.java index a31f340326e..1d61b50325a 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ChargesTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ChargesTest.java @@ -32,11 +32,9 @@ import org.apache.fineract.client.models.ChargeRequest; import org.apache.fineract.client.models.GetChargesResponse; import org.apache.fineract.client.models.PostChargesResponse; -import org.apache.fineract.client.models.PostTaxesComponentsRequest; -import org.apache.fineract.client.models.PostTaxesComponentsResponse; -import org.apache.fineract.client.models.PostTaxesGroupRequest; -import org.apache.fineract.client.models.PostTaxesGroupResponse; -import org.apache.fineract.client.models.PostTaxesGroupTaxComponents; +import org.apache.fineract.client.models.TaxComponentCreateRequest; +import org.apache.fineract.client.models.TaxGroupComponentData; +import org.apache.fineract.client.models.TaxGroupCreateRequest; import org.apache.fineract.integrationtests.common.TaxComponentHelper; import org.apache.fineract.integrationtests.common.TaxGroupHelper; import org.apache.fineract.integrationtests.common.Utils; @@ -365,19 +363,17 @@ public void testChargeUsingPercentageCalculationWithMinAndMaxGapValues() { public void testChargeCreationWithTaxGroup() { final ChargesHelper chargesHelper = new ChargesHelper(); - final PostTaxesComponentsRequest taxComponentRequest = new PostTaxesComponentsRequest() - .name(Utils.randomStringGenerator("TAX_COM_", 4)).percentage(12.0f).startDate("01 January 2023").dateFormat("dd MMMM yyyy") - .locale("en"); + var taxComponentRequest = new TaxComponentCreateRequest().name(Utils.randomStringGenerator("TAX_COM_", 4)) + .percentage(BigDecimal.valueOf(12.0f)).startDate("01 January 2023").dateFormat("dd MMMM yyyy").locale("en"); - final PostTaxesComponentsResponse taxComponentRespose = TaxComponentHelper.createTaxComponent(taxComponentRequest); + var taxComponentRespose = TaxComponentHelper.createTaxComponent(taxComponentRequest); Assertions.assertNotNull(taxComponentRequest); - final Set taxComponentsSet = new HashSet<>(); - taxComponentsSet - .add(new PostTaxesGroupTaxComponents().taxComponentId(taxComponentRespose.getResourceId()).startDate("01 January 2023")); - final PostTaxesGroupRequest taxGroupRequest = new PostTaxesGroupRequest().name(Utils.randomStringGenerator("TAX_GRP_", 4)) - .taxComponents(taxComponentsSet).dateFormat("dd MMMM yyyy").locale("en"); - final PostTaxesGroupResponse taxGroupResponse = TaxGroupHelper.createTaxGroup(taxGroupRequest); + final Set taxComponentsSet = new HashSet<>(); + taxComponentsSet.add(new TaxGroupComponentData().taxComponentId(taxComponentRespose.getResourceId()).startDate("01 January 2023")); + var taxGroupRequest = new TaxGroupCreateRequest().name(Utils.randomStringGenerator("TAX_GRP_", 4)).taxComponents(taxComponentsSet) + .dateFormat("dd MMMM yyyy").locale("en"); + var taxGroupResponse = TaxGroupHelper.createTaxGroup(taxGroupRequest); Assertions.assertNotNull(taxGroupResponse); final PostChargesResponse feeCharge = chargesHelper.createCharges( diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java index cdef3028357..df193b0b50e 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java @@ -41,10 +41,10 @@ import java.util.Locale; import java.util.Set; import org.apache.fineract.client.models.PaymentTypeCreateRequest; -import org.apache.fineract.client.models.PostTaxesComponentsRequest; -import org.apache.fineract.client.models.PostTaxesGroupRequest; -import org.apache.fineract.client.models.PostTaxesGroupTaxComponents; import org.apache.fineract.client.models.PutGlobalConfigurationsRequest; +import org.apache.fineract.client.models.TaxComponentCreateRequest; +import org.apache.fineract.client.models.TaxGroupComponentData; +import org.apache.fineract.client.models.TaxGroupCreateRequest; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.configuration.api.GlobalConfigurationConstants; import org.apache.fineract.integrationtests.common.BusinessDateHelper; @@ -2184,13 +2184,13 @@ private Integer createSavingsProduct(final RequestSpecification requestSpec, fin } private Integer createTaxGroup(final String percentage) { - final PostTaxesComponentsRequest componentRequest = new PostTaxesComponentsRequest() - .name(Utils.randomStringGenerator("Tax_component_Name_", 5)).percentage(Float.parseFloat(percentage)) - .startDate("01 January 2013").dateFormat("dd MMMM yyyy").locale("en"); + var componentRequest = new TaxComponentCreateRequest().name(Utils.randomStringGenerator("Tax_component_Name_", 5)) + .percentage(BigDecimal.valueOf(Float.parseFloat(percentage))).startDate("01 January 2013").dateFormat("dd MMMM yyyy") + .locale("en"); final var componentResponse = TaxComponentHelper.createTaxComponent(componentRequest); - final PostTaxesGroupRequest groupRequest = new PostTaxesGroupRequest().name(Utils.randomStringGenerator("Tax_group_Name_", 5)) - .dateFormat("dd MMMM yyyy").locale("en").taxComponents(Set.of( - new PostTaxesGroupTaxComponents().taxComponentId(componentResponse.getResourceId()).startDate("01 January 2013"))); + var groupRequest = new TaxGroupCreateRequest().name(Utils.randomStringGenerator("Tax_group_Name_", 5)).dateFormat("dd MMMM yyyy") + .locale("en").taxComponents( + Set.of(new TaxGroupComponentData().taxComponentId(componentResponse.getResourceId()).startDate("01 January 2013"))); return TaxGroupHelper.createTaxGroup(groupRequest).getResourceId().intValue(); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/FixedDepositTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/FixedDepositTest.java index 3e06285ea6a..a20683e5915 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/FixedDepositTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/FixedDepositTest.java @@ -49,10 +49,10 @@ import lombok.extern.slf4j.Slf4j; import org.apache.fineract.accounting.common.AccountingConstants.FinancialActivity; import org.apache.fineract.client.models.GetFixedDepositAccountsAccountIdTransactionsResponse; -import org.apache.fineract.client.models.PostTaxesComponentsRequest; -import org.apache.fineract.client.models.PostTaxesGroupRequest; -import org.apache.fineract.client.models.PostTaxesGroupTaxComponents; import org.apache.fineract.client.models.PutGlobalConfigurationsRequest; +import org.apache.fineract.client.models.TaxComponentCreateRequest; +import org.apache.fineract.client.models.TaxGroupComponentData; +import org.apache.fineract.client.models.TaxGroupCreateRequest; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.configuration.api.GlobalConfigurationConstants; import org.apache.fineract.infrastructure.core.api.JsonQuery; @@ -90,7 +90,7 @@ import org.mockito.Mockito; @Slf4j -@SuppressWarnings({ "unused", "unchecked", "rawtypes", "static-access" }) +@SuppressWarnings({ "unused", "unchecked", "rawtypes" }) public class FixedDepositTest extends IntegrationTest { private ResponseSpecification responseSpec; @@ -2947,14 +2947,13 @@ private void assertFinancialActivityAccountCreation(Integer financialActivityAcc } private Integer createTaxGroup(final String percentage, final Account liabilityAccountForTax) { - final PostTaxesComponentsRequest componentRequest = new PostTaxesComponentsRequest() - .name(Utils.randomStringGenerator("Tax_component_Name_", 5)).percentage(Float.parseFloat(percentage)) - .startDate("01 January 2013").dateFormat("dd MMMM yyyy").locale("en").creditAccountType(2) - .creditAccountId(liabilityAccountForTax.getAccountID().longValue()); - final var componentResponse = TaxComponentHelper.createTaxComponent(componentRequest); - final PostTaxesGroupRequest groupRequest = new PostTaxesGroupRequest().name(Utils.randomStringGenerator("Tax_group_Name_", 5)) - .dateFormat("dd MMMM yyyy").locale("en").taxComponents(Set.of( - new PostTaxesGroupTaxComponents().taxComponentId(componentResponse.getResourceId()).startDate("01 January 2013"))); + var componentRequest = new TaxComponentCreateRequest().name(Utils.randomStringGenerator("Tax_component_Name_", 5)) + .percentage(BigDecimal.valueOf(Float.parseFloat(percentage))).startDate("01 January 2013").dateFormat("dd MMMM yyyy") + .locale("en").creditAccountType(2).creditAccountId(liabilityAccountForTax.getAccountID().longValue()); + var componentResponse = TaxComponentHelper.createTaxComponent(componentRequest); + var groupRequest = new TaxGroupCreateRequest().name(Utils.randomStringGenerator("Tax_group_Name_", 5)).dateFormat("dd MMMM yyyy") + .locale("en").taxComponents( + Set.of(new TaxGroupComponentData().taxComponentId(componentResponse.getResourceId()).startDate("01 January 2013"))); return TaxGroupHelper.createTaxGroup(groupRequest).getResourceId().intValue(); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargeTaxIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargeTaxIntegrationTest.java index 71bf8d392dc..cc38176d7c0 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargeTaxIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargeTaxIntegrationTest.java @@ -30,16 +30,15 @@ import org.apache.fineract.client.models.ChargeRequest; import org.apache.fineract.client.models.GetChargesResponse; import org.apache.fineract.client.models.GetLoansLoanIdChargesChargeIdResponse; -import org.apache.fineract.client.models.GetTaxesGroupResponse; import org.apache.fineract.client.models.PostChargesResponse; import org.apache.fineract.client.models.PostLoanProductsRequest; import org.apache.fineract.client.models.PostLoansLoanIdChargesRequest; import org.apache.fineract.client.models.PostLoansLoanIdChargesResponse; -import org.apache.fineract.client.models.PostTaxesComponentsRequest; -import org.apache.fineract.client.models.PostTaxesComponentsResponse; -import org.apache.fineract.client.models.PostTaxesGroupRequest; -import org.apache.fineract.client.models.PostTaxesGroupResponse; -import org.apache.fineract.client.models.PostTaxesGroupTaxComponents; +import org.apache.fineract.client.models.TaxComponentCreateRequest; +import org.apache.fineract.client.models.TaxComponentCreateResponse; +import org.apache.fineract.client.models.TaxGroupComponentData; +import org.apache.fineract.client.models.TaxGroupCreateRequest; +import org.apache.fineract.client.models.TaxGroupCreateResponse; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.TaxComponentHelper; import org.apache.fineract.integrationtests.common.TaxGroupHelper; @@ -72,10 +71,10 @@ public class LoanChargeTaxIntegrationTest extends BaseLoanIntegrationTest { * Creates a TaxComponent with the given percentage and a fixed start date in the past so it is always active during * integration test runs. */ - private PostTaxesComponentsResponse createTaxComponent(float percentage) { - PostTaxesComponentsRequest request = new PostTaxesComponentsRequest().name(Utils.uniqueRandomStringGenerator("TAX_COMP_", 6)) - .percentage(percentage).startDate(TAX_START_DATE).dateFormat(DATE_FORMAT).locale(LOCALE); - PostTaxesComponentsResponse response = TaxComponentHelper.createTaxComponent(request); + private TaxComponentCreateResponse createTaxComponent(float percentage) { + var request = new TaxComponentCreateRequest().name(Utils.uniqueRandomStringGenerator("TAX_COMP_", 6)) + .percentage(BigDecimal.valueOf(percentage)).startDate(TAX_START_DATE).dateFormat(DATE_FORMAT).locale(LOCALE); + var response = TaxComponentHelper.createTaxComponent(request); assertNotNull(response); assertNotNull(response.getResourceId()); return response; @@ -84,14 +83,14 @@ private PostTaxesComponentsResponse createTaxComponent(float percentage) { /** * Wraps a list of already-created TaxComponent IDs into a TaxGroup. */ - private PostTaxesGroupResponse createTaxGroup(Long... taxComponentIds) { - Set components = new HashSet<>(); + private TaxGroupCreateResponse createTaxGroup(Long... taxComponentIds) { + Set components = new HashSet<>(); for (Long id : taxComponentIds) { - components.add(new PostTaxesGroupTaxComponents().taxComponentId(id).startDate(TAX_START_DATE)); + components.add(new TaxGroupComponentData().taxComponentId(id).startDate(TAX_START_DATE)); } - PostTaxesGroupRequest request = new PostTaxesGroupRequest().name(Utils.uniqueRandomStringGenerator("TAX_GRP_", 6)) - .taxComponents(components).dateFormat(DATE_FORMAT).locale(LOCALE); - PostTaxesGroupResponse response = TaxGroupHelper.createTaxGroup(request); + var request = new TaxGroupCreateRequest().name(Utils.uniqueRandomStringGenerator("TAX_GRP_", 6)).taxComponents(components) + .dateFormat(DATE_FORMAT).locale(LOCALE); + var response = TaxGroupHelper.createTaxGroup(request); assertNotNull(response); assertNotNull(response.getResourceId()); return response; @@ -101,11 +100,11 @@ private PostTaxesGroupResponse createTaxGroup(Long... taxComponentIds) { * Creates a TaxComponent with the given percentage, linked to the provided GL account as credit account (tax * liability). The credit account determines where the tax portion is posted in accounting. */ - private PostTaxesComponentsResponse createTaxComponent(float percentage, Long creditAccountId) { - PostTaxesComponentsRequest request = new PostTaxesComponentsRequest().name(Utils.uniqueRandomStringGenerator("TAX_COMP_", 6)) - .percentage(percentage).startDate(TAX_START_DATE).dateFormat(DATE_FORMAT).locale(LOCALE).creditAccountId(creditAccountId) - .creditAccountType(2); - PostTaxesComponentsResponse response = TaxComponentHelper.createTaxComponent(request); + private TaxComponentCreateResponse createTaxComponent(float percentage, Long creditAccountId) { + var request = new TaxComponentCreateRequest().name(Utils.uniqueRandomStringGenerator("TAX_COMP_", 6)) + .percentage(BigDecimal.valueOf(percentage)).startDate(TAX_START_DATE).dateFormat(DATE_FORMAT).locale(LOCALE) + .creditAccountId(creditAccountId).creditAccountType(2); + var response = TaxComponentHelper.createTaxComponent(request); assertNotNull(response); assertNotNull(response.getResourceId()); return response; @@ -178,8 +177,8 @@ private PostChargesResponse createFlatLoanCharge(double baseAmount, Long taxGrou public void testLoanChargeAmount_remainsUnchanged_whenTaxGroupIsConfigured() { runAt(LOAN_DATE, () -> { // Given – tax infrastructure - PostTaxesComponentsResponse taxComponent = createTaxComponent(10.0f); - PostTaxesGroupResponse taxGroup = createTaxGroup(taxComponent.getResourceId()); + var taxComponent = createTaxComponent(10.0f); + var taxGroup = createTaxGroup(taxComponent.getResourceId()); // Given – charge definition with 10 % tax group, base = 100 PostChargesResponse chargeResponse = createFlatLoanCharge(100.0, taxGroup.getResourceId()); @@ -220,9 +219,9 @@ public void testLoanChargeAmount_remainsUnchanged_whenTaxGroupIsConfigured() { public void testLoanChargeAmount_remainsUnchanged_multipleComponents() { runAt(LOAN_DATE, () -> { // Given – two tax components in the same group - PostTaxesComponentsResponse comp1 = createTaxComponent(10.0f); - PostTaxesComponentsResponse comp2 = createTaxComponent(5.0f); - PostTaxesGroupResponse taxGroup = createTaxGroup(comp1.getResourceId(), comp2.getResourceId()); + var comp1 = createTaxComponent(10.0f); + var comp2 = createTaxComponent(5.0f); + var taxGroup = createTaxGroup(comp1.getResourceId(), comp2.getResourceId()); PostChargesResponse chargeResponse = createFlatLoanCharge(200.0, taxGroup.getResourceId()); @@ -285,8 +284,8 @@ public void testLoanChargeAmount_noTaxGroup_isNotModified() { @Test public void testChargeDefinition_hasTaxGroupPopulated() { // Given – tax infrastructure (no loan needed for this test) - PostTaxesComponentsResponse taxComponent = createTaxComponent(16.0f); - PostTaxesGroupResponse taxGroup = createTaxGroup(taxComponent.getResourceId()); + var taxComponent = createTaxComponent(16.0f); + var taxGroup = createTaxGroup(taxComponent.getResourceId()); // When – create charge linked to the tax group PostChargesResponse chargeResponse = createFlatLoanCharge(50.0, taxGroup.getResourceId()); @@ -311,11 +310,11 @@ public void testChargeDefinition_hasTaxGroupPopulated() { @Test public void testTaxGroupRetrieval_includesExpectedComponent() { // Given - PostTaxesComponentsResponse taxComponent = createTaxComponent(12.0f); - PostTaxesGroupResponse taxGroup = createTaxGroup(taxComponent.getResourceId()); + var taxComponent = createTaxComponent(12.0f); + var taxGroup = createTaxGroup(taxComponent.getResourceId()); // When - GetTaxesGroupResponse retrieved = TaxGroupHelper.retrieveTaxGroup(taxGroup.getResourceId()); + var retrieved = TaxGroupHelper.retrieveTaxGroup(taxGroup.getResourceId()); // Then assertNotNull(retrieved); @@ -336,11 +335,11 @@ public void testTaxGroupRetrieval_includesExpectedComponent() { @Test public void testTaxGroup_appearsInRetrieveAllList() { // Given - PostTaxesComponentsResponse taxComponent = createTaxComponent(8.0f); - PostTaxesGroupResponse taxGroup = createTaxGroup(taxComponent.getResourceId()); + var taxComponent = createTaxComponent(8.0f); + var taxGroup = createTaxGroup(taxComponent.getResourceId()); // When - List allGroups = TaxGroupHelper.retrieveAllTaxGroups(); + var allGroups = TaxGroupHelper.retrieveAllTaxGroups(); // Then assertNotNull(allGroups); @@ -360,8 +359,8 @@ public void testTaxGroup_appearsInRetrieveAllList() { public void testLoanChargeTax_appliedIndependentlyToEachLoan() { runAt(LOAN_DATE, () -> { // Given – shared charge definition with 10 % tax - PostTaxesComponentsResponse taxComponent = createTaxComponent(10.0f); - PostTaxesGroupResponse taxGroup = createTaxGroup(taxComponent.getResourceId()); + var taxComponent = createTaxComponent(10.0f); + var taxGroup = createTaxGroup(taxComponent.getResourceId()); PostChargesResponse chargeResponse = createFlatLoanCharge(100.0, taxGroup.getResourceId()); Long chargeDefinitionId = chargeResponse.getResourceId(); @@ -415,8 +414,8 @@ public void testCashAccounting_journalEntries_feeWithTaxSplitsIncomeAndLiability Account taxLiabilityAccount = accountHelper.createLiabilityAccount("taxLiability_cash"); // Given – tax infrastructure linked to the tax liability account - PostTaxesComponentsResponse taxComponent = createTaxComponent(10.0f, taxLiabilityAccount.getAccountID().longValue()); - PostTaxesGroupResponse taxGroup = createTaxGroup(taxComponent.getResourceId()); + var taxComponent = createTaxComponent(10.0f, taxLiabilityAccount.getAccountID().longValue()); + var taxGroup = createTaxGroup(taxComponent.getResourceId()); // Given – flat charge of 100 with 10 % tax, due on the loan start date PostChargesResponse chargeResponse = createFlatLoanCharge(100.0, taxGroup.getResourceId()); @@ -476,8 +475,8 @@ public void testAccrualAccounting_journalEntries_feeWithTaxSplitsIncomeAndLiabil Account taxLiabilityAccount = accountHelper.createLiabilityAccount("taxLiability_accrual"); // Given – tax infrastructure linked to the tax liability account - PostTaxesComponentsResponse taxComponent = createTaxComponent(10.0f, taxLiabilityAccount.getAccountID().longValue()); - PostTaxesGroupResponse taxGroup = createTaxGroup(taxComponent.getResourceId()); + var taxComponent = createTaxComponent(10.0f, taxLiabilityAccount.getAccountID().longValue()); + var taxGroup = createTaxGroup(taxComponent.getResourceId()); // Given – flat charge of 100 with 10 % tax, due on the loan start date PostChargesResponse chargeResponse = createFlatLoanCharge(100.0, taxGroup.getResourceId()); @@ -525,8 +524,8 @@ public void testAccrualAccounting_journalEntries_feeWithTaxSplitsIncomeAndLiabil public void testLoanChargeList_containsOriginalAmount() { runAt(LOAN_DATE, () -> { // Given - PostTaxesComponentsResponse taxComponent = createTaxComponent(10.0f); - PostTaxesGroupResponse taxGroup = createTaxGroup(taxComponent.getResourceId()); + var taxComponent = createTaxComponent(10.0f); + var taxGroup = createTaxGroup(taxComponent.getResourceId()); PostChargesResponse chargeResponse = createFlatLoanCharge(100.0, taxGroup.getResourceId()); Long clientId = ClientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId(); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/RecurringDepositTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/RecurringDepositTest.java index 36a0d73b1e7..b69482a2207 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/RecurringDepositTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/RecurringDepositTest.java @@ -25,6 +25,7 @@ import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.time.LocalDate; @@ -40,9 +41,9 @@ import java.util.Set; import java.util.TimeZone; import org.apache.fineract.accounting.common.AccountingConstants.FinancialActivity; -import org.apache.fineract.client.models.PostTaxesComponentsRequest; -import org.apache.fineract.client.models.PostTaxesGroupRequest; -import org.apache.fineract.client.models.PostTaxesGroupTaxComponents; +import org.apache.fineract.client.models.TaxComponentCreateRequest; +import org.apache.fineract.client.models.TaxGroupComponentData; +import org.apache.fineract.client.models.TaxGroupCreateRequest; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.CommonConstants; import org.apache.fineract.integrationtests.common.SchedulerJobHelper; @@ -3100,14 +3101,13 @@ private void assertFinancialActivityAccountCreation(Integer financialActivityAcc } private Integer createTaxGroup(final String percentage, final Account liabilityAccountForTax) { - final PostTaxesComponentsRequest componentRequest = new PostTaxesComponentsRequest() - .name(Utils.randomStringGenerator("Tax_component_Name_", 5)).percentage(Float.parseFloat(percentage)) - .startDate("01 January 2013").dateFormat("dd MMMM yyyy").locale("en").creditAccountType(2) - .creditAccountId(liabilityAccountForTax.getAccountID().longValue()); + var componentRequest = new TaxComponentCreateRequest().name(Utils.randomStringGenerator("Tax_component_Name_", 5)) + .percentage(BigDecimal.valueOf(Float.parseFloat(percentage))).startDate("01 January 2013").dateFormat("dd MMMM yyyy") + .locale("en").creditAccountType(2).creditAccountId(liabilityAccountForTax.getAccountID().longValue()); final var componentResponse = TaxComponentHelper.createTaxComponent(componentRequest); - final PostTaxesGroupRequest groupRequest = new PostTaxesGroupRequest().name(Utils.randomStringGenerator("Tax_group_Name_", 5)) - .dateFormat("dd MMMM yyyy").locale("en").taxComponents(Set.of( - new PostTaxesGroupTaxComponents().taxComponentId(componentResponse.getResourceId()).startDate("01 January 2013"))); + var groupRequest = new TaxGroupCreateRequest().name(Utils.randomStringGenerator("Tax_group_Name_", 5)).dateFormat("dd MMMM yyyy") + .locale("en").taxComponents( + Set.of(new TaxGroupComponentData().taxComponentId(componentResponse.getResourceId()).startDate("01 January 2013"))); return TaxGroupHelper.createTaxGroup(groupRequest).getResourceId().intValue(); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/TaxesTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/TaxesTest.java index 3d62ad28f8f..69b65fd5cf0 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/TaxesTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/TaxesTest.java @@ -21,18 +21,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.math.BigDecimal; import java.util.HashSet; -import java.util.List; import java.util.Set; import org.apache.fineract.client.feign.util.CallFailedRuntimeException; -import org.apache.fineract.client.models.GetTaxesComponentsResponse; -import org.apache.fineract.client.models.GetTaxesGroupResponse; -import org.apache.fineract.client.models.GetTaxesGroupTaxAssociations; -import org.apache.fineract.client.models.PostTaxesComponentsRequest; -import org.apache.fineract.client.models.PostTaxesComponentsResponse; -import org.apache.fineract.client.models.PostTaxesGroupRequest; -import org.apache.fineract.client.models.PostTaxesGroupResponse; -import org.apache.fineract.client.models.PostTaxesGroupTaxComponents; +import org.apache.fineract.client.models.TaxComponentCreateRequest; +import org.apache.fineract.client.models.TaxGroupComponentData; +import org.apache.fineract.client.models.TaxGroupCreateRequest; import org.apache.fineract.integrationtests.client.feign.helpers.FeignTaxComponentHelper; import org.apache.fineract.integrationtests.client.feign.helpers.FeignTaxGroupHelper; import org.apache.fineract.integrationtests.common.FineractFeignClientHelper; @@ -58,7 +53,7 @@ public void setup() { public void createTaxComponentTest() { Long taxComponentId = createTaxComponentWithLiabilityToCredit("taxComponent"); - GetTaxesComponentsResponse taxComponentDetails = taxComponentHelper.retrieveTaxComponent(taxComponentId); + var taxComponentDetails = taxComponentHelper.retrieveTaxComponent(taxComponentId); Assertions.assertNotNull(taxComponentDetails); Assertions.assertNotNull(taxComponentDetails.getId()); Assertions.assertEquals(taxComponentId, taxComponentDetails.getId()); @@ -73,24 +68,24 @@ public void createTaxComponentTest() { @Test public void createTaxGroupTest() { - List allTaxGroups = taxGroupHelper.retrieveAllTaxGroups(); + var allTaxGroups = taxGroupHelper.retrieveAllTaxGroups(); Assertions.assertNotNull(allTaxGroups); final Long taxComponentId = createTaxComponentWithLiabilityToCredit("taxComponent"); - final Set taxComponentsSet = new HashSet<>(); - taxComponentsSet.add(new PostTaxesGroupTaxComponents().taxComponentId(taxComponentId).startDate("01 January 2023")); - final PostTaxesGroupRequest taxGroupRequest = new PostTaxesGroupRequest().name(Utils.randomStringGenerator("TAX_GRP_", 4)) - .taxComponents(taxComponentsSet).dateFormat("dd MMMM yyyy").locale("en"); - final PostTaxesGroupResponse taxGroupResponse = taxGroupHelper.createTaxGroup(taxGroupRequest); + final Set taxComponentsSet = new HashSet<>(); + taxComponentsSet.add(new TaxGroupComponentData().taxComponentId(taxComponentId).startDate("01 January 2023")); + var taxGroupRequest = new TaxGroupCreateRequest().name(Utils.randomStringGenerator("TAX_GRP_", 4)).taxComponents(taxComponentsSet) + .dateFormat("dd MMMM yyyy").locale("en"); + var taxGroupResponse = taxGroupHelper.createTaxGroup(taxGroupRequest); Assertions.assertNotNull(taxGroupResponse); Assertions.assertNotNull(taxGroupResponse.getResourceId()); - final GetTaxesGroupResponse taxGroupDetails = taxGroupHelper.retrieveTaxGroup(taxGroupResponse.getResourceId()); + var taxGroupDetails = taxGroupHelper.retrieveTaxGroup(taxGroupResponse.getResourceId()); Assertions.assertNotNull(taxGroupDetails); Assertions.assertEquals(taxGroupResponse.getResourceId(), taxGroupDetails.getId()); Assertions.assertFalse(taxGroupDetails.getTaxAssociations().isEmpty()); - GetTaxesGroupTaxAssociations taxAssociation = taxGroupDetails.getTaxAssociations().iterator().next(); + var taxAssociation = taxGroupDetails.getTaxAssociations().iterator().next(); Assertions.assertNotNull(taxAssociation); Assertions.assertEquals(taxComponentId, taxAssociation.getTaxComponent().getId()); @@ -102,12 +97,12 @@ public void createTaxGroupTest() { private Long createTaxComponentWithLiabilityToCredit(final String taxComponentPrefix) { final Account taxComponentGlAccount = AccountHelper.createLiabilityGlAccount(taxComponentPrefix); - final PostTaxesComponentsRequest taxComponentRequest = new PostTaxesComponentsRequest() - .name(Utils.randomStringGenerator(taxComponentPrefix, 4)).percentage(12.0f).startDate("01 January 2023") + var taxComponentRequest = new TaxComponentCreateRequest().name(Utils.randomStringGenerator(taxComponentPrefix, 4)) + .percentage(BigDecimal.valueOf(12.0f)).startDate("01 January 2023") .creditAccountType(Integer.valueOf(taxComponentGlAccount.getAccountType().toString())) .creditAccountId(taxComponentGlAccount.getAccountID().longValue()).dateFormat(Utils.DATE_FORMAT).locale(Utils.LOCALE); - final PostTaxesComponentsResponse taxComponentRespose = taxComponentHelper.createTaxComponent(taxComponentRequest); + var taxComponentRespose = taxComponentHelper.createTaxComponent(taxComponentRequest); Assertions.assertNotNull(taxComponentRespose); Assertions.assertNotNull(taxComponentRespose.getResourceId()); @@ -117,12 +112,12 @@ private Long createTaxComponentWithLiabilityToCredit(final String taxComponentPr private Long createTaxComponentWithLiabilityToDebit(final String taxComponentPrefix) { final Account taxComponentGlAccount = AccountHelper.createLiabilityGlAccount(taxComponentPrefix); - final PostTaxesComponentsRequest taxComponentRequest = new PostTaxesComponentsRequest() - .name(Utils.randomStringGenerator(taxComponentPrefix, 4)).percentage(12.0f).startDate("01 January 2023") + var taxComponentRequest = new TaxComponentCreateRequest().name(Utils.randomStringGenerator(taxComponentPrefix, 4)) + .percentage(BigDecimal.valueOf(12.0f)).startDate("01 January 2023") .debitAccountType(Integer.valueOf(taxComponentGlAccount.getAccountType().toString())) .debitAccountId(taxComponentGlAccount.getAccountID().longValue()).dateFormat(Utils.DATE_FORMAT).locale(Utils.LOCALE); - final PostTaxesComponentsResponse taxComponentRespose = taxComponentHelper.createTaxComponent(taxComponentRequest); + var taxComponentRespose = taxComponentHelper.createTaxComponent(taxComponentRequest); Assertions.assertNotNull(taxComponentRespose); Assertions.assertNotNull(taxComponentRespose.getResourceId()); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignTaxComponentHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignTaxComponentHelper.java index f50b234bb0d..6edbb4ca9eb 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignTaxComponentHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignTaxComponentHelper.java @@ -23,9 +23,9 @@ import org.apache.fineract.client.feign.FineractFeignClient; import org.apache.fineract.client.feign.util.CallFailedRuntimeException; -import org.apache.fineract.client.models.GetTaxesComponentsResponse; -import org.apache.fineract.client.models.PostTaxesComponentsRequest; -import org.apache.fineract.client.models.PostTaxesComponentsResponse; +import org.apache.fineract.client.models.TaxComponentCreateRequest; +import org.apache.fineract.client.models.TaxComponentCreateResponse; +import org.apache.fineract.client.models.TaxComponentData; public class FeignTaxComponentHelper { @@ -35,11 +35,11 @@ public FeignTaxComponentHelper(FineractFeignClient fineractClient) { this.fineractClient = fineractClient; } - public PostTaxesComponentsResponse createTaxComponent(PostTaxesComponentsRequest request) { + public TaxComponentCreateResponse createTaxComponent(TaxComponentCreateRequest request) { return ok(() -> fineractClient.taxComponents().createTaxComponent(request)); } - public GetTaxesComponentsResponse retrieveTaxComponent(Long taxComponentId) { + public TaxComponentData retrieveTaxComponent(Long taxComponentId) { return ok(() -> fineractClient.taxComponents().retrieveOneTaxComponent(taxComponentId)); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignTaxGroupHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignTaxGroupHelper.java index bd0a6495042..68e6f62132f 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignTaxGroupHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignTaxGroupHelper.java @@ -24,9 +24,9 @@ import java.util.List; import org.apache.fineract.client.feign.FineractFeignClient; import org.apache.fineract.client.feign.util.CallFailedRuntimeException; -import org.apache.fineract.client.models.GetTaxesGroupResponse; -import org.apache.fineract.client.models.PostTaxesGroupRequest; -import org.apache.fineract.client.models.PostTaxesGroupResponse; +import org.apache.fineract.client.models.TaxGroupCreateRequest; +import org.apache.fineract.client.models.TaxGroupCreateResponse; +import org.apache.fineract.client.models.TaxGroupData; public class FeignTaxGroupHelper { @@ -36,19 +36,19 @@ public FeignTaxGroupHelper(FineractFeignClient fineractClient) { this.fineractClient = fineractClient; } - public PostTaxesGroupResponse createTaxGroup(PostTaxesGroupRequest request) { + public TaxGroupCreateResponse createTaxGroup(TaxGroupCreateRequest request) { return ok(() -> fineractClient.taxGroup().createTaxGroup(request)); } - public GetTaxesGroupResponse retrieveTaxGroup(Long taxGroupId) { - return ok(() -> fineractClient.taxGroup().retrieveOneTaxGroup(taxGroupId)); + public TaxGroupData retrieveTaxGroup(Long taxGroupId) { + return ok(() -> fineractClient.taxGroup().retrieveOneTaxGroup(taxGroupId, false)); } - public List retrieveAllTaxGroups() { + public List retrieveAllTaxGroups() { return ok(() -> fineractClient.taxGroup().retrieveAllTaxGroups()); } public CallFailedRuntimeException retrieveTaxGroupExpectingError(Long taxGroupId) { - return fail(() -> fineractClient.taxGroup().retrieveOneTaxGroup(taxGroupId)); + return fail(() -> fineractClient.taxGroup().retrieveOneTaxGroup(taxGroupId, false)); } } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/TaxComponentHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/TaxComponentHelper.java index 98b89341b7f..af1a858f258 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/TaxComponentHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/TaxComponentHelper.java @@ -20,19 +20,19 @@ import static org.apache.fineract.client.feign.util.FeignCalls.ok; -import org.apache.fineract.client.models.GetTaxesComponentsResponse; -import org.apache.fineract.client.models.PostTaxesComponentsRequest; -import org.apache.fineract.client.models.PostTaxesComponentsResponse; +import org.apache.fineract.client.models.TaxComponentCreateRequest; +import org.apache.fineract.client.models.TaxComponentCreateResponse; +import org.apache.fineract.client.models.TaxComponentData; public final class TaxComponentHelper { private TaxComponentHelper() {} - public static PostTaxesComponentsResponse createTaxComponent(PostTaxesComponentsRequest request) { + public static TaxComponentCreateResponse createTaxComponent(TaxComponentCreateRequest request) { return ok(() -> FineractFeignClientHelper.getFineractFeignClient().taxComponents().createTaxComponent(request)); } - public static GetTaxesComponentsResponse retrieveTaxComponent(Long taxComponentId) { + public static TaxComponentData retrieveTaxComponent(Long taxComponentId) { return ok(() -> FineractFeignClientHelper.getFineractFeignClient().taxComponents().retrieveOneTaxComponent(taxComponentId)); } } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/TaxGroupHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/TaxGroupHelper.java index 826cde5df37..b0148e74051 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/TaxGroupHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/TaxGroupHelper.java @@ -21,23 +21,23 @@ import static org.apache.fineract.client.feign.util.FeignCalls.ok; import java.util.List; -import org.apache.fineract.client.models.GetTaxesGroupResponse; -import org.apache.fineract.client.models.PostTaxesGroupRequest; -import org.apache.fineract.client.models.PostTaxesGroupResponse; +import org.apache.fineract.client.models.TaxGroupCreateRequest; +import org.apache.fineract.client.models.TaxGroupCreateResponse; +import org.apache.fineract.client.models.TaxGroupData; public final class TaxGroupHelper { private TaxGroupHelper() {} - public static PostTaxesGroupResponse createTaxGroup(PostTaxesGroupRequest request) { + public static TaxGroupCreateResponse createTaxGroup(TaxGroupCreateRequest request) { return ok(() -> FineractFeignClientHelper.getFineractFeignClient().taxGroup().createTaxGroup(request)); } - public static GetTaxesGroupResponse retrieveTaxGroup(Long taxGroupId) { - return ok(() -> FineractFeignClientHelper.getFineractFeignClient().taxGroup().retrieveOneTaxGroup(taxGroupId)); + public static TaxGroupData retrieveTaxGroup(Long taxGroupId) { + return ok(() -> FineractFeignClientHelper.getFineractFeignClient().taxGroup().retrieveOneTaxGroup(taxGroupId, false)); } - public static List retrieveAllTaxGroups() { + public static List retrieveAllTaxGroups() { return ok(() -> FineractFeignClientHelper.getFineractFeignClient().taxGroup().retrieveAllTaxGroups()); } }