Skip to content

Commit

Permalink
Simplify, avoid dependency on kb invoice module and update jackson ve…
Browse files Browse the repository at this point in the history
…rsion without vulnerability
  • Loading branch information
vlaskhilkevich committed Aug 13, 2024
1 parent 2df6471 commit 028ba4a
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 150 deletions.
9 changes: 3 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,23 @@
<properties>
<check.spotbugs-exclude-filter-file>spotbugs-exclude.xml</check.spotbugs-exclude-filter-file>
<jooq.version>3.14.15</jooq.version>
<killbill.version>0.22.32</killbill.version>
<osgi.private>org.killbill.billing.plugin.vertex.*</osgi.private>
</properties>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.13.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.13.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.4.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
Expand Down Expand Up @@ -156,11 +158,6 @@
<artifactId>killbill-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.kill-bill.billing</groupId>
<artifactId>killbill-invoice</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.kill-bill.billing</groupId>
<artifactId>killbill-platform-osgi-api</artifactId>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import org.killbill.billing.account.api.Account;
import org.killbill.billing.invoice.api.Invoice;
import org.killbill.billing.invoice.api.InvoiceItem;
import org.killbill.billing.invoice.usage.details.UsageConsumableInArrearAggregate;
import org.killbill.billing.osgi.libs.killbill.OSGIKillbillAPI;
import org.killbill.billing.payment.api.PluginProperty;
import org.killbill.billing.plugin.api.PluginProperties;
Expand Down Expand Up @@ -69,14 +68,15 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;

public class VertexTaxCalculator extends PluginTaxCalculator {
Expand Down Expand Up @@ -118,7 +118,7 @@ public VertexTaxCalculator(final VertexApiConfigurationHandler vertexApiConfigur
this.vertexApiConfigurationHandler = vertexApiConfigurationHandler;
this.clock = clock;
this.dao = dao;
this.objectMapper = new ObjectMapper().setSerializationInclusion(Include.NON_NULL);
this.objectMapper = new ObjectMapper();
}

public List<InvoiceItem> compute(final Account account,
Expand Down Expand Up @@ -327,13 +327,7 @@ private InvoiceItem createTaxInvoiceItem(final InvoiceItem taxableItem, final UU
taxRate = calculatedTax.divide(taxableItem.getAmount(), 5, RoundingMode.FLOOR).doubleValue();
}

final UsageConsumableInArrearAggregate usageDetail = getUsageDetailFromItemDetails(taxItem);

final String taxItemDetails = createTaxItemDetails(new TaxItemDetails(taxRate, usageDetail));

if (taxItemDetails == null) {
return taxItem;
}
final String taxItemDetails = addTaxRateToItemDetails(taxItem.getItemDetails(), taxRate);

return new PluginInvoiceItem(new Builder<>()
.withId(taxItem.getId())
Expand Down Expand Up @@ -366,26 +360,38 @@ private InvoiceItem createTaxInvoiceItem(final InvoiceItem taxableItem, final UU
.validate().build());
}

private UsageConsumableInArrearAggregate getUsageDetailFromItemDetails(final InvoiceItem taxItem) {
if (taxItem.getItemDetails() == null) {
return null;
private String addTaxRateToItemDetails(@Nullable final String itemDetails, @Nonnull final Double taxRate) {
final ObjectNode existingItemsDetailsJson = deserializeItemDetails(itemDetails);

final Object itemDetailsWithTaxRate;
if (existingItemsDetailsJson != null) {
existingItemsDetailsJson.put("taxRate", taxRate);
itemDetailsWithTaxRate = existingItemsDetailsJson;
} else {
itemDetailsWithTaxRate = ImmutableMap.of("taxRate", taxRate);
}

UsageConsumableInArrearAggregate usageDetail = null;
try {
usageDetail = objectMapper.readValue(taxItem.getItemDetails(), new TypeReference<UsageConsumableInArrearAggregate>() {});
} catch (JsonProcessingException e) {
logger.error("Failed to parse the item details for tax item with ID: {}", taxItem.getId(), e);
return objectMapper.writeValueAsString(itemDetailsWithTaxRate);
} catch (JsonProcessingException exception) {
logger.error("Couldn't serialize the tax item details: {}", itemDetailsWithTaxRate, exception);
return null;
}

return usageDetail;
}

private String createTaxItemDetails(@Nonnull final TaxItemDetails taxItemDetails) {
private ObjectNode deserializeItemDetails(@Nullable final String itemDetails) {
if (itemDetails == null || itemDetails.isEmpty()) {
return null;
}

try {
return objectMapper.writeValueAsString(taxItemDetails);
} catch (JsonProcessingException exception) {
logger.error("Couldn't serialize the tax item details: {}", taxItemDetails, exception);
final JsonNode jsonNode = objectMapper.readTree(itemDetails);
if (!jsonNode.isObject()) {
return null;
}
return (ObjectNode) jsonNode;
} catch (JsonProcessingException e) {
logger.error("Couldn't deserialize the tax item details: {}", itemDetails, e);
return null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@
import org.killbill.billing.invoice.api.Invoice;
import org.killbill.billing.invoice.api.InvoiceItem;
import org.killbill.billing.invoice.api.InvoiceItemType;
import org.killbill.billing.invoice.usage.details.UsageConsumableInArrearAggregate;
import org.killbill.billing.invoice.usage.details.UsageConsumableInArrearTierUnitAggregate;
import org.killbill.billing.plugin.vertex.dao.VertexDao;
import org.killbill.billing.plugin.vertex.gen.client.model.ApiSuccessResponseTransactionResponseType;
import org.killbill.billing.plugin.vertex.gen.client.model.ApiSuccessResponseTransactionResponseTypeData;
Expand All @@ -52,9 +50,8 @@
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableList;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyMap;
Expand Down Expand Up @@ -260,64 +257,27 @@ public void testTaxEffectiveRate() throws Exception {
@Test(groups = "fast")
public void testTaxItemDetailsWhenUsageDetailsExists() throws Exception {
//given
final double taxRate = 0.09975d;
final Double taxRate = 0.09975d;
given(taxesType.getEffectiveRate()).willReturn(taxRate);

final ObjectMapper objectMapper = new ObjectMapper();
final int tier1 = 1;
final String unit1 = "hour";
final BigDecimal tierPrice1 = BigDecimal.valueOf(0.5);
final long tierBlockSize1 = 1L;
final long quantity1 = 1L;

final int tier2 = 2;
final String unit2 = "min";
final BigDecimal tierPrice2 = BigDecimal.valueOf(0.7);
final long tierBlockSize2 = 2L;
final long quantity2 = 2L;

final List<UsageConsumableInArrearTierUnitAggregate> usages = ImmutableList.of(
new UsageConsumableInArrearTierUnitAggregate(tier1, unit1, tierPrice1, tierBlockSize1, quantity1),
new UsageConsumableInArrearTierUnitAggregate(tier2, unit2, tierPrice2, tierBlockSize2, quantity2));

final UsageConsumableInArrearAggregate usagesAggregate = new UsageConsumableInArrearAggregate(usages);
final String taxableInvoiceItemDetails = objectMapper.writeValueAsString(usagesAggregate);
final String itemDetailsWithTierInfo =
"{\"tierDetails\":[{\"tier\":1,\"tierUnit\":\"hour\",\"tierPrice\":0.500000000," +
"\"tierBlockSize\":1,\"quantity\":1,\"amount\":0.500000000}],\"amount\":0.500000000}";
given(taxableInvoiceItem.getItemDetails()).willReturn(itemDetailsWithTierInfo);

given(taxableInvoiceItem.getItemDetails()).willReturn(taxableInvoiceItemDetails);

final TaxItemDetails expectedTaxItemDetails = new TaxItemDetails(taxRate, usagesAggregate);
final String expectedTaxItemDetailsJson = objectMapper.writeValueAsString(expectedTaxItemDetails);
final String expectedItemDetailsWithTaxRate =
"{\"tierDetails\":[{\"tier\":1,\"tierUnit\":\"hour\",\"tierPrice\":0.500000000," +
"\"tierBlockSize\":1,\"quantity\":1,\"amount\":0.500000000}],\"amount\":0.500000000," +
"\"taxRate\":" + taxRate + "}";

//when
final List<InvoiceItem> result = vertexTaxCalculator.compute(account, invoice, true, Collections.emptyList(), tenantContext);

//then
final String actualItemDetailsJson = result.get(0).getItemDetails();
final TaxItemDetails actualItemDetails = objectMapper.readValue(actualItemDetailsJson, new TypeReference<TaxItemDetails>() {});

assertEquals(taxRate, actualItemDetails.getTaxRate());

assertEquals(usages.size(), actualItemDetails.getTierDetails().size());

final UsageConsumableInArrearTierUnitAggregate actualTierAggregate1 = actualItemDetails.getTierDetails().get(0);
assertEquals(tier1, actualTierAggregate1.getTier());
assertEquals(unit1, actualTierAggregate1.getTierUnit());
assertEquals(tierPrice1, actualTierAggregate1.getTierPrice());
assertEquals(tierBlockSize1, actualTierAggregate1.getTierBlockSize());
assertEquals(Long.valueOf(quantity1), actualTierAggregate1.getQuantity());
assertEquals(tierPrice1.multiply(BigDecimal.valueOf(quantity1)), actualTierAggregate1.getAmount());

final UsageConsumableInArrearTierUnitAggregate actualTierAggregate2 = actualItemDetails.getTierDetails().get(1);
assertEquals(tier2, actualTierAggregate2.getTier());
assertEquals(unit2, actualTierAggregate2.getTierUnit());
assertEquals(tierPrice2, actualTierAggregate2.getTierPrice());
assertEquals(tierBlockSize2, actualTierAggregate2.getTierBlockSize());
assertEquals(Long.valueOf(quantity2), actualTierAggregate2.getQuantity());
assertEquals(tierPrice2.multiply(BigDecimal.valueOf(quantity2)), actualItemDetails.getTierDetails().get(1).getAmount());
List<InvoiceItem> result = vertexTaxCalculator.compute(account, invoice, true, Collections.emptyList(), tenantContext);

assertEquals(actualTierAggregate1.getAmount().add(actualTierAggregate2.getAmount()), actualItemDetails.getAmount());
final ObjectMapper objectMapper = new ObjectMapper();
final JsonNode expectedNode = objectMapper.readTree(expectedItemDetailsWithTaxRate);
final JsonNode actualNode = objectMapper.readTree(result.get(0).getItemDetails());

assertEquals(expectedTaxItemDetailsJson, objectMapper.writeValueAsString(actualItemDetails));
assertEquals(expectedNode, actualNode);
}

@Test(groups = "fast")
Expand Down

0 comments on commit 028ba4a

Please sign in to comment.