From 3acf0d67dbc842bba0f8060d581edc2019490b95 Mon Sep 17 00:00:00 2001 From: Sukhvir Singh Date: Thu, 18 Jul 2024 17:29:00 -0500 Subject: [PATCH 1/2] Validate if we can create tax item with custom details --- .../plugin/vertex/VertexTaxCalculator.java | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/killbill/billing/plugin/vertex/VertexTaxCalculator.java b/src/main/java/org/killbill/billing/plugin/vertex/VertexTaxCalculator.java index 7795e7e..2ea4f9c 100644 --- a/src/main/java/org/killbill/billing/plugin/vertex/VertexTaxCalculator.java +++ b/src/main/java/org/killbill/billing/plugin/vertex/VertexTaxCalculator.java @@ -38,6 +38,8 @@ import org.killbill.billing.osgi.libs.killbill.OSGIKillbillAPI; import org.killbill.billing.payment.api.PluginProperty; import org.killbill.billing.plugin.api.PluginProperties; +import org.killbill.billing.plugin.api.invoice.PluginInvoiceItem; +import org.killbill.billing.plugin.api.invoice.PluginInvoiceItem.Builder; import org.killbill.billing.plugin.api.invoice.PluginTaxCalculator; import org.killbill.billing.plugin.vertex.dao.VertexDao; import org.killbill.billing.plugin.vertex.gen.ApiException; @@ -298,7 +300,37 @@ private Collection toInvoiceItems(final UUID invoiceId, final BigDecimal calculatedTax = transactionLineDetailModel.getCalculatedTax() != null ? BigDecimal.valueOf(transactionLineDetailModel.getCalculatedTax()) : null; final InvoiceItem taxItem = buildTaxItem(taxableItem, invoiceId, adjustmentItem, calculatedTax, description); if (taxItem != null) { - invoiceItems.add(taxItem); + final InvoiceItem taxItemDerived = new PluginInvoiceItem(new Builder<>() + .withId(taxItem.getId()) + .withInvoiceItemType(taxItem.getInvoiceItemType()) + .withInvoiceId(taxItem.getInvoiceId()) + .withAccountId(taxItem.getAccountId()) + .withChildAccountId(taxItem.getChildAccountId()) + .withStartDate(taxItem.getStartDate()) + .withEndDate(taxItem.getEndDate()) + .withAmount(taxItem.getAmount()) + .withCurrency(taxItem.getCurrency()) + .withDescription(taxItem.getDescription()) + .withSubscriptionId(taxItem.getSubscriptionId()) + .withBundleId(taxItem.getBundleId()) + .withCatalogEffectiveDate(taxItem.getCatalogEffectiveDate()) + .withProductName(taxItem.getProductName()) + .withPrettyProductName(taxItem.getPrettyProductName()) + .withPlanName(taxItem.getPlanName()) + .withPrettyPlanName(taxItem.getPrettyPlanName()) + .withPhaseName(taxItem.getPhaseName()) + .withPrettyPhaseName(taxItem.getPrettyPhaseName()) + .withRate(taxItem.getRate()) + .withLinkedItemId(taxItem.getLinkedItemId()) + .withUsageName(taxItem.getUsageName()) + .withPrettyUsageName(taxItem.getPrettyUsageName()) + .withQuantity(taxItem.getQuantity()) + .withItemDetails("gelatic fussion") + .withCreatedDate(taxItem.getCreatedDate()) + .withUpdatedDate(taxItem.getUpdatedDate()) + .validate().build() + ); + invoiceItems.add(taxItemDerived); } } return invoiceItems; From 8c3fac345fc6159a9a08aa2bebe7d4304e3c6026 Mon Sep 17 00:00:00 2001 From: Vlas Khilkevich <93208596+vlaskhilkevich@users.noreply.github.com> Date: Mon, 22 Jul 2024 12:21:47 +0200 Subject: [PATCH 2/2] save effective rate in tax invoice items --- .../plugin/vertex/VertexTaxCalculator.java | 63 ++++++++++--------- .../vertex/VertexTaxCalculatorTest.java | 36 ++++++++++- 2 files changed, 67 insertions(+), 32 deletions(-) diff --git a/src/main/java/org/killbill/billing/plugin/vertex/VertexTaxCalculator.java b/src/main/java/org/killbill/billing/plugin/vertex/VertexTaxCalculator.java index 2ea4f9c..1c7c2ac 100644 --- a/src/main/java/org/killbill/billing/plugin/vertex/VertexTaxCalculator.java +++ b/src/main/java/org/killbill/billing/plugin/vertex/VertexTaxCalculator.java @@ -300,37 +300,38 @@ private Collection toInvoiceItems(final UUID invoiceId, final BigDecimal calculatedTax = transactionLineDetailModel.getCalculatedTax() != null ? BigDecimal.valueOf(transactionLineDetailModel.getCalculatedTax()) : null; final InvoiceItem taxItem = buildTaxItem(taxableItem, invoiceId, adjustmentItem, calculatedTax, description); if (taxItem != null) { - final InvoiceItem taxItemDerived = new PluginInvoiceItem(new Builder<>() - .withId(taxItem.getId()) - .withInvoiceItemType(taxItem.getInvoiceItemType()) - .withInvoiceId(taxItem.getInvoiceId()) - .withAccountId(taxItem.getAccountId()) - .withChildAccountId(taxItem.getChildAccountId()) - .withStartDate(taxItem.getStartDate()) - .withEndDate(taxItem.getEndDate()) - .withAmount(taxItem.getAmount()) - .withCurrency(taxItem.getCurrency()) - .withDescription(taxItem.getDescription()) - .withSubscriptionId(taxItem.getSubscriptionId()) - .withBundleId(taxItem.getBundleId()) - .withCatalogEffectiveDate(taxItem.getCatalogEffectiveDate()) - .withProductName(taxItem.getProductName()) - .withPrettyProductName(taxItem.getPrettyProductName()) - .withPlanName(taxItem.getPlanName()) - .withPrettyPlanName(taxItem.getPrettyPlanName()) - .withPhaseName(taxItem.getPhaseName()) - .withPrettyPhaseName(taxItem.getPrettyPhaseName()) - .withRate(taxItem.getRate()) - .withLinkedItemId(taxItem.getLinkedItemId()) - .withUsageName(taxItem.getUsageName()) - .withPrettyUsageName(taxItem.getPrettyUsageName()) - .withQuantity(taxItem.getQuantity()) - .withItemDetails("gelatic fussion") - .withCreatedDate(taxItem.getCreatedDate()) - .withUpdatedDate(taxItem.getUpdatedDate()) - .validate().build() - ); - invoiceItems.add(taxItemDerived); + final InvoiceItem taxItemWithEffectiveRate = transactionLineDetailModel.getEffectiveRate() != null + ? new PluginInvoiceItem(new Builder<>() + .withId(taxItem.getId()) + .withInvoiceItemType(taxItem.getInvoiceItemType()) + .withInvoiceId(taxItem.getInvoiceId()) + .withAccountId(taxItem.getAccountId()) + .withChildAccountId(taxItem.getChildAccountId()) + .withStartDate(taxItem.getStartDate()) + .withEndDate(taxItem.getEndDate()) + .withAmount(taxItem.getAmount()) + .withCurrency(taxItem.getCurrency()) + .withDescription(taxItem.getDescription()) + .withSubscriptionId(taxItem.getSubscriptionId()) + .withBundleId(taxItem.getBundleId()) + .withCatalogEffectiveDate(taxItem.getCatalogEffectiveDate()) + .withProductName(taxItem.getProductName()) + .withPrettyProductName(taxItem.getPrettyProductName()) + .withPlanName(taxItem.getPlanName()) + .withPrettyPlanName(taxItem.getPrettyPlanName()) + .withPhaseName(taxItem.getPhaseName()) + .withPrettyPhaseName(taxItem.getPrettyPhaseName()) + .withRate(taxItem.getRate()) + .withLinkedItemId(taxItem.getLinkedItemId()) + .withUsageName(taxItem.getUsageName()) + .withPrettyUsageName(taxItem.getPrettyUsageName()) + .withQuantity(taxItem.getQuantity()) + .withItemDetails(String.valueOf(transactionLineDetailModel.getEffectiveRate())) + .withCreatedDate(taxItem.getCreatedDate()) + .withUpdatedDate(taxItem.getUpdatedDate()) + .validate().build()) + : taxItem; + invoiceItems.add(taxItemWithEffectiveRate); } } return invoiceItems; diff --git a/src/test/java/org/killbill/billing/plugin/vertex/VertexTaxCalculatorTest.java b/src/test/java/org/killbill/billing/plugin/vertex/VertexTaxCalculatorTest.java index 8de7176..0c9e6e3 100644 --- a/src/test/java/org/killbill/billing/plugin/vertex/VertexTaxCalculatorTest.java +++ b/src/test/java/org/killbill/billing/plugin/vertex/VertexTaxCalculatorTest.java @@ -58,6 +58,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertNull; public class VertexTaxCalculatorTest { @@ -157,7 +158,6 @@ public void testCompute() throws Exception { //given given(taxResponse.getData()).willReturn(apiResponseData); given(invoice.getInvoiceItems()).willReturn(Collections.singletonList(taxableInvoiceItem)); - final boolean isDryRun = false; //when @@ -231,6 +231,40 @@ public void testTaxDescription() throws Exception { assertEquals("CA STATE TAX", result.get(0).getDescription()); } + @Test(groups = "fast") + public void testTaxEffectiveRate() throws Exception { + //given + given(invoice.getInvoiceItems()).willReturn(Collections.singletonList(taxableInvoiceItem)); + given(taxResponse.getData()).willReturn(apiResponseData); + final TaxesType taxesType = new TaxesType(); + taxesType.setCalculatedTax(MOCK_TAX_AMOUNT_1_01); + given(responseLineItem.getTaxes()).willReturn(Collections.singletonList(taxesType)); + + //given tax effective rate is present + taxesType.setEffectiveRate(0.09975d); + + //then it persisted in item details invoice item field + List result = vertexTaxCalculator.compute(account, invoice, true, Collections.emptyList(), tenantContext); + assertEquals("0.09975", result.get(0).getItemDetails()); + checkTaxItemFields(result.get(0)); + + //given effective rate is not present + taxesType.setEffectiveRate(null); + + //then no item details persisted + result = vertexTaxCalculator.compute(account, invoice, true, Collections.emptyList(), tenantContext); + assertNull(result.get(0).getItemDetails()); + checkTaxItemFields(result.get(0)); + } + + private void checkTaxItemFields(final InvoiceItem taxItem) { + assertEquals(InvoiceItemType.TAX, taxItem.getInvoiceItemType()); + assertEquals("Tax", taxItem.getDescription()); + assertEquals(INVOICE_ID, taxItem.getInvoiceId()); + assertEquals(INVOICE_DATE, taxItem.getStartDate()); + assertEquals(INVOICE_DATE.plusMonths(1), taxItem.getEndDate()); + } + @Test(groups = "fast", expectedExceptions = {IllegalStateException.class}) public void testComputeWithAnomalousAdjustmentsException() throws Exception { //given