diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
index 06ea733..0531696 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
@@ -19,34 +19,32 @@ package com.ning.billing.beatrix.integration.overdue;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
-import com.google.inject.Inject;
-import com.google.inject.name.Named;
import com.ning.billing.account.api.Account;
import com.ning.billing.api.TestApiListener.NextEvent;
import com.ning.billing.beatrix.integration.BeatrixModule;
import com.ning.billing.beatrix.integration.TestIntegrationBase;
+import com.ning.billing.beatrix.util.InvoiceChecker.ExpectedItemCheck;
import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.PlanPhaseSpecifier;
import com.ning.billing.catalog.api.PriceListSet;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.api.user.SubscriptionBundle;
-import com.ning.billing.entitlement.api.user.SubscriptionData;
import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItemType;
import com.ning.billing.invoice.api.InvoiceUserApi;
import com.ning.billing.junction.api.BlockingApi;
import com.ning.billing.junction.api.BlockingApiException;
@@ -56,15 +54,16 @@ import com.ning.billing.overdue.wrapper.OverdueWrapperFactory;
import com.ning.billing.payment.api.PaymentApi;
import com.ning.billing.payment.api.PaymentMethodPlugin;
import com.ning.billing.payment.provider.MockPaymentProviderPlugin;
-import com.ning.billing.util.callcontext.DefaultCallContext;
import com.ning.billing.util.clock.ClockMock;
import com.ning.billing.util.config.XMLLoader;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
import static com.jayway.awaitility.Awaitility.await;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
@Test(groups = "slow")
@Guice(modules = {BeatrixModule.class})
@@ -97,58 +96,57 @@ public class TestOverdueIntegration extends TestIntegrationBase {
private SubscriptionBundle bundle;
private String productName;
private BillingPeriod term;
- private String planSetName;
@BeforeMethod(groups = "slow")
public void setupOverdue() throws Exception {
final String configXml = "<overdueConfig>" +
- " <bundleOverdueStates>" +
- " <state name=\"OD3\">" +
- " <condition>" +
- " <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
- " <unit>DAYS</unit><number>50</number>" +
- " </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
- " </condition>" +
- " <externalMessage>Reached OD3</externalMessage>" +
- " <blockChanges>true</blockChanges>" +
- " <disableEntitlementAndChangesBlocked>true</disableEntitlementAndChangesBlocked>" +
- " <autoReevaluationInterval>" +
- " <unit>DAYS</unit><number>5</number>" +
- " </autoReevaluationInterval>" +
- " </state>" +
- " <state name=\"OD2\">" +
- " <condition>" +
- " <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
- " <unit>DAYS</unit><number>40</number>" +
- " </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
- " </condition>" +
- " <externalMessage>Reached OD2</externalMessage>" +
- " <blockChanges>true</blockChanges>" +
- " <disableEntitlementAndChangesBlocked>true</disableEntitlementAndChangesBlocked>" +
- " <autoReevaluationInterval>" +
- " <unit>DAYS</unit><number>5</number>" +
- " </autoReevaluationInterval>" +
- " </state>" +
- " <state name=\"OD1\">" +
- " <condition>" +
- " <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
- " <unit>DAYS</unit><number>30</number>" +
- " </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
- " </condition>" +
- " <externalMessage>Reached OD1</externalMessage>" +
- " <blockChanges>true</blockChanges>" +
- " <disableEntitlementAndChangesBlocked>false</disableEntitlementAndChangesBlocked>" +
- " <autoReevaluationInterval>" +
- " <unit>DAYS</unit><number>100</number>" + // this number is intentionally too high
- " </autoReevaluationInterval>" +
- " </state>" +
- " </bundleOverdueStates>" +
- "</overdueConfig>";
+ " <bundleOverdueStates>" +
+ " <state name=\"OD3\">" +
+ " <condition>" +
+ " <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+ " <unit>DAYS</unit><number>50</number>" +
+ " </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+ " </condition>" +
+ " <externalMessage>Reached OD3</externalMessage>" +
+ " <blockChanges>true</blockChanges>" +
+ " <disableEntitlementAndChangesBlocked>true</disableEntitlementAndChangesBlocked>" +
+ " <autoReevaluationInterval>" +
+ " <unit>DAYS</unit><number>5</number>" +
+ " </autoReevaluationInterval>" +
+ " </state>" +
+ " <state name=\"OD2\">" +
+ " <condition>" +
+ " <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+ " <unit>DAYS</unit><number>40</number>" +
+ " </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+ " </condition>" +
+ " <externalMessage>Reached OD2</externalMessage>" +
+ " <blockChanges>true</blockChanges>" +
+ " <disableEntitlementAndChangesBlocked>true</disableEntitlementAndChangesBlocked>" +
+ " <autoReevaluationInterval>" +
+ " <unit>DAYS</unit><number>5</number>" +
+ " </autoReevaluationInterval>" +
+ " </state>" +
+ " <state name=\"OD1\">" +
+ " <condition>" +
+ " <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+ " <unit>DAYS</unit><number>30</number>" +
+ " </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+ " </condition>" +
+ " <externalMessage>Reached OD1</externalMessage>" +
+ " <blockChanges>true</blockChanges>" +
+ " <disableEntitlementAndChangesBlocked>false</disableEntitlementAndChangesBlocked>" +
+ " <autoReevaluationInterval>" +
+ " <unit>DAYS</unit><number>100</number>" + // this number is intentionally too high
+ " </autoReevaluationInterval>" +
+ " </state>" +
+ " </bundleOverdueStates>" +
+ "</overdueConfig>";
final InputStream is = new ByteArrayInputStream(configXml.getBytes());
final OverdueConfig config = XMLLoader.getObjectFromStreamNoValidation(is, OverdueConfig.class);
overdueWrapperFactory.setOverdueConfig(config);
- account = createAccountWithPaymentMethod(getAccountData(25));
+ account = createAccountWithPaymentMethod(getAccountData(0));
assertNotNull(account);
final PaymentMethodPlugin info = new PaymentMethodPlugin() {
@@ -178,7 +176,6 @@ public class TestOverdueIntegration extends TestIntegrationBase {
productName = "Shotgun";
term = BillingPeriod.MONTHLY;
- planSetName = PriceListSet.DEFAULT_PRICELIST_NAME;
// create account
// set mock payments to fail
@@ -191,91 +188,86 @@ public class TestOverdueIntegration extends TestIntegrationBase {
// Clear databases
}
- // We set the the property killbill.payment.retry.days=8,8,8,8,8,8,8,8 so that Payment retry logics does not end with an ABORTED state
+ // We set the the property killbill.payment.retry.days=8,8,8,8,8,8,8,8 so that Payment retry logic does not end with an ABORTED state
// preventing final instant payment to succeed.
- //
@Test(groups = "slow")
public void testBasicOverdueState() throws Exception {
clock.setTime(new DateTime(2012, 5, 1, 0, 3, 42, 0));
paymentPlugin.makeAllInvoicesFailWithError(true);
- // set next invoice to fail and create subscription
- busHandler.pushExpectedEvents(NextEvent.CREATE, NextEvent.INVOICE);
- final Subscription baseSubscription = entitlementUserApi.createSubscription(bundle.getId(), new PlanPhaseSpecifier(productName, ProductCategory.BASE, term, planSetName, null), null, context);
+ // Set next invoice to fail and create subscription
+ final Subscription baseSubscription = createSubscriptionAndCheckForCompletion(bundle.getId(), productName, ProductCategory.BASE, term, NextEvent.CREATE, NextEvent.INVOICE);
- assertNotNull(baseSubscription);
- assertTrue(busHandler.isCompleted(DELAY));
+ invoiceChecker.checkInvoice(account.getId(), 1, new ExpectedItemCheck(new LocalDate(2012, 5, 1), null, InvoiceItemType.FIXED, new BigDecimal("0")));
- busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT_ERROR);
- clock.addDays(30); // DAY 30 have to get out of trial before first payment
+ // DAY 30 have to get out of trial before first payment
+ addDaysAndCheckForCompletion(30, NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT_ERROR);
- assertTrue(busHandler.isCompleted(DELAY));
+ invoiceChecker.checkInvoice(account.getId(), 2, new ExpectedItemCheck(new LocalDate(2012, 5, 31), new LocalDate(2012, 6, 30), InvoiceItemType.RECURRING, new BigDecimal("249.95")));
- // should still be in clear state
+ // Should still be in clear state
checkODState(BlockingApi.CLEAR_STATE_NAME);
- clock.addDays(15); // DAY 45 - 15 days after invoice
- assertTrue(busHandler.isCompleted(DELAY));
- //should still be in clear state
+ // DAY 45 - 15 days after invoice
+ addDaysAndCheckForCompletion(15, NextEvent.PAYMENT_ERROR);
+
+ // Should still be in clear state
checkODState(BlockingApi.CLEAR_STATE_NAME);
- busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT_ERROR);
- clock.addDays(20); // DAY 65 - 35 days after invoice
- assertTrue(busHandler.isCompleted(DELAY));
+ // Note: we have two tracks of payment retries because of the invoice generated at the phase change
+
+ // DAY 65 - 35 days after invoice
+ addDaysAndCheckForCompletion(20, NextEvent.INVOICE, NextEvent.PAYMENT_ERROR, NextEvent.PAYMENT_ERROR);
- //Now we should be in OD1
+ invoiceChecker.checkInvoice(account.getId(), 3, new ExpectedItemCheck(new LocalDate(2012, 6, 30), new LocalDate(2012, 7, 31), InvoiceItemType.RECURRING, new BigDecimal("249.95")));
+
+ // Now we should be in OD1
checkODState("OD1");
checkChangePlanWithOverdueState(baseSubscription, true);
- clock.addDays(2); //DAY 67 - 37 days after invoice
- assertTrue(busHandler.isCompleted(DELAY));
- // should still be in OD1
+ // DAY 67 - 37 days after invoice
+ addDaysAndCheckForCompletion(2);
+
+ // Should still be in OD1
checkODState("OD1");
checkChangePlanWithOverdueState(baseSubscription, true);
- //busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT_ERROR);
- clock.addDays(8); //DAY 75 - 45 days after invoice
- assertTrue(busHandler.isCompleted(DELAY));
- // should still be in OD1
+ // DAY 75 - 45 days after invoice
+ addDaysAndCheckForCompletion(8, NextEvent.PAYMENT_ERROR, NextEvent.PAYMENT_ERROR);
+
+ // Should still be in OD1
checkODState("OD2");
checkChangePlanWithOverdueState(baseSubscription, true);
- busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT_ERROR);
- clock.addDays(10); //DAY 85 - 55 days after invoice
- assertTrue(busHandler.isCompleted(DELAY));
- // should now be in OD2 state once the update is processed
+ // DAY 85 - 55 days after invoice
+ addDaysAndCheckForCompletion(10, NextEvent.PAYMENT_ERROR, NextEvent.PAYMENT_ERROR);
+
+ // Should now be in OD2 state once the update is processed
checkODState("OD3");
checkChangePlanWithOverdueState(baseSubscription, true);
paymentPlugin.makeAllInvoicesFailWithError(false);
final Collection<Invoice> invoices = invoiceApi.getUnpaidInvoicesByAccountId(account.getId(), clock.getUTCToday());
- final List<String> invoiceIds = new ArrayList<String>();
for (final Invoice invoice : invoices) {
- invoiceIds.add(invoice.getId().toString());
if (invoice.getBalance().compareTo(BigDecimal.ZERO) > 0) {
- busHandler.pushExpectedEvent(NextEvent.PAYMENT);
- paymentApi.createPayment(account, invoice.getId(), invoice.getBalance(), new DefaultCallContext("test", null, null, clock));
- assertTrue(busHandler.isCompleted(DELAY));
+ createPaymentAndCheckForCompletion(account, invoice, NextEvent.PAYMENT);
}
}
checkODState(BlockingApi.CLEAR_STATE_NAME);
checkChangePlanWithOverdueState(baseSubscription, false);
-
}
private void checkChangePlanWithOverdueState(final Subscription subscription, final boolean shouldFail) {
- try {
- subscription.changePlan("Pistol", term, planSetName, clock.getUTCNow(), context);
- if (shouldFail) {
- fail("Expected change plan to fail because of OD1 state");
- }
- } catch(EntitlementUserApiException expected) {
- if (shouldFail) {
- assertTrue(expected.getCause() instanceof BlockingApiException);
- } else {
- fail("Expected change plan to succeed because of clean OD state");
+ if (shouldFail) {
+ try {
+ subscription.changePlan("Pistol", term, PriceListSet.DEFAULT_PRICELIST_NAME, clock.getUTCNow(), context);
+ } catch (EntitlementUserApiException e) {
+ assertTrue(e.getCause() instanceof BlockingApiException);
}
+ } else {
+ // Downgrade
+ changeSubscriptionAndCheckForCompletion(subscription, "Pistol", BillingPeriod.MONTHLY, NextEvent.CHANGE);
}
}
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
index 2339a8f..d33cfa9 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
@@ -16,7 +16,6 @@
package com.ning.billing.beatrix.integration;
-import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@@ -31,26 +30,27 @@ import org.skife.jdbi.v2.IDBI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
-import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
-import com.google.inject.Inject;
-import com.google.inject.name.Named;
import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountData;
import com.ning.billing.account.api.AccountService;
import com.ning.billing.account.api.AccountUserApi;
-import com.ning.billing.account.api.BillCycleDay;
import com.ning.billing.analytics.AnalyticsListener;
import com.ning.billing.analytics.api.user.DefaultAnalyticsUserApi;
import com.ning.billing.api.TestApiListener;
+import com.ning.billing.api.TestApiListener.NextEvent;
import com.ning.billing.api.TestListenerStatus;
import com.ning.billing.beatrix.BeatrixTestSuiteWithEmbeddedDB;
import com.ning.billing.beatrix.lifecycle.Lifecycle;
import com.ning.billing.beatrix.util.InvoiceChecker;
+import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.PriceListSet;
+import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.dbi.MysqlTestingHelper;
import com.ning.billing.entitlement.api.EntitlementService;
import com.ning.billing.entitlement.api.timeline.EntitlementTimelineApi;
@@ -63,23 +63,27 @@ import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceItem;
import com.ning.billing.invoice.api.InvoiceService;
import com.ning.billing.invoice.api.InvoiceUserApi;
-import com.ning.billing.invoice.generator.InvoiceDateUtils;
import com.ning.billing.invoice.model.InvoicingConfiguration;
import com.ning.billing.junction.plumbing.api.BlockingSubscription;
import com.ning.billing.mock.MockAccountBuilder;
import com.ning.billing.mock.api.MockBillCycleDay;
import com.ning.billing.overdue.wrapper.OverdueWrapperFactory;
import com.ning.billing.payment.api.PaymentApi;
+import com.ning.billing.payment.api.PaymentApiException;
import com.ning.billing.payment.api.PaymentMethodPlugin;
import com.ning.billing.payment.provider.MockPaymentProviderPlugin;
import com.ning.billing.util.api.TagUserApi;
import com.ning.billing.util.bus.BusService;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.DefaultCallContext;
import com.ning.billing.util.callcontext.DefaultCallContextFactory;
import com.ning.billing.util.callcontext.UserType;
import com.ning.billing.util.clock.ClockMock;
-import com.ning.billing.util.io.IOUtils;
+
+import com.google.common.base.Function;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
@@ -87,6 +91,7 @@ import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implements TestListenerStatus {
+
protected static final DateTimeZone testTimeZone = DateTimeZone.UTC;
protected static final int NUMBER_OF_DECIMALS = InvoicingConfiguration.getNumberOfDecimals();
@@ -306,4 +311,92 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
.timeZone(DateTimeZone.UTC)
.build();
}
+
+ protected void addMonthsAndCheckForCompletion(final int nbMonth, final NextEvent... events) {
+ doCallAndCheckForCompletion(new Function<Void, Void>() {
+ @Override
+ public Void apply(@Nullable final Void dontcare) {
+ clock.addMonths(nbMonth);
+ return null;
+ }
+ }, events);
+ }
+
+ protected void addDaysAndCheckForCompletion(final int nbDays, final NextEvent... events) {
+ doCallAndCheckForCompletion(new Function<Void, Void>() {
+ @Override
+ public Void apply(@Nullable final Void dontcare) {
+ clock.addDays(nbDays);
+ return null;
+ }
+ }, events);
+ }
+
+ protected void createPaymentAndCheckForCompletion(final Account account, final Invoice invoice, final NextEvent... events) {
+ doCallAndCheckForCompletion(new Function<Void, Void>() {
+ @Override
+ public Void apply(@Nullable final Void input) {
+ try {
+ paymentApi.createPayment(account, invoice.getId(), invoice.getBalance(), new DefaultCallContext("test", null, null, clock));
+ } catch (PaymentApiException e) {
+ fail(e.toString());
+ }
+ return null;
+ }
+ }, events);
+ }
+
+ protected Subscription createSubscriptionAndCheckForCompletion(final UUID bundleId,
+ final String productName,
+ final ProductCategory productCategory,
+ final BillingPeriod billingPeriod,
+ final NextEvent... events) {
+ return doCallAndCheckForCompletion(new Function<Void, Subscription>() {
+ @Override
+ public Subscription apply(@Nullable final Void dontcare) {
+ try {
+ final Subscription subscription = entitlementUserApi.createSubscription(bundleId,
+ new PlanPhaseSpecifier(productName, productCategory, billingPeriod, PriceListSet.DEFAULT_PRICELIST_NAME, null),
+ null,
+ context);
+ assertNotNull(subscription);
+ return subscription;
+ } catch (EntitlementUserApiException e) {
+ fail();
+ return null;
+ }
+ }
+ }, events);
+ }
+
+ protected Subscription changeSubscriptionAndCheckForCompletion(final Subscription subscription,
+ final String productName,
+ final BillingPeriod billingPeriod,
+ final NextEvent... events) {
+ return doCallAndCheckForCompletion(new Function<Void, Subscription>() {
+ @Override
+ public Subscription apply(@Nullable final Void dontcare) {
+ try {
+ subscription.changePlan(productName, billingPeriod, PriceListSet.DEFAULT_PRICELIST_NAME, clock.getUTCNow(), context);
+ return subscription;
+ } catch (EntitlementUserApiException e) {
+ fail();
+ return null;
+ }
+ }
+ }, events);
+ }
+
+ private <T> T doCallAndCheckForCompletion(Function<Void, T> f, final NextEvent... events) {
+ log.info(" ************ STARTING BUS HANDLER CHECK ********************");
+
+ busHandler.pushExpectedEvents(events);
+
+ final T result = f.apply(null);
+ assertTrue(busHandler.isCompleted(DELAY));
+ assertListenerStatus();
+
+ log.info(" ************ DONE WITH BUS HANDLER CHECK ********************");
+ return result;
+ }
}
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/util/InvoiceChecker.java b/beatrix/src/test/java/com/ning/billing/beatrix/util/InvoiceChecker.java
index dca65a5..f098895 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/util/InvoiceChecker.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/util/InvoiceChecker.java
@@ -13,37 +13,50 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
+
package com.ning.billing.beatrix.util;
import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;
-
import org.joda.time.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
-import com.google.inject.Inject;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceItem;
import com.ning.billing.invoice.api.InvoiceItemType;
import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.google.common.collect.ImmutableList;
+import com.google.inject.Inject;
+
public class InvoiceChecker {
- private final static Logger log = LoggerFactory.getLogger(InvoiceChecker.class);
+ private static final Logger log = LoggerFactory.getLogger(InvoiceChecker.class);
private final InvoiceUserApi invoiceUserApi;
@Inject
public InvoiceChecker(final InvoiceUserApi invoiceUserApi) {
- this.invoiceUserApi = invoiceUserApi;
+ this.invoiceUserApi = invoiceUserApi;
+ }
+
+ public void checkInvoice(final UUID accountId, final int invoiceOrderingNumber, final ExpectedItemCheck... expected) {
+ checkInvoice(accountId, invoiceOrderingNumber, ImmutableList.<ExpectedItemCheck>copyOf(expected));
+ }
+
+ public void checkInvoice(final UUID accountId, final int invoiceOrderingNumber, final List<ExpectedItemCheck> expected) {
+ final List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(accountId);
+ Assert.assertEquals(invoices.size(), invoiceOrderingNumber);
+ final Invoice invoice = invoices.get(invoiceOrderingNumber - 1);
+ checkInvoice(invoice.getId(), expected);
}
public void checkInvoice(final UUID invoiceId, final List<ExpectedItemCheck> expected) {
- final Invoice invoice =invoiceUserApi.getInvoice(invoiceId);
+ final Invoice invoice = invoiceUserApi.getInvoice(invoiceId);
Assert.assertNotNull(invoice);
final List<InvoiceItem> actual = invoice.getInvoiceItems();
@@ -57,21 +70,21 @@ public class InvoiceChecker {
}
if (in.getAmount().compareTo(cur.getAmount()) != 0) {
log.info(String.format("Found item type = %s and startDate = %s but amount differ (actual = %s, expected = %s) ",
- cur.getType(), cur.getStartDate(), in.getAmount(), cur.getAmount()));
+ cur.getType(), cur.getStartDate(), in.getAmount(), cur.getAmount()));
continue;
}
if ((cur.getEndDate() == null && in.getEndDate() == null) ||
- (cur.getEndDate() != null && in.getEndDate() != null && cur.getEndDate().compareTo(in.getEndDate()) == 0)) {
+ (cur.getEndDate() != null && in.getEndDate() != null && cur.getEndDate().compareTo(in.getEndDate()) == 0)) {
found = true;
break;
}
log.info(String.format("Found item type = %s and startDate = %s, amount = %s but endDate differ (actual = %s, expected = %s) ",
- cur.getType(), cur.getStartDate(), in.getAmount(), in.getEndDate(), cur.getEndDate()));
+ cur.getType(), cur.getStartDate(), in.getAmount(), in.getEndDate(), cur.getEndDate()));
}
if (!found) {
- Assert.fail(String.format("Failed to find invoice item type = %s and startDate = %s, amount = %s, endDate = %s",
- cur.getType(), cur.getStartDate(), cur.getAmount(), cur.getEndDate()));
+ Assert.fail(String.format("Failed to find invoice item type = %s and startDate = %s, amount = %s, endDate = %s for invoice id %s",
+ cur.getType(), cur.getStartDate(), cur.getAmount(), cur.getEndDate(), invoice.getId()));
}
}
}
@@ -84,7 +97,7 @@ public class InvoiceChecker {
private final BigDecimal Amount;
public ExpectedItemCheck(final LocalDate startDate, final LocalDate endDate,
- final InvoiceItemType type, final BigDecimal amount) {
+ final InvoiceItemType type, final BigDecimal amount) {
this.startDate = startDate;
this.endDate = endDate;
this.type = type;
@@ -94,12 +107,15 @@ public class InvoiceChecker {
public LocalDate getStartDate() {
return startDate;
}
+
public LocalDate getEndDate() {
return endDate;
}
+
public InvoiceItemType getType() {
return type;
}
+
public BigDecimal getAmount() {
return Amount;
}