killbill-uncached
Changes
beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithDifferentBillingPeriods.java 315(+315 -0)
beatrix/src/test/resources/catalogSample.xml 35(+35 -0)
Details
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithDifferentBillingPeriods.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithDifferentBillingPeriods.java
new file mode 100644
index 0000000..f8abb84
--- /dev/null
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithDifferentBillingPeriods.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2010-2014 Ning, Inc.
+ *
+ * Ning 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:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.beatrix.integration;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import org.joda.time.DateTimeZone;
+import org.joda.time.LocalDate;
+import org.testng.annotations.Test;
+
+import com.ning.billing.ObjectType;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.api.TestApiListener.NextEvent;
+import com.ning.billing.beatrix.util.InvoiceChecker.ExpectedInvoiceItemCheck;
+import com.ning.billing.catalog.api.BillingActionPolicy;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.entitlement.api.DefaultEntitlement;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItemType;
+import com.ning.billing.util.tag.ControlTagType;
+
+import com.google.common.collect.ImmutableList;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+public class TestIntegrationWithDifferentBillingPeriods extends TestIntegrationBase {
+
+ @Test(groups = "slow")
+ public void testChangeMonthlyToAnnual() throws Exception {
+
+ // We take april as it has 30 days (easier to play with BCD)
+ final LocalDate today = new LocalDate(2012, 4, 1);
+ final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(1));
+
+ // Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
+ clock.setDeltaFromReality(today.toDateTimeAtCurrentTime(DateTimeZone.UTC).getMillis() - clock.getUTCNow().getMillis());
+
+ final String productName = "Shotgun";
+
+ //
+ // CREATE SUBSCRIPTION AND EXPECT BOTH EVENTS: NextEvent.CREATE NextEvent.INVOICE
+ //
+
+ final DefaultEntitlement bpEntitlement = createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey", productName, ProductCategory.BASE, BillingPeriod.MONTHLY, NextEvent.CREATE, NextEvent.INVOICE);
+ assertNotNull(bpEntitlement);
+ assertEquals(invoiceUserApi.getInvoicesByAccount(account.getId(), callContext).size(), 1);
+
+ assertEquals(bpEntitlement.getSubscriptionBase().getCurrentPlan().getBillingPeriod(), BillingPeriod.MONTHLY);
+
+ // Move out of trials for interesting invoices adjustments
+ busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT);
+ clock.addDays(31);
+ assertListenerStatus();
+
+ List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), callContext);
+ assertEquals(invoices.size(), 2);
+ ImmutableList<ExpectedInvoiceItemCheck> toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 1), new LocalDate(2012, 6, 1), InvoiceItemType.RECURRING, new BigDecimal("249.95")));
+ invoiceChecker.checkInvoice(invoices.get(1).getId(), callContext, toBeChecked);
+
+ //
+ // MOVE MONTHLY TO ANNUAL
+ //
+ clock.addDays(10);
+
+ changeEntitlementAndCheckForCompletion(bpEntitlement, productName, BillingPeriod.ANNUAL, BillingActionPolicy.IMMEDIATE, NextEvent.CHANGE, NextEvent.INVOICE, NextEvent.INVOICE_ADJUSTMENT, NextEvent.PAYMENT);
+
+ invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), callContext);
+ assertEquals(invoices.size(), 3);
+
+ toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 1), new LocalDate(2012, 6, 1), InvoiceItemType.RECURRING, new BigDecimal("249.95")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 12), new LocalDate(2012, 5, 12), InvoiceItemType.CBA_ADJ, new BigDecimal("161.27")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 12), new LocalDate(2012, 6, 1), InvoiceItemType.REPAIR_ADJ, new BigDecimal("-161.27")));
+ invoiceChecker.checkInvoice(invoices.get(1).getId(), callContext, toBeChecked);
+
+ toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 12), new LocalDate(2013, 5, 1), InvoiceItemType.RECURRING, new BigDecimal("2327.71")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 12), new LocalDate(2012, 5, 12), InvoiceItemType.CBA_ADJ, new BigDecimal("-161.27")));
+ invoiceChecker.checkInvoice(invoices.get(2).getId(), callContext, toBeChecked);
+ }
+
+ @Test(groups = "slow")
+ public void testChangeMonthlyToQuarterly() throws Exception {
+
+ // We take april as it has 30 days (easier to play with BCD)
+ final LocalDate today = new LocalDate(2012, 4, 1);
+ final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(1));
+
+ // Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
+ clock.setDeltaFromReality(today.toDateTimeAtCurrentTime(DateTimeZone.UTC).getMillis() - clock.getUTCNow().getMillis());
+
+ final String productName = "Pistol";
+
+ //
+ // CREATE SUBSCRIPTION AND EXPECT BOTH EVENTS: NextEvent.CREATE NextEvent.INVOICE
+ //
+
+ final DefaultEntitlement bpEntitlement = createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey", productName, ProductCategory.BASE, BillingPeriod.MONTHLY, NextEvent.CREATE, NextEvent.INVOICE);
+ assertNotNull(bpEntitlement);
+ assertEquals(invoiceUserApi.getInvoicesByAccount(account.getId(), callContext).size(), 1);
+
+ assertEquals(bpEntitlement.getSubscriptionBase().getCurrentPlan().getBillingPeriod(), BillingPeriod.MONTHLY);
+
+ // Move out of trials for interesting invoices adjustments
+ busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT);
+ clock.addDays(31);
+ assertListenerStatus();
+
+ List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), callContext);
+ assertEquals(invoices.size(), 2);
+ ImmutableList<ExpectedInvoiceItemCheck> toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 1), new LocalDate(2012, 6, 1), InvoiceItemType.RECURRING, new BigDecimal("29.95")));
+ invoiceChecker.checkInvoice(invoices.get(1).getId(), callContext, toBeChecked);
+
+ //
+ // MOVE MONTHLY TO QUARTERLY
+ //
+ clock.addDays(10);
+
+ changeEntitlementAndCheckForCompletion(bpEntitlement, productName, BillingPeriod.QUARTERLY, BillingActionPolicy.IMMEDIATE, NextEvent.CHANGE, NextEvent.INVOICE, NextEvent.INVOICE_ADJUSTMENT, NextEvent.PAYMENT);
+
+ invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), callContext);
+ assertEquals(invoices.size(), 3);
+
+ toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 1), new LocalDate(2012, 6, 1), InvoiceItemType.RECURRING, new BigDecimal("29.95")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 12), new LocalDate(2012, 5, 12), InvoiceItemType.CBA_ADJ, new BigDecimal("19.32")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 12), new LocalDate(2012, 6, 1), InvoiceItemType.REPAIR_ADJ, new BigDecimal("-19.32")));
+ invoiceChecker.checkInvoice(invoices.get(1).getId(), callContext, toBeChecked);
+
+ toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 12), new LocalDate(2012, 8, 1), InvoiceItemType.RECURRING, new BigDecimal("61.58")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 12), new LocalDate(2012, 5, 12), InvoiceItemType.CBA_ADJ, new BigDecimal("-19.32")));
+ invoiceChecker.checkInvoice(invoices.get(2).getId(), callContext, toBeChecked);
+
+ // Move to 1020-08-01
+ busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT);
+ clock.addDays(20);
+ clock.addMonths(2);
+ assertListenerStatus();
+
+ invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), callContext);
+ assertEquals(invoices.size(), 4);
+
+ toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 8, 1), new LocalDate(2012, 11, 1), InvoiceItemType.RECURRING, new BigDecimal("69.95")));
+ invoiceChecker.checkInvoice(invoices.get(3).getId(), callContext, toBeChecked);
+
+ }
+
+ @Test(groups = "slow")
+ public void testPauseResumeAnnual() throws Exception {
+
+ // We take april as it has 30 days (easier to play with BCD)
+ final LocalDate today = new LocalDate(2012, 4, 1);
+ final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(1));
+
+ // Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
+ clock.setDeltaFromReality(today.toDateTimeAtCurrentTime(DateTimeZone.UTC).getMillis() - clock.getUTCNow().getMillis());
+
+ final String productName = "Shotgun";
+
+ //
+ // CREATE SUBSCRIPTION AND EXPECT BOTH EVENTS: NextEvent.CREATE NextEvent.INVOICE
+ //
+
+ final DefaultEntitlement bpEntitlement = createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey", productName, ProductCategory.BASE, BillingPeriod.ANNUAL, NextEvent.CREATE, NextEvent.INVOICE);
+ assertNotNull(bpEntitlement);
+ assertEquals(invoiceUserApi.getInvoicesByAccount(account.getId(), callContext).size(), 1);
+
+ assertEquals(bpEntitlement.getSubscriptionBase().getCurrentPlan().getBillingPeriod(), BillingPeriod.ANNUAL);
+
+ // Move out of trials for interesting invoices adjustments
+ busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT);
+ clock.addDays(31);
+ assertListenerStatus();
+
+ // 2012-5-12
+ clock.addDays(10);
+
+ busHandler.pushExpectedEvents(NextEvent.PAUSE, NextEvent.BLOCK, NextEvent.INVOICE_ADJUSTMENT);
+ entitlementApi.pause(bpEntitlement.getBundleId(), clock.getUTCNow().toLocalDate(), callContext);
+ assertListenerStatus();
+
+ List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), callContext);
+ assertEquals(invoices.size(), 2);
+
+ ImmutableList<ExpectedInvoiceItemCheck> toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 1), new LocalDate(2013, 5, 1), InvoiceItemType.RECURRING, new BigDecimal("2399.95")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 12), new LocalDate(2012, 5, 12), InvoiceItemType.CBA_ADJ, new BigDecimal("2327.71")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 12), new LocalDate(2013, 5, 1), InvoiceItemType.REPAIR_ADJ, new BigDecimal("-2327.71")));
+ invoiceChecker.checkInvoice(invoices.get(1).getId(), callContext, toBeChecked);
+
+ // 2012-6-4
+ clock.addDays(23);
+
+ busHandler.pushExpectedEvents(NextEvent.RESUME, NextEvent.BLOCK, NextEvent.INVOICE, NextEvent.PAYMENT);
+ entitlementApi.resume(bpEntitlement.getBundleId(), clock.getUTCNow().toLocalDate(), callContext);
+ assertListenerStatus();
+
+ invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), callContext);
+ assertEquals(invoices.size(), 3);
+
+ toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 6, 4), new LocalDate(2013, 6, 1), InvoiceItemType.RECURRING, new BigDecimal("2380.27")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 6, 4), new LocalDate(2012, 6, 4), InvoiceItemType.CBA_ADJ, new BigDecimal("-2327.71")));
+ invoiceChecker.checkInvoice(invoices.get(2).getId(), callContext, toBeChecked);
+
+ busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT);
+ clock.addYears(1);
+ assertListenerStatus();
+
+ invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), callContext);
+ assertEquals(invoices.size(), 4);
+
+ toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2013, 6, 1), new LocalDate(2014, 6, 1), InvoiceItemType.RECURRING, new BigDecimal("2399.95")));
+ invoiceChecker.checkInvoice(invoices.get(3).getId(), callContext, toBeChecked);
+ }
+
+ @Test(groups = "slow")
+ public void testPauseResumeAnnualWithInvoicingOff() throws Exception {
+
+ // We take april as it has 30 days (easier to play with BCD)
+ final LocalDate today = new LocalDate(2012, 4, 1);
+ final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(1));
+
+ // Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
+ clock.setDeltaFromReality(today.toDateTimeAtCurrentTime(DateTimeZone.UTC).getMillis() - clock.getUTCNow().getMillis());
+
+ final String productName = "Shotgun";
+
+ //
+ // CREATE SUBSCRIPTION AND EXPECT BOTH EVENTS: NextEvent.CREATE NextEvent.INVOICE
+ //
+
+ final DefaultEntitlement bpEntitlement = createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey", productName, ProductCategory.BASE, BillingPeriod.ANNUAL, NextEvent.CREATE, NextEvent.INVOICE);
+ assertNotNull(bpEntitlement);
+ assertEquals(invoiceUserApi.getInvoicesByAccount(account.getId(), callContext).size(), 1);
+
+ assertEquals(bpEntitlement.getSubscriptionBase().getCurrentPlan().getBillingPeriod(), BillingPeriod.ANNUAL);
+
+ // Move out of trials for interesting invoices adjustments
+ busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT);
+ clock.addDays(31);
+ assertListenerStatus();
+
+ // Auto invoice off
+ busHandler.pushExpectedEvents(NextEvent.TAG);
+ tagUserApi.addTag(account.getId(), ObjectType.ACCOUNT, ControlTagType.AUTO_INVOICING_OFF.getId(), callContext);
+ assertListenerStatus();
+
+ // 2012-5-12
+ clock.addDays(10);
+
+ busHandler.pushExpectedEvents(NextEvent.PAUSE, NextEvent.BLOCK);
+ entitlementApi.pause(bpEntitlement.getBundleId(), clock.getUTCNow().toLocalDate(), callContext);
+ assertListenerStatus();
+
+ // 2012-6-4
+ clock.addDays(23);
+ busHandler.pushExpectedEvents(NextEvent.RESUME, NextEvent.BLOCK);
+ entitlementApi.resume(bpEntitlement.getBundleId(), clock.getUTCNow().toLocalDate(), callContext);
+ assertListenerStatus();
+
+
+ busHandler.pushExpectedEvents(NextEvent.TAG, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_ADJUSTMENT);
+ tagUserApi.removeTag(account.getId(), ObjectType.ACCOUNT, ControlTagType.AUTO_INVOICING_OFF.getId(), callContext);
+ assertListenerStatus();
+
+ List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), callContext);
+ assertEquals(invoices.size(), 3);
+
+
+ ImmutableList<ExpectedInvoiceItemCheck> toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 1), new LocalDate(2013, 5, 1), InvoiceItemType.RECURRING, new BigDecimal("2399.95")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 6, 4), new LocalDate(2012, 6, 4), InvoiceItemType.CBA_ADJ, new BigDecimal("2327.71")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 12), new LocalDate(2013, 5, 1), InvoiceItemType.REPAIR_ADJ, new BigDecimal("-2327.71")));
+ invoiceChecker.checkInvoice(invoices.get(1).getId(), callContext, toBeChecked);
+
+ toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 6, 4), new LocalDate(2013, 6, 1), InvoiceItemType.RECURRING, new BigDecimal("2380.27")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 6, 4), new LocalDate(2012, 6, 4), InvoiceItemType.CBA_ADJ, new BigDecimal("-2327.71")));
+ invoiceChecker.checkInvoice(invoices.get(2).getId(), callContext, toBeChecked);
+
+ busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT);
+ clock.addYears(1);
+ assertListenerStatus();
+
+ invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), callContext);
+ assertEquals(invoices.size(), 4);
+
+ toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
+ new ExpectedInvoiceItemCheck(new LocalDate(2013, 6, 1), new LocalDate(2014, 6, 1), InvoiceItemType.RECURRING, new BigDecimal("2399.95")));
+ invoiceChecker.checkInvoice(invoices.get(3).getId(), callContext, toBeChecked);
+ }
+}
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestSubscription.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestSubscription.java
index c99bca8..a8b442b 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestSubscription.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestSubscription.java
@@ -109,8 +109,8 @@ public class TestSubscription extends TestIntegrationBase {
invoiceChecker.checkInvoice(invoices.get(2).getId(), callContext, toBeChecked);
toBeChecked = ImmutableList.<ExpectedInvoiceItemCheck>of(
- new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 11), new LocalDate(2012, 6, 1), InvoiceItemType.RECURRING, new BigDecimal("137.76")),
- new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 11), new LocalDate(2012, 5, 11), InvoiceItemType.CBA_ADJ, new BigDecimal("-137.76")));
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 11), new LocalDate(2013, 5, 1), InvoiceItemType.RECURRING, new BigDecimal("2334.19")),
+ new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 11), new LocalDate(2012, 5, 11), InvoiceItemType.CBA_ADJ, new BigDecimal("-2334.19")));
invoiceChecker.checkInvoice(invoices.get(3).getId(), callContext, toBeChecked);
}
beatrix/src/test/resources/catalogSample.xml 35(+35 -0)
diff --git a/beatrix/src/test/resources/catalogSample.xml b/beatrix/src/test/resources/catalogSample.xml
index d6531b1..e7e47d2 100644
--- a/beatrix/src/test/resources/catalogSample.xml
+++ b/beatrix/src/test/resources/catalogSample.xml
@@ -322,6 +322,40 @@
</recurringPrice>
</finalPhase>
</plan>
+ <plan name="pistol-quarterly">
+ <product>Pistol</product>
+ <initialPhases>
+ <phase type="TRIAL">
+ <duration>
+ <unit>DAYS</unit>
+ <number>30</number>
+ </duration>
+ <billingPeriod>NO_BILLING_PERIOD</billingPeriod>
+ <fixedPrice> <!-- empty price implies $0 -->
+ </fixedPrice>
+ </phase>
+ </initialPhases>
+ <finalPhase type="EVERGREEN">
+ <duration>
+ <unit>UNLIMITED</unit>
+ </duration>
+ <billingPeriod>QUARTERLY</billingPeriod>
+ <recurringPrice>
+ <price>
+ <currency>GBP</currency>
+ <value>69.95</value>
+ </price>
+ <price>
+ <currency>EUR</currency>
+ <value>69.95</value>
+ </price>
+ <price>
+ <currency>USD</currency>
+ <value>69.95</value>
+ </price>
+ </recurringPrice>
+ </finalPhase>
+ </plan>
<plan name="pistol-annual">
<product>Pistol</product>
<initialPhases>
@@ -867,6 +901,7 @@
<plan>shotgun-monthly</plan>
<plan>assault-rifle-monthly</plan>
<plan>pistol-annual</plan>
+ <plan>pistol-quarterly</plan>
<plan>shotgun-annual</plan>
<plan>assault-rifle-annual</plan>
<plan>laser-scope-monthly</plan>
diff --git a/invoice/src/main/java/com/ning/billing/invoice/generator/BillingIntervalDetail.java b/invoice/src/main/java/com/ning/billing/invoice/generator/BillingIntervalDetail.java
index c54a084..9c7de27 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/generator/BillingIntervalDetail.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/generator/BillingIntervalDetail.java
@@ -22,9 +22,6 @@ import com.ning.billing.catalog.api.BillingPeriod;
public class BillingIntervalDetail {
-
- private final boolean shouldUsePatch = true;
-
private final LocalDate startDate;
private final LocalDate endDate;
private final LocalDate targetDate;
@@ -78,11 +75,14 @@ public class BillingIntervalDetail {
billingCycleDate = new LocalDate(startDate.getYear(), startDate.getMonthOfYear(), billingCycleDay, startDate.getChronology());
}
+ int numberOfPeriods = 0;
+ final int numberOfMonthsInPeriod = billingPeriod.getNumberOfMonths();
LocalDate proposedDate = billingCycleDate;
while (proposedDate.isBefore(startDate)) {
- proposedDate = proposedDate.plusMonths(1);
+ proposedDate = proposedDate.plusMonths(numberOfPeriods * numberOfMonthsInPeriod);
+ numberOfPeriods += 1;
}
- firstBillingCycleDate = proposedDate;
+ firstBillingCycleDate = alignProposedBillCycleDate(proposedDate);
}
private void calculateEffectiveEndDate() {
@@ -144,9 +144,6 @@ public class BillingIntervalDetail {
// We start from a billCycleDate
//
private LocalDate alignProposedBillCycleDate(final LocalDate proposedDate) {
- if (!shouldUsePatch) {
- return proposedDate;
- }
final int lastDayOfMonth = proposedDate.dayOfMonth().getMaximumValue();
int proposedBillCycleDate = proposedDate.getDayOfMonth();
diff --git a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceHelper.java b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceHelper.java
index 17c2f2c..e2f53c6 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceHelper.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceHelper.java
@@ -112,7 +112,6 @@ public class TestInvoiceHelper {
public static final BigDecimal TWENTY_FOUR = new BigDecimal("24.0").setScale(NUMBER_OF_DECIMALS);
public static final BigDecimal TWENTY_FIVE = new BigDecimal("25.0").setScale(NUMBER_OF_DECIMALS);
- public static final BigDecimal TWENTY_SEVEN = new BigDecimal("27.0").setScale(NUMBER_OF_DECIMALS);
public static final BigDecimal TWENTY_EIGHT = new BigDecimal("28.0").setScale(NUMBER_OF_DECIMALS);
public static final BigDecimal TWENTY_NINE = new BigDecimal("29.0").setScale(NUMBER_OF_DECIMALS);
public static final BigDecimal THIRTY = new BigDecimal("30.0").setScale(NUMBER_OF_DECIMALS);
@@ -120,6 +119,8 @@ public class TestInvoiceHelper {
public static final BigDecimal FORTY = new BigDecimal("40.0").setScale(NUMBER_OF_DECIMALS);
+ public static final BigDecimal SEVENTY_FIVE = new BigDecimal("75.0").setScale(NUMBER_OF_DECIMALS);
+
public static final BigDecimal EIGHTY_NINE = new BigDecimal("89.0").setScale(NUMBER_OF_DECIMALS);
public static final BigDecimal NINETY = new BigDecimal("90.0").setScale(NUMBER_OF_DECIMALS);
public static final BigDecimal NINETY_ONE = new BigDecimal("91.0").setScale(NUMBER_OF_DECIMALS);
@@ -127,6 +128,9 @@ public class TestInvoiceHelper {
public static final BigDecimal ONE_HUNDRED = new BigDecimal("100.0").setScale(NUMBER_OF_DECIMALS);
+ public static final BigDecimal THREE_HUNDRED_AND_FOURTY_NINE = new BigDecimal("349.0").setScale(NUMBER_OF_DECIMALS);
+ public static final BigDecimal THREE_HUNDRED_AND_FIFTY_FOUR = new BigDecimal("354.0").setScale(NUMBER_OF_DECIMALS);
+
public static final BigDecimal THREE_HUNDRED_AND_SIXTY_FIVE = new BigDecimal("365.0").setScale(NUMBER_OF_DECIMALS);
public static final BigDecimal THREE_HUNDRED_AND_SIXTY_SIX = new BigDecimal("366.0").setScale(NUMBER_OF_DECIMALS);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/TestProRation.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/TestProRation.java
index dde0beb..1fb7106 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/TestProRation.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/TestProRation.java
@@ -20,6 +20,7 @@ import static com.ning.billing.invoice.TestInvoiceHelper.*;
import java.math.BigDecimal;
+import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.testng.annotations.Test;
@@ -39,16 +40,18 @@ public class TestProRation extends ProRationInAdvanceTestBase {
final LocalDate startDate = invoiceUtil.buildDate(2011, 1, 31);
final LocalDate targetDate = invoiceUtil.buildDate(2011, 2, 24);
- final BigDecimal expectedValue = ONE.add(FIFTEEN.divide(THREE_HUNDRED_AND_SIXTY_FIVE, NUMBER_OF_DECIMALS, ROUNDING_METHOD));
+ // THREE_HUNDRED_AND_FOURTY_NINE is number of days between startDate and expected first billing cycle date (2012, 1, 15);
+ final BigDecimal expectedValue = THREE_HUNDRED_AND_FOURTY_NINE.divide(THREE_HUNDRED_AND_SIXTY_FIVE, NUMBER_OF_DECIMALS, ROUNDING_METHOD);
testCalculateNumberOfBillingCycles(startDate, targetDate, 15, expectedValue);
}
@Test(groups = "fast")
public void testSinglePlan_PrecedingProRation_CrossingYearBoundary() throws InvalidDateSequenceException {
final LocalDate startDate = invoiceUtil.buildDate(2010, 12, 15);
- final LocalDate targetDate = invoiceUtil.buildDate(2011, 1, 13);
+ final LocalDate targetDate = invoiceUtil.buildDate(2012, 1, 13);
- final BigDecimal expectedValue = ONE.add(TWENTY.divide(THREE_HUNDRED_AND_SIXTY_FIVE, NUMBER_OF_DECIMALS, ROUNDING_METHOD));
+ // THREE_HUNDRED_AND_FOURTY_NINE is number of days between startDate and expected first billing cycle date (2011, 12, 4);
+ final BigDecimal expectedValue = ONE.add(THREE_HUNDRED_AND_FIFTY_FOUR.divide(THREE_HUNDRED_AND_SIXTY_FIVE, NUMBER_OF_DECIMALS, ROUNDING_METHOD));
testCalculateNumberOfBillingCycles(startDate, targetDate, 4, expectedValue);
}
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/TestProRation.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/TestProRation.java
index ce3608e..ada9ec9 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/TestProRation.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/TestProRation.java
@@ -20,6 +20,7 @@ import static com.ning.billing.invoice.TestInvoiceHelper.*;
import java.math.BigDecimal;
+import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.testng.annotations.Test;
@@ -44,35 +45,23 @@ public class TestProRation extends ProRationInAdvanceTestBase {
expectedValue = FOURTEEN.divide(EIGHTY_NINE, NUMBER_OF_DECIMALS, ROUNDING_METHOD);
testCalculateNumberOfBillingCycles(startDate, phaseChangeDate, targetDate, 10, expectedValue);
- expectedValue = FOURTEEN.divide(NINETY, NUMBER_OF_DECIMALS, ROUNDING_METHOD);
+ // 75 is number of days between phaseChangeDate and next billing cycle date (2011, 5, 10)
+ // 89 is total number of days between the next and previous billing period (2011, 2, 10) -> (2011, 5, 10)
+ expectedValue = SEVENTY_FIVE.divide(EIGHTY_NINE, NUMBER_OF_DECIMALS, ROUNDING_METHOD);
testCalculateNumberOfBillingCycles(phaseChangeDate, targetDate, 10, expectedValue);
}
@Test(groups = "fast")
- public void testSinglePlan_WithPhaseChange_BeforeBillCycleDay() throws InvalidDateSequenceException {
- final LocalDate startDate = invoiceUtil.buildDate(2011, 2, 3);
- final LocalDate phaseChangeDate = invoiceUtil.buildDate(2011, 2, 17);
- final LocalDate targetDate = invoiceUtil.buildDate(2011, 3, 1);
-
- BigDecimal expectedValue;
- expectedValue = FOURTEEN.divide(EIGHTY_NINE, NUMBER_OF_DECIMALS, ROUNDING_METHOD);
- testCalculateNumberOfBillingCycles(startDate, phaseChangeDate, targetDate, 3, expectedValue);
-
- expectedValue = FOURTEEN.divide(NINETY, NUMBER_OF_DECIMALS, ROUNDING_METHOD);
- testCalculateNumberOfBillingCycles(phaseChangeDate, targetDate, 3, expectedValue);
- }
-
- @Test(groups = "fast")
public void testSinglePlan_WithPhaseChange_OnBillCycleDay() throws InvalidDateSequenceException {
final LocalDate startDate = invoiceUtil.buildDate(2011, 2, 3);
final LocalDate phaseChangeDate = invoiceUtil.buildDate(2011, 2, 17);
- final LocalDate targetDate = invoiceUtil.buildDate(2011, 3, 3);
+ final LocalDate targetDate = invoiceUtil.buildDate(2011, 5, 3);
BigDecimal expectedValue;
expectedValue = FOURTEEN.divide(EIGHTY_NINE, NUMBER_OF_DECIMALS, ROUNDING_METHOD);
testCalculateNumberOfBillingCycles(startDate, phaseChangeDate, targetDate, 3, expectedValue);
- expectedValue = FOURTEEN.divide(NINETY, NUMBER_OF_DECIMALS, ROUNDING_METHOD).add(ONE);
+ expectedValue = ONE.add(SEVENTY_FIVE.divide(EIGHTY_NINE, NUMBER_OF_DECIMALS, ROUNDING_METHOD));
testCalculateNumberOfBillingCycles(phaseChangeDate, targetDate, 3, expectedValue);
}
@@ -80,13 +69,13 @@ public class TestProRation extends ProRationInAdvanceTestBase {
public void testSinglePlan_WithPhaseChange_AfterBillCycleDay() throws InvalidDateSequenceException {
final LocalDate startDate = invoiceUtil.buildDate(2011, 2, 3);
final LocalDate phaseChangeDate = invoiceUtil.buildDate(2011, 2, 17);
- final LocalDate targetDate = invoiceUtil.buildDate(2011, 3, 4);
+ final LocalDate targetDate = invoiceUtil.buildDate(2011, 5, 4);
BigDecimal expectedValue;
expectedValue = FOURTEEN.divide(EIGHTY_NINE, NUMBER_OF_DECIMALS, ROUNDING_METHOD);
testCalculateNumberOfBillingCycles(startDate, phaseChangeDate, targetDate, 3, expectedValue);
- expectedValue = FOURTEEN.divide(NINETY, NUMBER_OF_DECIMALS, ROUNDING_METHOD).add(ONE);
+ expectedValue = SEVENTY_FIVE.divide(EIGHTY_NINE, NUMBER_OF_DECIMALS, ROUNDING_METHOD).add(ONE);
testCalculateNumberOfBillingCycles(phaseChangeDate, targetDate, 3, expectedValue);
}
@@ -235,12 +224,13 @@ public class TestProRation extends ProRationInAdvanceTestBase {
final LocalDate targetDate = invoiceUtil.buildDate(2011, 5, 21);
BigDecimal expectedValue;
- expectedValue = SEVEN.divide(NINETY_TWO, NUMBER_OF_DECIMALS, ROUNDING_METHOD);
- expectedValue = expectedValue.add(ONE);
- expectedValue = expectedValue.add(THREE.divide(NINETY_TWO, NUMBER_OF_DECIMALS, ROUNDING_METHOD));
+ // startDate, 2011, 4, 7 -> 66 days out of 2011, 1, 7, 2011, 4, 7 -> 90
+ expectedValue = new BigDecimal("66.00").divide(NINETY, 2 * NUMBER_OF_DECIMALS, ROUNDING_METHOD);
+ // 2011, 1, 7, planChangeDate-> 33 days out of 2011, 4, 7, 2011, 7, 7 -> 89
+ expectedValue = expectedValue.add(new BigDecimal("33.00").divide(NINETY_ONE, 2 * NUMBER_OF_DECIMALS, ROUNDING_METHOD)).setScale(NUMBER_OF_DECIMALS, ROUNDING_METHOD);
testCalculateNumberOfBillingCycles(startDate, planChangeDate, targetDate, 7, expectedValue);
- expectedValue = FIVE.divide(EIGHTY_NINE, NUMBER_OF_DECIMALS, ROUNDING_METHOD).add(ONE);
+ expectedValue = FIVE.divide(EIGHTY_NINE, NUMBER_OF_DECIMALS, ROUNDING_METHOD).add(ONE).setScale(NUMBER_OF_DECIMALS, ROUNDING_METHOD);
testCalculateNumberOfBillingCycles(planChangeDate, targetDate, 15, expectedValue);
}
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tree/TestSubscriptionItemTree.java b/invoice/src/test/java/com/ning/billing/invoice/tree/TestSubscriptionItemTree.java
index f34b1e9..258ada8 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tree/TestSubscriptionItemTree.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tree/TestSubscriptionItemTree.java
@@ -807,8 +807,6 @@ public class TestSubscriptionItemTree /* extends InvoiceTestSuiteNoDB */ {
tree.getRoot().jsonSerializeTree(new ObjectMapper(), outputStream);
final String json = outputStream.toString("UTF-8");
- System.out.println(json);
-
final String expectedJson = "[{\"start\":\"2014-01-01\",\"end\":\"2015-01-01\",\"items\":[{\"id\":\"e8ba6ce7-9bd4-417d-af53-70951ecaa99f\",\"startDate\":\"2014-01-01\",\"endDate\":\"2015-01-01\",\"amount\":10,\"currency\":\"USD\",\"linkedId\":null,\"action\":\"ADD\"}]},[{\"start\":\"2014-08-01\",\"end\":\"2015-01-01\",\"items\":[{\"id\":\"48db1317-9a6e-4666-bcc5-fc7d3d0defc8\",\"startDate\":\"2014-08-01\",\"endDate\":\"2015-01-01\",\"amount\":1,\"currency\":\"USD\",\"linkedId\":null,\"action\":\"ADD\"},{\"id\":\"02ec57f5-2723-478b-86ba-ebeaedacb9db\",\"startDate\":\"2014-08-01\",\"endDate\":\"2015-01-01\",\"amount\":10,\"currency\":\"USD\",\"linkedId\":\"e8ba6ce7-9bd4-417d-af53-70951ecaa99f\",\"action\":\"CANCEL\"}]}]]";
assertEquals(json, expectedJson);