killbill-memoizeit

Merge remote-tracking branch 'origin/work-for-release-0.19.x'

3/11/2018 6:23:49 PM

Changes

Details

diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithInvoicePlugin.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithInvoicePlugin.java
index ed205d5..cf4b16a 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithInvoicePlugin.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithInvoicePlugin.java
@@ -1,6 +1,6 @@
 /*
- * Copyright 2014-2017 Groupon, Inc
- * Copyright 2014-2017 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
  *
  * The Billing Project 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
@@ -19,6 +19,7 @@ package org.killbill.billing.beatrix.integration;
 
 import java.math.BigDecimal;
 import java.util.List;
+import java.util.UUID;
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
 
@@ -33,12 +34,14 @@ import org.killbill.billing.account.api.AccountData;
 import org.killbill.billing.api.TestApiListener.NextEvent;
 import org.killbill.billing.beatrix.util.InvoiceChecker.ExpectedInvoiceItemCheck;
 import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.catalog.api.ProductCategory;
 import org.killbill.billing.entitlement.api.DefaultEntitlement;
 import org.killbill.billing.invoice.api.DefaultInvoiceService;
 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.model.ExternalChargeInvoiceItem;
 import org.killbill.billing.invoice.model.TaxInvoiceItem;
 import org.killbill.billing.invoice.notification.DefaultNextBillingDateNotifier;
 import org.killbill.billing.invoice.plugin.api.InvoicePluginApi;
@@ -54,11 +57,15 @@ import org.killbill.notificationq.api.NotificationQueueService.NoSuchNotificatio
 import org.killbill.queue.retry.RetryNotificationEvent;
 import org.killbill.queue.retry.RetryableService;
 import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
 
 public class TestWithInvoicePlugin extends TestIntegrationBase {
 
@@ -93,6 +100,65 @@ public class TestWithInvoicePlugin extends TestIntegrationBase {
         }, testInvoicePluginApi);
     }
 
+    @BeforeMethod(groups = "slow")
+    public void setUp() throws Exception {
+        testInvoicePluginApi.additionalInvoiceItem = null;
+    }
+
+    @Test(groups = "slow")
+    public void testBasicAdditionalExternalChargeItem() throws Exception {
+        // We take april as it has 30 days (easier to play with BCD)
+        // Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
+        clock.setDay(new LocalDate(2012, 4, 1));
+
+        final AccountData accountData = getAccountData(1);
+        final Account account = createAccountWithNonOsgiPaymentMethod(accountData);
+        accountChecker.checkAccount(account.getId(), accountData, callContext);
+
+        final UUID pluginInvoiceItemId = UUID.randomUUID();
+        final UUID pluginLinkedItemId = UUID.randomUUID();
+        testInvoicePluginApi.additionalInvoiceItem = new ExternalChargeInvoiceItem(pluginInvoiceItemId,
+                                                                                   clock.getUTCNow(),
+                                                                                   null,
+                                                                                   account.getId(),
+                                                                                   null,
+                                                                                   null,
+                                                                                   null,
+                                                                                   null,
+                                                                                   null,
+                                                                                   null,
+                                                                                   "My charge",
+                                                                                   clock.getUTCToday(),
+                                                                                   null,
+                                                                                   BigDecimal.TEN,
+                                                                                   null,
+                                                                                   Currency.USD,
+                                                                                   pluginLinkedItemId,
+                                                                                   null);
+
+        // Create original subscription (Trial PHASE) -> $0 invoice but plugin added one item
+        final DefaultEntitlement bpSubscription = createBaseEntitlementAndCheckForCompletion(account.getId(), "bundleKey", "Pistol", ProductCategory.BASE, BillingPeriod.MONTHLY, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
+        invoiceChecker.checkInvoice(account.getId(), 1, callContext,
+                                    new ExpectedInvoiceItemCheck(new LocalDate(2012, 4, 1), null, InvoiceItemType.FIXED, new BigDecimal("0")),
+                                    new ExpectedInvoiceItemCheck(new LocalDate(2012, 4, 1), null, InvoiceItemType.EXTERNAL_CHARGE, BigDecimal.TEN));
+        subscriptionChecker.checkSubscriptionCreated(bpSubscription.getId(), internalCallContext);
+
+        final List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), false, false, callContext);
+        assertEquals(invoices.size(), 1);
+        final List<InvoiceItem> invoiceItems = invoices.get(0).getInvoiceItems();
+        final InvoiceItem externalCharge = Iterables.tryFind(invoiceItems, new Predicate<InvoiceItem>() {
+            @Override
+            public boolean apply(final InvoiceItem input) {
+                return input.getInvoiceItemType() == InvoiceItemType.EXTERNAL_CHARGE;
+            }
+        }).orNull();
+        assertNotNull(externalCharge);
+        // verify the ID is the one passed by the plugin #818
+        assertEquals(externalCharge.getId(), pluginInvoiceItemId);
+        // verify the ID is the one passed by the plugin #887
+        assertEquals(externalCharge.getLinkedItemId(), pluginLinkedItemId);
+    }
+
     @Test(groups = "slow")
     public void testWithRetries() throws Exception {
         // We take april as it has 30 days (easier to play with BCD)
@@ -250,13 +316,17 @@ public class TestWithInvoicePlugin extends TestIntegrationBase {
     public class TestInvoicePluginApi implements InvoicePluginApi {
 
         boolean shouldThrowException = false;
+        InvoiceItem additionalInvoiceItem;
 
         @Override
         public List<InvoiceItem> getAdditionalInvoiceItems(final Invoice invoice, final boolean isDryRun, final Iterable<PluginProperty> pluginProperties, final CallContext callContext) {
             if (shouldThrowException) {
                 throw new InvoicePluginApiRetryException();
+            } else if (additionalInvoiceItem != null) {
+                return ImmutableList.<InvoiceItem>of(additionalInvoiceItem);
+            } else {
+                return ImmutableList.<InvoiceItem>of(createTaxInvoiceItem(invoice));
             }
-            return ImmutableList.<InvoiceItem>of(createTaxInvoiceItem(invoice));
         }
 
         private InvoiceItem createTaxInvoiceItem(final Invoice invoice) {
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java b/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
index ad28373..8dc4193 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/InvoiceDispatcher.java
@@ -48,7 +48,6 @@ import org.killbill.billing.catalog.api.BillingActionPolicy;
 import org.killbill.billing.catalog.api.CatalogApiException;
 import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
 import org.killbill.billing.catalog.api.PlanPhaseSpecifier;
-import org.killbill.billing.entitlement.api.Entitlement.EntitlementState;
 import org.killbill.billing.entitlement.api.SubscriptionEventType;
 import org.killbill.billing.events.BusInternalEvent;
 import org.killbill.billing.events.EffectiveSubscriptionInternalEvent;
@@ -77,6 +76,7 @@ import org.killbill.billing.invoice.generator.InvoiceWithMetadata.SubscriptionFu
 import org.killbill.billing.invoice.generator.InvoiceWithMetadata.SubscriptionFutureNotificationDates.UsageDef;
 import org.killbill.billing.invoice.model.DefaultInvoice;
 import org.killbill.billing.invoice.model.FixedPriceInvoiceItem;
+import org.killbill.billing.invoice.model.InvoiceItemCatalogBase;
 import org.killbill.billing.invoice.model.InvoiceItemFactory;
 import org.killbill.billing.invoice.model.ItemAdjInvoiceItem;
 import org.killbill.billing.invoice.model.ParentInvoiceItem;
@@ -571,7 +571,30 @@ public class InvoiceDispatcher {
                     if (exitingItem != null) {
                         invoice.removeInvoiceItem(exitingItem);
                     }
-                    invoice.addInvoiceItem(cur);
+
+                    final InvoiceItem sanitizedInvoiceItemFromPlugin = new InvoiceItemCatalogBase(cur.getId(),
+                                                                                                  cur.getCreatedDate(),
+                                                                                                  MoreObjects.firstNonNull(cur.getInvoiceId(), invoice.getId()),
+                                                                                                  cur.getAccountId(),
+                                                                                                  cur.getBundleId(),
+                                                                                                  cur.getSubscriptionId(),
+                                                                                                  cur.getDescription(),
+                                                                                                  cur.getPlanName(),
+                                                                                                  cur.getPhaseName(),
+                                                                                                  cur.getUsageName(),
+                                                                                                  cur.getPrettyPlanName(),
+                                                                                                  cur.getPrettyPhaseName(),
+                                                                                                  cur.getPrettyUsageName(),
+                                                                                                  cur.getStartDate(),
+                                                                                                  cur.getEndDate(),
+                                                                                                  cur.getAmount(),
+                                                                                                  cur.getRate(),
+                                                                                                  cur.getCurrency(),
+                                                                                                  cur.getLinkedItemId(),
+                                                                                                  cur.getQuantity(),
+                                                                                                  cur.getItemDetails(),
+                                                                                                  cur.getInvoiceItemType());
+                    invoice.addInvoiceItem(sanitizedInvoiceItemFromPlugin);
                 }
 
                 // Use credit after we call the plugin (https://github.com/killbill/killbill/issues/637)
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/AdjInvoiceItem.java b/invoice/src/main/java/org/killbill/billing/invoice/model/AdjInvoiceItem.java
index 6a7eb2e..305fd7d 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/AdjInvoiceItem.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/AdjInvoiceItem.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014 Groupon, Inc
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
  *
  * The Billing Project 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
@@ -32,10 +32,7 @@ public abstract class AdjInvoiceItem extends InvoiceItemBase {
 
     AdjInvoiceItem(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId,
                    final LocalDate startDate, final LocalDate endDate, @Nullable final String description,
-                   final BigDecimal amount, final Currency currency, @Nullable final UUID reversingId) {
-        super(id, createdDate, invoiceId, accountId, null, null, description, startDate, endDate, amount, null, currency, reversingId);
+                   final BigDecimal amount, final Currency currency, @Nullable final UUID reversingId, final InvoiceItemType invoiceItemType) {
+        super(id, createdDate, invoiceId, accountId, null, null, description, startDate, endDate, amount, null, currency, reversingId, invoiceItemType);
     }
-
-    @Override
-    public abstract InvoiceItemType getInvoiceItemType();
 }
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/CreditAdjInvoiceItem.java b/invoice/src/main/java/org/killbill/billing/invoice/model/CreditAdjInvoiceItem.java
index 597c4a1..68ef0d8 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/CreditAdjInvoiceItem.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/CreditAdjInvoiceItem.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014 Groupon, Inc
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
  *
  * The Billing Project 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
@@ -38,15 +38,9 @@ public class CreditAdjInvoiceItem extends AdjInvoiceItem {
         this(UUIDs.randomUUID(), null, invoiceId, accountId, date, description, amount, currency);
     }
 
-
     public CreditAdjInvoiceItem(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, final LocalDate date,
                                 @Nullable final String description, final BigDecimal amount, final Currency currency) {
-        super(id, createdDate, invoiceId, accountId, date, date, description, amount, currency, null);
-    }
-
-    @Override
-    public InvoiceItemType getInvoiceItemType() {
-        return InvoiceItemType.CREDIT_ADJ;
+        super(id, createdDate, invoiceId, accountId, date, date, description, amount, currency, null, InvoiceItemType.CREDIT_ADJ);
     }
 
     @Override
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/CreditBalanceAdjInvoiceItem.java b/invoice/src/main/java/org/killbill/billing/invoice/model/CreditBalanceAdjInvoiceItem.java
index 5dfe7cc..a70f0bf 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/CreditBalanceAdjInvoiceItem.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/CreditBalanceAdjInvoiceItem.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014 Groupon, Inc
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
  *
  * The Billing Project 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
@@ -45,12 +45,7 @@ public class CreditBalanceAdjInvoiceItem extends AdjInvoiceItem {
     public CreditBalanceAdjInvoiceItem(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId,
                                        final LocalDate date, final UUID linkedInvoiceItemId,
                                        @Nullable final String description, final BigDecimal amount, final Currency currency) {
-        super(id, createdDate, invoiceId, accountId, date, date, description, amount, currency, linkedInvoiceItemId);
-    }
-
-    @Override
-    public InvoiceItemType getInvoiceItemType() {
-        return InvoiceItemType.CBA_ADJ;
+        super(id, createdDate, invoiceId, accountId, date, date, description, amount, currency, linkedInvoiceItemId, InvoiceItemType.CBA_ADJ);
     }
 
     @Override
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/ExternalChargeInvoiceItem.java b/invoice/src/main/java/org/killbill/billing/invoice/model/ExternalChargeInvoiceItem.java
index c56e7f0..78ff132 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/ExternalChargeInvoiceItem.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/ExternalChargeInvoiceItem.java
@@ -1,7 +1,9 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
  *
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
  *
@@ -41,13 +43,13 @@ public class ExternalChargeInvoiceItem extends InvoiceItemCatalogBase {
 
     public ExternalChargeInvoiceItem(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, @Nullable final UUID bundleId,
                                      @Nullable final String description, final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final Currency currency, @Nullable final String itemDetails) {
-        super(id, createdDate, invoiceId, accountId, bundleId, null, description, null, null, null, startDate, endDate, amount, null, currency, null, null, itemDetails);
+        super(id, createdDate, invoiceId, accountId, bundleId, null, description, null, null, null, startDate, endDate, amount, null, currency, null, null, itemDetails, InvoiceItemType.EXTERNAL_CHARGE);
     }
 
     public ExternalChargeInvoiceItem(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, final UUID bundleId, final UUID subscriptionId,
                                      final String planName, final String phaseName, final String prettyPlanName, final String prettyPhaseName, @Nullable final String description, final LocalDate startDate, final LocalDate endDate,
                                      final BigDecimal amount, final BigDecimal rate, final Currency currency, @Nullable final UUID linkedItemId, @Nullable String itemDetails) {
-        super(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, null, prettyPlanName, prettyPhaseName, null, startDate, endDate, amount, rate, currency, linkedItemId, null, itemDetails);
+        super(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, null, prettyPlanName, prettyPhaseName, null, startDate, endDate, amount, rate, currency, linkedItemId, null, itemDetails, InvoiceItemType.EXTERNAL_CHARGE);
     }
 
     @Override
@@ -62,9 +64,4 @@ public class ExternalChargeInvoiceItem extends InvoiceItemCatalogBase {
             return String.format("%s (external charge)", getPlanName());
         }
     }
-
-    @Override
-    public InvoiceItemType getInvoiceItemType() {
-        return InvoiceItemType.EXTERNAL_CHARGE;
-    }
 }
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/FixedPriceInvoiceItem.java b/invoice/src/main/java/org/killbill/billing/invoice/model/FixedPriceInvoiceItem.java
index b177056..9f9d90e 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/FixedPriceInvoiceItem.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/FixedPriceInvoiceItem.java
@@ -40,13 +40,13 @@ public class FixedPriceInvoiceItem extends InvoiceItemCatalogBase {
     public FixedPriceInvoiceItem(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, final UUID bundleId,
                                  final UUID subscriptionId, final String planName, final String phaseName,
                                  @Nullable final String description, final LocalDate date, final BigDecimal amount, final Currency currency) {
-        super(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, null, date, null, amount, null, currency, null);
+        super(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, null, date, null, amount, null, currency, null, InvoiceItemType.FIXED);
     }
 
     public FixedPriceInvoiceItem(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, final UUID bundleId,
                                  final UUID subscriptionId, final String planName, final String phaseName, final String prettyPlanName, final String prettyPhaseName,
                                  @Nullable final String description, final LocalDate date, final BigDecimal amount, final Currency currency) {
-        super(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, null, prettyPlanName, prettyPhaseName, null, date, null, amount, null, currency, null);
+        super(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, null, prettyPlanName, prettyPhaseName, null, date, null, amount, null, currency, null, InvoiceItemType.FIXED);
     }
 
     @Override
@@ -65,9 +65,4 @@ public class FixedPriceInvoiceItem extends InvoiceItemCatalogBase {
             }
         }
     }
-
-    @Override
-    public InvoiceItemType getInvoiceItemType() {
-        return InvoiceItemType.FIXED;
-    }
 }
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/InvoiceItemBase.java b/invoice/src/main/java/org/killbill/billing/invoice/model/InvoiceItemBase.java
index b183ebe..ed31c6a 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/InvoiceItemBase.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/InvoiceItemBase.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2014 Ning, Inc.
- * Copyright 2014-2016 Groupon, Inc
- * Copyright 2014-2016 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
  *
  * The Billing Project 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
@@ -42,6 +42,7 @@ public abstract class InvoiceItemBase extends EntityBase implements InvoiceItem 
     protected final BigDecimal amount;
     protected final Currency currency;
     protected final String description;
+    protected final InvoiceItemType invoiceItemType;
 
     /* Fixed and recurring specific */
     protected final UUID subscriptionId;
@@ -59,34 +60,27 @@ public abstract class InvoiceItemBase extends EntityBase implements InvoiceItem 
 
     public InvoiceItemBase(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, @Nullable final UUID bundleId,
                            @Nullable final UUID subscriptionId, @Nullable final String description,
-                           final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final BigDecimal rate, final Currency currency, final UUID reversedItemId) {
-        this(id, createdDate, invoiceId, accountId, null, bundleId, subscriptionId, description, startDate, endDate, amount, rate, currency, reversedItemId, null, null);
+                           final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final BigDecimal rate, final Currency currency, final UUID reversedItemId, final InvoiceItemType invoiceItemType) {
+        this(id, createdDate, invoiceId, accountId, null, bundleId, subscriptionId, description, startDate, endDate, amount, rate, currency, reversedItemId, null, null, invoiceItemType);
     }
 
     public InvoiceItemBase(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, @Nullable final UUID bundleId,
                            @Nullable final UUID subscriptionId, @Nullable final String description,
                            final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final BigDecimal rate, final Currency currency, final UUID reversedItemId,
-                           @Nullable final Integer quantity, @Nullable final String itemDetails) {
-        this(id, createdDate, invoiceId, accountId, null, bundleId, subscriptionId, description, startDate, endDate, amount, rate, currency, reversedItemId, quantity, itemDetails);
+                           @Nullable final Integer quantity, @Nullable final String itemDetails, final InvoiceItemType invoiceItemType) {
+        this(id, createdDate, invoiceId, accountId, null, bundleId, subscriptionId, description, startDate, endDate, amount, rate, currency, reversedItemId, quantity, itemDetails, invoiceItemType);
     }
 
     // For parent invoices
     public InvoiceItemBase(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, final UUID childAccountId,
-                           final BigDecimal amount, final Currency currency, final String description) {
-        this(id, createdDate, invoiceId, accountId, childAccountId, null, null, description, null, null, amount, null, currency, null, null, null);
-    }
-
-    public InvoiceItemBase(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, @Nullable final UUID childAccountId, @Nullable final UUID bundleId,
-                           @Nullable final UUID subscriptionId, @Nullable final String description,
-                           @Nullable final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final BigDecimal rate, final Currency currency,
-                           final UUID reversedItemId) {
-        this(id, createdDate, invoiceId, accountId, childAccountId, bundleId, subscriptionId, description, startDate, endDate, amount, rate, currency, reversedItemId, null, null);
+                           final BigDecimal amount, final Currency currency, final String description, final InvoiceItemType invoiceItemType) {
+        this(id, createdDate, invoiceId, accountId, childAccountId, null, null, description, null, null, amount, null, currency, null, null, null, invoiceItemType);
     }
 
     private InvoiceItemBase(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, @Nullable final UUID childAccountId, @Nullable final UUID bundleId,
                             @Nullable final UUID subscriptionId, @Nullable final String description,
                             @Nullable final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final BigDecimal rate, final Currency currency,
-                            final UUID reversedItemId, @Nullable final Integer quantity, @Nullable final String itemDetails) {
+                            final UUID reversedItemId, @Nullable final Integer quantity, @Nullable final String itemDetails, final InvoiceItemType invoiceItemType) {
         super(id, createdDate, createdDate);
         this.invoiceId = invoiceId;
         this.accountId = accountId;
@@ -102,6 +96,7 @@ public abstract class InvoiceItemBase extends EntityBase implements InvoiceItem 
         this.linkedItemId = reversedItemId;
         this.quantity = quantity;
         this.itemDetails = itemDetails;
+        this.invoiceItemType = invoiceItemType;
     }
 
     @Override
@@ -313,8 +308,12 @@ public abstract class InvoiceItemBase extends EntityBase implements InvoiceItem 
     }
 
     @Override
-    public abstract InvoiceItemType getInvoiceItemType();
+    public InvoiceItemType getInvoiceItemType() {
+        return invoiceItemType;
+    }
 
     @Override
-    public abstract String getDescription();
+    public String getDescription() {
+        return description;
+    }
 }
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/InvoiceItemCatalogBase.java b/invoice/src/main/java/org/killbill/billing/invoice/model/InvoiceItemCatalogBase.java
index 9ad25ce..4afb0e8 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/InvoiceItemCatalogBase.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/InvoiceItemCatalogBase.java
@@ -1,6 +1,6 @@
 /*
- * Copyright 2014-2017 Groupon, Inc
- * Copyright 2014-2017 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
  *
  * The Billing Project 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
@@ -26,8 +26,9 @@ import org.joda.time.DateTime;
 import org.joda.time.LocalDate;
 import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.invoice.api.InvoiceItem;
+import org.killbill.billing.invoice.api.InvoiceItemType;
 
-public abstract class InvoiceItemCatalogBase extends InvoiceItemBase implements InvoiceItem {
+public class InvoiceItemCatalogBase extends InvoiceItemBase implements InvoiceItem {
 
     protected final String planName;
     protected final String phaseName;
@@ -39,31 +40,30 @@ public abstract class InvoiceItemCatalogBase extends InvoiceItemBase implements 
 
     public InvoiceItemCatalogBase(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, @Nullable final UUID bundleId,
                                   @Nullable final UUID subscriptionId, @Nullable final String description, @Nullable final String planName, @Nullable final String phaseName, @Nullable final String usageName,
-                                  final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final BigDecimal rate, final Currency currency, @Nullable final UUID linkedItemId) {
-        this(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, usageName, null, null, null, startDate, endDate, amount, rate, currency, linkedItemId, null, null);
+                                  final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final BigDecimal rate, final Currency currency, @Nullable final UUID linkedItemId, final InvoiceItemType invoiceItemType) {
+        this(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, usageName, null, null, null, startDate, endDate, amount, rate, currency, linkedItemId, null, null, invoiceItemType);
     }
 
     public InvoiceItemCatalogBase(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, @Nullable final UUID bundleId,
                                   @Nullable final UUID subscriptionId, @Nullable final String description, @Nullable final String planName, @Nullable final String phaseName, @Nullable final String usageName,
                                   final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final BigDecimal rate, final Currency currency, @Nullable final UUID linkedItemId,
-                                  @Nullable final Integer quantity, @Nullable final String itemDetails) {
-        this(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, usageName, null, null, null, startDate, endDate, amount, rate, currency, linkedItemId, quantity, itemDetails);
+                                  @Nullable final Integer quantity, @Nullable final String itemDetails, final InvoiceItemType invoiceItemType) {
+        this(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, usageName, null, null, null, startDate, endDate, amount, rate, currency, linkedItemId, quantity, itemDetails, invoiceItemType);
     }
 
     public InvoiceItemCatalogBase(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, @Nullable final UUID bundleId,
                                   @Nullable final UUID subscriptionId, @Nullable final String description, @Nullable final String planName, @Nullable final String phaseName, @Nullable final String usageName,
                                   @Nullable final String prettyPlanName, @Nullable final String prettyPhaseName, @Nullable final String prettyUsageName,
-                                  final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final BigDecimal rate, final Currency currency, @Nullable final UUID linkedItemId) {
-        this(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, usageName, prettyPlanName, prettyPhaseName, prettyUsageName, startDate, endDate, amount, rate, currency, linkedItemId, null, null);
+                                  final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final BigDecimal rate, final Currency currency, @Nullable final UUID linkedItemId, final InvoiceItemType invoiceItemType) {
+        this(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, usageName, prettyPlanName, prettyPhaseName, prettyUsageName, startDate, endDate, amount, rate, currency, linkedItemId, null, null, invoiceItemType);
     }
 
-
     public InvoiceItemCatalogBase(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, @Nullable final UUID bundleId,
                                   @Nullable final UUID subscriptionId, @Nullable final String description, @Nullable final String planName, @Nullable final String phaseName, @Nullable final String usageName,
                                   @Nullable final String prettyPlanName, @Nullable final String prettyPhaseName, @Nullable final String prettyUsageName,
                                   final LocalDate startDate, final LocalDate endDate, final BigDecimal amount, final BigDecimal rate, final Currency currency, @Nullable final UUID linkedItemId,
-                                  @Nullable final Integer quantity, @Nullable final String itemDetails) {
-        super(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, startDate, endDate, amount, rate, currency, linkedItemId, quantity, itemDetails);
+                                  @Nullable final Integer quantity, @Nullable final String itemDetails, final InvoiceItemType invoiceItemType) {
+        super(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, startDate, endDate, amount, rate, currency, linkedItemId, quantity, itemDetails, invoiceItemType);
         this.planName = planName;
         this.phaseName = phaseName;
         this.usageName = usageName;
@@ -72,7 +72,6 @@ public abstract class InvoiceItemCatalogBase extends InvoiceItemBase implements 
         this.prettyUsageName = prettyUsageName;
     }
 
-
     @Override
     public String getPlanName() {
         return planName;
@@ -88,7 +87,6 @@ public abstract class InvoiceItemCatalogBase extends InvoiceItemBase implements 
         return usageName;
     }
 
-
     @Override
     public String getPrettyPlanName() {
         return prettyPlanName;
@@ -104,12 +102,11 @@ public abstract class InvoiceItemCatalogBase extends InvoiceItemBase implements 
         return prettyUsageName;
     }
 
-
     @Override
     public boolean matches(final Object o) {
 
         if (!super.matches(o)) {
-            return  false;
+            return false;
         }
         final InvoiceItemCatalogBase that = (InvoiceItemCatalogBase) o;
         if (phaseName != null ? !phaseName.equals(that.phaseName) : that.phaseName != null) {
@@ -134,38 +131,17 @@ public abstract class InvoiceItemCatalogBase extends InvoiceItemBase implements 
     public String toString() {
         // Note: we don't use all fields here, as the output would be overwhelming
         // (we output all invoice items as they are generated).
-        final StringBuilder sb = new StringBuilder();
-        sb.append(getInvoiceItemType());
-        sb.append("{");
-        if (planName != null) {
-            sb.append("planName=").append(planName);
-        }
-        if (phaseName != null) {
-            sb.append("phaseName=").append(phaseName);
-        }
-        if (usageName != null) {
-            sb.append("usageName=").append(usageName);
-        }
-        if (startDate != null) {
-            sb.append("startDate=").append(startDate);
-        }
-        if (endDate != null) {
-            sb.append("endDate=").append(endDate);
-        }
-        if (amount != null) {
-            sb.append("amount=").append(amount);
-        }
-        if (rate != null) {
-            sb.append("rate=").append(rate);
-        }
-        if (subscriptionId != null) {
-            sb.append("subscriptionId=").append(subscriptionId);
-        }
-        if (linkedItemId != null) {
-            sb.append("linkedItemId=").append(linkedItemId);
-        }
+        final StringBuilder sb = new StringBuilder().append(invoiceItemType).append("{");
+        sb.append("planName='").append(planName).append('\'');
+        sb.append(", phaseName='").append(phaseName).append('\'');
+        sb.append(", usageName='").append(usageName).append('\'');
+        sb.append(", startDate=").append(startDate);
+        sb.append(", endDate=").append(endDate);
+        sb.append(", amount=").append(amount);
+        sb.append(", subscriptionId=").append(subscriptionId);
+        sb.append(", rate=").append(rate);
+        sb.append(", linkedItemId=").append(linkedItemId);
         sb.append('}');
         return sb.toString();
     }
-
 }
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/ItemAdjInvoiceItem.java b/invoice/src/main/java/org/killbill/billing/invoice/model/ItemAdjInvoiceItem.java
index a8ffffc..0f6bcbc 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/ItemAdjInvoiceItem.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/ItemAdjInvoiceItem.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014 Groupon, Inc
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
  *
  * The Billing Project 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
@@ -40,15 +40,9 @@ public class ItemAdjInvoiceItem extends AdjInvoiceItem {
              linkedInvoiceItem.getDescription(), amount, currency, linkedInvoiceItem.getId());
     }
 
-
     public ItemAdjInvoiceItem(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, final LocalDate startDate,
                               @Nullable final String description, final BigDecimal amount, final Currency currency, final UUID linkedItemId) {
-        super(id, createdDate, invoiceId, accountId, startDate, startDate, description, amount, currency, linkedItemId);
-    }
-
-    @Override
-    public InvoiceItemType getInvoiceItemType() {
-        return InvoiceItemType.ITEM_ADJ;
+        super(id, createdDate, invoiceId, accountId, startDate, startDate, description, amount, currency, linkedItemId, InvoiceItemType.ITEM_ADJ);
     }
 
     @Override
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/ParentInvoiceItem.java b/invoice/src/main/java/org/killbill/billing/invoice/model/ParentInvoiceItem.java
index 0dc8c8d..be5769b 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/ParentInvoiceItem.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/ParentInvoiceItem.java
@@ -1,6 +1,6 @@
 /*
- * Copyright 2014-2016 Groupon, Inc
- * Copyright 2014-2016 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
  *
  * The Billing Project 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
@@ -32,12 +32,7 @@ public class ParentInvoiceItem extends InvoiceItemBase {
 
     public ParentInvoiceItem(@Nullable final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, final UUID childAccountId,
                              final BigDecimal amount, final Currency currency, final String description) {
-        super(id, createdDate, invoiceId, accountId, childAccountId, amount, currency, description);
-    }
-
-    @Override
-    public InvoiceItemType getInvoiceItemType() {
-        return InvoiceItemType.PARENT_SUMMARY;
+        super(id, createdDate, invoiceId, accountId, childAccountId, amount, currency, description, InvoiceItemType.PARENT_SUMMARY);
     }
 
     @Override
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/RecurringInvoiceItem.java b/invoice/src/main/java/org/killbill/billing/invoice/model/RecurringInvoiceItem.java
index 45b9866..678ca98 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/RecurringInvoiceItem.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/RecurringInvoiceItem.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014 Groupon, Inc
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
  *
  * The Billing Project 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
@@ -48,7 +48,7 @@ public class RecurringInvoiceItem extends InvoiceItemCatalogBase {
     public RecurringInvoiceItem(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, final UUID bundleId, final UUID subscriptionId,
                                 final String planName, final String phaseName, final String prettyPlanName, final String prettyPhaseName, @Nullable final String description, final LocalDate startDate, final LocalDate endDate,
                                 final BigDecimal amount, final BigDecimal rate, final Currency currency) {
-        super(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, null, prettyPlanName, prettyPhaseName, null, startDate, endDate, amount, rate, currency, null);
+        super(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, null, prettyPlanName, prettyPhaseName, null, startDate, endDate, amount, rate, currency, null, InvoiceItemType.RECURRING);
     }
 
     @Override
@@ -60,9 +60,4 @@ public class RecurringInvoiceItem extends InvoiceItemCatalogBase {
     public BigDecimal getRate() {
         return rate;
     }
-
-    @Override
-    public InvoiceItemType getInvoiceItemType() {
-        return InvoiceItemType.RECURRING;
-    }
 }
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/RepairAdjInvoiceItem.java b/invoice/src/main/java/org/killbill/billing/invoice/model/RepairAdjInvoiceItem.java
index 2eca25f..9d42b86 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/RepairAdjInvoiceItem.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/RepairAdjInvoiceItem.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014 Groupon, Inc
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
  *
  * The Billing Project 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
@@ -45,12 +45,7 @@ public class RepairAdjInvoiceItem extends AdjInvoiceItem {
 
     public RepairAdjInvoiceItem(final UUID id, @Nullable final DateTime createdDate, final UUID invoiceId, final UUID accountId, final LocalDate startDate, final LocalDate endDate,
                                 @Nullable final String description, final BigDecimal amount, final Currency currency, final UUID reversingId) {
-        super(id, createdDate, invoiceId, accountId, startDate, endDate, description, amount, currency, reversingId);
-    }
-
-    @Override
-    public InvoiceItemType getInvoiceItemType() {
-        return InvoiceItemType.REPAIR_ADJ;
+        super(id, createdDate, invoiceId, accountId, startDate, endDate, description, amount, currency, reversingId, InvoiceItemType.REPAIR_ADJ);
     }
 
     @Override
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/TaxInvoiceItem.java b/invoice/src/main/java/org/killbill/billing/invoice/model/TaxInvoiceItem.java
index cd708e9..4acad06 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/TaxInvoiceItem.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/TaxInvoiceItem.java
@@ -1,7 +1,8 @@
 /*
- * Copyright 2014 Groupon, Inc
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
  *
- * Groupon licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
  *
@@ -43,7 +44,7 @@ public class TaxInvoiceItem extends InvoiceItemCatalogBase {
                           @Nullable final UUID subscriptionId, @Nullable final String planName, @Nullable final String phaseName, @Nullable final String usageName,
                           @Nullable final String prettyPlanName, @Nullable final String prettyPhaseName, @Nullable final String prettyUsageName,
                           final LocalDate date, @Nullable final String description, final BigDecimal amount, final Currency currency, @Nullable final UUID linkedItemId) {
-        super(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, usageName, prettyPlanName, prettyPhaseName, prettyUsageName, date, null, amount, null, currency, linkedItemId);
+        super(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, usageName, prettyPlanName, prettyPhaseName, prettyUsageName, date, null, amount, null, currency, linkedItemId, InvoiceItemType.TAX);
     }
 
     @Override
@@ -54,9 +55,4 @@ public class TaxInvoiceItem extends InvoiceItemCatalogBase {
 
         return "Tax";
     }
-
-    @Override
-    public InvoiceItemType getInvoiceItemType() {
-        return InvoiceItemType.TAX;
-    }
 }
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/UsageInvoiceItem.java b/invoice/src/main/java/org/killbill/billing/invoice/model/UsageInvoiceItem.java
index e5841aa..6857259 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/UsageInvoiceItem.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/UsageInvoiceItem.java
@@ -1,6 +1,6 @@
 /*
- * Copyright 2014 Groupon, Inc
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
  *
  * The Billing Project 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
@@ -49,12 +49,7 @@ public class UsageInvoiceItem extends InvoiceItemCatalogBase {
                             final String prettyPlanName, final String prettyPhaseName, final String prettyUsageName,
                             final LocalDate startDate, final LocalDate endDate, @Nullable final String description, final BigDecimal amount, final BigDecimal rate,
                             final Currency currency, @Nullable final Integer quantity, @Nullable final String itemDetails) {
-        super(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, usageName, prettyPlanName, prettyPhaseName, prettyUsageName, startDate, endDate, amount, rate, currency, null, quantity, itemDetails);
-    }
-
-    @Override
-    public InvoiceItemType getInvoiceItemType() {
-        return InvoiceItemType.USAGE;
+        super(id, createdDate, invoiceId, accountId, bundleId, subscriptionId, description, planName, phaseName, usageName, prettyPlanName, prettyPhaseName, prettyUsageName, startDate, endDate, amount, rate, currency, null, quantity, itemDetails, InvoiceItemType.USAGE);
     }
 
     @Override
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/util/JaxrsUriBuilder.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/util/JaxrsUriBuilder.java
index b0f210e..6d9f9b6 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/util/JaxrsUriBuilder.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/util/JaxrsUriBuilder.java
@@ -106,7 +106,7 @@ public class JaxrsUriBuilder {
                 // Use "remote" value to support X-Forwarded headers (assumes RemoteIpValve or similar is configured)
                 // See https://github.com/killbill/killbill/issues/566
                 uriBuilder.scheme(request.getScheme())
-                          .host(MoreObjects.firstNonNull(jaxrsConfig.getJaxrsLocationHost(), uriInfo.getAbsolutePath().getHost())) // Should we look for X-Forwarded-By instead?
+                          .host(MoreObjects.firstNonNull(jaxrsConfig.getJaxrsLocationHost(), request.getServerName()))
                           .port(request.getServerPort());
             } else {
                 uriBuilder.scheme(uriInfo.getAbsolutePath().getScheme())
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoice.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoice.java
index 29ccf26..4b93ff5 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoice.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoice.java
@@ -438,7 +438,10 @@ public class TestInvoice extends TestJaxrsBase {
         final Account accountJson = createAccountNoPMBundleAndSubscriptionAndWaitForFirstInvoice();
 
         // Get the invoices
-        assertEquals(killBillClient.getInvoicesForAccount(accountJson.getAccountId(), requestOptions).size(), 2);
+        final Invoices originalInvoices = killBillClient.getInvoicesForAccount(accountJson.getAccountId(), requestOptions);
+        assertEquals(originalInvoices.size(), 2);
+
+        final UUID firstInvoiceItemId = originalInvoices.get(0).getItems().get(0).getInvoiceItemId();
 
         // Post an external charge
         final BigDecimal chargeAmount = BigDecimal.TEN;
@@ -448,6 +451,7 @@ public class TestInvoice extends TestJaxrsBase {
         externalCharge.setCurrency(accountJson.getCurrency());
         externalCharge.setDescription(UUID.randomUUID().toString());
         externalCharge.setItemDetails("Item Details");
+        externalCharge.setLinkedInvoiceItemId(firstInvoiceItemId);
 
         final LocalDate startDate = clock.getUTCToday();
         externalCharge.setStartDate(startDate);
@@ -464,6 +468,7 @@ public class TestInvoice extends TestJaxrsBase {
         assertEquals(invoiceWithItems.getItems().get(0).getStartDate().compareTo(startDate), 0);
         assertEquals(invoiceWithItems.getItems().get(0).getEndDate().compareTo(endDate), 0);
         assertEquals(invoiceWithItems.getItems().get(0).getItemDetails(), "Item Details");
+        assertEquals(invoiceWithItems.getItems().get(0).getLinkedInvoiceItemId(), firstInvoiceItemId);
 
         // Verify the total number of invoices
         assertEquals(killBillClient.getInvoicesForAccount(accountJson.getAccountId(), requestOptions).size(), 3);