From e2fef33f151ac4f3451757db639e52c5ae62fb59 Mon Sep 17 00:00:00 2001 From: "Rym.Ghosn" Date: Tue, 18 Aug 2026 16:43:15 +0300 Subject: [PATCH] FINERACT-2748: Add validation for at least one Tax Component in TaxGroup submission Submitting a Tax Group without any tax components previously failed only on the generic integerGreaterThanZero check, without a clear message. This adds an explicit validation error (validation.msg.at.least.one.tax.component.required) with a user-friendly message ("Please add at least one Tax Component before submitting the Tax Group.") when the taxComponents array is empty. Added an integration test (TaxesTest#createTaxGroupWithoutTaxComponent_shouldReturnValidationError) covering the new validation path. --- .../portfolio/tax/serialization/TaxValidator.java | 4 ++++ .../fineract/integrationtests/TaxesTest.java | 14 ++++++++++++++ .../client/feign/helpers/FeignTaxGroupHelper.java | 4 ++++ 3 files changed, 22 insertions(+) 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 index 37898b021f5..05a2ea87933 100644 --- 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 @@ -192,6 +192,10 @@ public void validateForTaxGroupCreate(final String json) { final JsonObject topLevelJsonElement = element.getAsJsonObject(); if (topLevelJsonElement.get(TaxApiConstants.taxComponentsParamName).isJsonArray()) { final JsonArray array = topLevelJsonElement.get(TaxApiConstants.taxComponentsParamName).getAsJsonArray(); + if (array.isEmpty()) { + dataValidationErrors.add(ApiParameterError.parameterError("validation.msg.at.least.one.tax.component.required", + "Please add at least one Tax Component before submitting the Tax Group.", TaxApiConstants.taxComponentsParamName)); + } 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(); 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..1f01f353af3 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 @@ -151,4 +151,18 @@ void retrieveTaxComponentWithNonExistentId_shouldReturn404() { "Response should contain the error code for tax component not found"); } + @Test + void createTaxGroupWithoutTaxComponent_shouldReturnValidationError() { + final PostTaxesGroupRequest taxGroupRequest = new PostTaxesGroupRequest().name(Utils.randomStringGenerator("TAX_GRP_", 4)) + .taxComponents(new HashSet<>()).dateFormat("dd MMMM yyyy").locale("en"); + + CallFailedRuntimeException exception = taxGroupHelper.createTaxGroupExpectingError(taxGroupRequest); + + assertEquals(400, exception.getStatus()); + assertTrue(exception.getMessage().contains("validation.msg.at.least.one.tax.component.required"), + "Response should contain the error code requiring at least one tax component"); + assertTrue(exception.getMessage().contains("Please add at least one Tax Component before submitting the Tax Group."), + "Response should contain the user friendly validation message"); + } + } 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..9d267c59eea 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 @@ -51,4 +51,8 @@ public List retrieveAllTaxGroups() { public CallFailedRuntimeException retrieveTaxGroupExpectingError(Long taxGroupId) { return fail(() -> fineractClient.taxGroup().retrieveOneTaxGroup(taxGroupId)); } + + public CallFailedRuntimeException createTaxGroupExpectingError(PostTaxesGroupRequest request) { + return fail(() -> fineractClient.taxGroup().createTaxGroup(request)); + } }