killbill-memoizeit

Changes

Details

diff --git a/api/src/main/java/org/killbill/billing/junction/BillingEvent.java b/api/src/main/java/org/killbill/billing/junction/BillingEvent.java
index 02e0bb6..7a222a3 100644
--- a/api/src/main/java/org/killbill/billing/junction/BillingEvent.java
+++ b/api/src/main/java/org/killbill/billing/junction/BillingEvent.java
@@ -86,16 +86,19 @@ public interface BillingEvent extends Comparable<BillingEvent> {
     /**
      * @return the recurring price for the phase
      */
-    BigDecimal getRecurringPrice();
+    BigDecimal getRecurringPrice(DateTime requestedDate) throws CatalogApiException;
 
     /**
      * @return the currency for the account being invoiced
      */
     Currency getCurrency();
 
-    /**
-     * @return the transition type of the underlying subscription event that triggered this
-     */
+
+    public DateTime getLastChangePlanDate();
+
+        /**
+         * @return the transition type of the underlying subscription event that triggered this
+         */
     SubscriptionBaseTransitionType getTransitionType();
 
     /**
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestCatalogWithEffectiveDateForExistingSubscriptions.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestCatalogWithEffectiveDateForExistingSubscriptions.java
new file mode 100644
index 0000000..8fd168f
--- /dev/null
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestCatalogWithEffectiveDateForExistingSubscriptions.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2014-2019 Groupon, Inc
+ * Copyright 2014-2019 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
+ * 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 org.killbill.billing.beatrix.integration;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.joda.time.LocalDate;
+import org.killbill.billing.account.api.Account;
+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.PlanPhaseSpecifier;
+import org.killbill.billing.catalog.api.ProductCategory;
+import org.killbill.billing.entitlement.api.DefaultEntitlement;
+import org.killbill.billing.entitlement.api.DefaultEntitlementSpecifier;
+import org.killbill.billing.invoice.api.InvoiceItemType;
+import org.killbill.billing.payment.api.PluginProperty;
+import org.killbill.billing.platform.api.KillbillConfigSource;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+import static org.testng.Assert.assertNotNull;
+
+public class TestCatalogWithEffectiveDateForExistingSubscriptions extends TestIntegrationBase {
+
+    @Override
+    protected KillbillConfigSource getConfigSource(final Map<String, String> extraProperties) {
+        final Map<String, String> allExtraProperties = new HashMap<String, String>(extraProperties);
+        allExtraProperties.put("org.killbill.catalog.uri", "catalogs/testCatalogWithEffectiveDateForExistingSubscriptions");
+        return super.getConfigSource(null, allExtraProperties);
+    }
+
+    @Test(groups = "slow")
+    public void testRecurringPlan() throws Exception {
+
+        final LocalDate today = new LocalDate(2018, 1, 1);
+        clock.setDay(today);
+
+        final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(1));
+
+        final DefaultEntitlement bpEntitlement =
+                createBaseEntitlementAndCheckForCompletion(account.getId(), "externalKey1", "PlumberInsurance",
+                                                           ProductCategory.BASE, BillingPeriod.MONTHLY,
+                                                           NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
+
+        assertNotNull(bpEntitlement);
+        invoiceChecker.checkInvoice(account.getId(), 1, callContext,
+                                    new ExpectedInvoiceItemCheck(new LocalDate(2018, 1, 1), new LocalDate(2018, 2, 1), InvoiceItemType.RECURRING, new BigDecimal("49.95")));
+
+        // Catalog v2 with price increase is on 2018-04-01 but because we have an effectiveDateForExistingSubscriptions set to 2018-05-01
+        // we don't see any change until 5-1
+        //
+        // 2018-2-1
+        busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+        clock.addMonths(1);
+        assertListenerStatus();
+        invoiceChecker.checkInvoice(account.getId(), 2, callContext,
+                                    new ExpectedInvoiceItemCheck(new LocalDate(2018, 2, 1), new LocalDate(2018, 3, 1), InvoiceItemType.RECURRING, new BigDecimal("49.95")));
+
+        busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+        // 2018-3-1
+        clock.addMonths(1);
+        assertListenerStatus();
+        invoiceChecker.checkInvoice(account.getId(), 3, callContext,
+                                    new ExpectedInvoiceItemCheck(new LocalDate(2018, 3, 1), new LocalDate(2018, 4, 1), InvoiceItemType.RECURRING, new BigDecimal("49.95")));
+
+        busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+        // 2018-4-1
+        clock.addMonths(1);
+        assertListenerStatus();
+        invoiceChecker.checkInvoice(account.getId(), 4, callContext,
+                                    new ExpectedInvoiceItemCheck(new LocalDate(2018, 4, 1), new LocalDate(2018, 5, 1), InvoiceItemType.RECURRING, new BigDecimal("49.95")));
+
+
+        // effectiveDateForExistingSubscriptions set to 2018-05-01 should kick-in and we should see the price increase
+        busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+        // 2018-5-1
+        clock.addMonths(1);
+        assertListenerStatus();
+        invoiceChecker.checkInvoice(account.getId(), 5, callContext,
+                                    new ExpectedInvoiceItemCheck(new LocalDate(2018, 5, 1), new LocalDate(2018, 6, 1), InvoiceItemType.RECURRING, new BigDecimal("59.95")));
+
+
+        // One more month to make sure
+        busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+        // 2018-6-1
+        clock.addMonths(1);
+        assertListenerStatus();
+        invoiceChecker.checkInvoice(account.getId(), 6, callContext,
+                                    new ExpectedInvoiceItemCheck(new LocalDate(2018, 6, 1), new LocalDate(2018, 7, 1), InvoiceItemType.RECURRING, new BigDecimal("59.95")));
+
+
+    }
+
+    @Test(groups = "slow")
+    public void testUsagePlan() throws Exception {
+
+        final LocalDate today = new LocalDate(2018, 1, 1);
+        clock.setDay(today);
+
+        final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(1));
+
+        final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("water-monthly");
+        busHandler.pushExpectedEvents(NextEvent.CREATE, NextEvent.BLOCK, NextEvent.NULL_INVOICE);
+        final UUID entitlementId = entitlementApi.createBaseEntitlement(account.getId(), new DefaultEntitlementSpecifier(spec), null, null, null, false, true, ImmutableList.<PluginProperty>of(), callContext);
+        assertListenerStatus();
+    }
+
+}
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithCatalogPlugin.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithCatalogPlugin.java
index f8cf109..14f7fd9 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithCatalogPlugin.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithCatalogPlugin.java
@@ -222,6 +222,7 @@ public class TestWithCatalogPlugin extends TestIntegrationBase {
             return new TestModelVersionedPluginCatalog(versionedCatalog.getCatalogName(), toStandalonePluginCatalogs(versionedCatalog.getVersions()));
         }
 
+        // This actually pulls catalog resources from `catalog` module and not the one from beatrix/src/test/resources//catalogs
         public void addCatalogVersion(final String catalogResource) throws Exception {
 
             final StandaloneCatalog inputCatalogVersion = XMLLoader.getObjectFromString(Resources.getResource(catalogResource).toExternalForm(), StandaloneCatalog.class);
diff --git a/beatrix/src/test/resources/catalogs/testCatalogRetireElements/WeaponsHireSmall-v1.xml b/beatrix/src/test/resources/catalogs/testCatalogRetireElements/WeaponsHireSmall-v1.xml
index 9cd2a82..e79acf8 100644
--- a/beatrix/src/test/resources/catalogs/testCatalogRetireElements/WeaponsHireSmall-v1.xml
+++ b/beatrix/src/test/resources/catalogs/testCatalogRetireElements/WeaponsHireSmall-v1.xml
@@ -109,7 +109,6 @@
 
     <plans>
         <plan name="pistol-monthly">
-            <effectiveDateForExistingSubscriptions>2011-03-14T00:00:00+00:00</effectiveDateForExistingSubscriptions>
             <product>Pistol</product>
             <initialPhases>
                 <phase type="TRIAL">
diff --git a/beatrix/src/test/resources/catalogs/testCatalogWithEffectiveDateForExistingSubscriptions/WaterUtility-v1.xml b/beatrix/src/test/resources/catalogs/testCatalogWithEffectiveDateForExistingSubscriptions/WaterUtility-v1.xml
new file mode 100644
index 0000000..cea38e8
--- /dev/null
+++ b/beatrix/src/test/resources/catalogs/testCatalogWithEffectiveDateForExistingSubscriptions/WaterUtility-v1.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+  ~ Copyright 2014 The Billing Project, 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.
+  -->
+
+<catalog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="CatalogSchema.xsd ">
+
+    <effectiveDate>2018-01-01T00:00:00+00:00</effectiveDate>
+    <catalogName>MyCatalog</catalogName>
+
+    <recurringBillingMode>IN_ADVANCE</recurringBillingMode>
+
+    <currencies>
+        <currency>USD</currency>
+    </currencies>
+
+    <units>
+        <unit name="liter"/>
+    </units>
+
+    <products>
+        <product name="PlumberInsurance">
+            <category>BASE</category>
+        </product>
+        <product name="Water">
+            <category>BASE</category>
+        </product>
+    </products>
+
+    <rules>
+        <changePolicy>
+            <changePolicyCase>
+                <policy>IMMEDIATE</policy>
+            </changePolicyCase>
+        </changePolicy>
+        <cancelPolicy>
+            <cancelPolicyCase>
+                <policy>IMMEDIATE</policy>
+            </cancelPolicyCase>
+        </cancelPolicy>
+    </rules>
+
+    <plans>
+        <plan name="plumber-insurance-monthly-no-trial">
+            <product>PlumberInsurance</product>
+            <initialPhases>
+            </initialPhases>
+            <finalPhase type="EVERGREEN">
+                <duration>
+                    <unit>UNLIMITED</unit>
+                </duration>
+                <recurring>
+                    <billingPeriod>MONTHLY</billingPeriod>
+                    <recurringPrice>
+                        <price>
+                            <currency>GBP</currency>
+                            <value>49.95</value>
+                        </price>
+                        <price>
+                            <currency>EUR</currency>
+                            <value>49.95</value>
+                        </price>
+                        <price>
+                            <currency>USD</currency>
+                            <value>49.95</value>
+                        </price>
+                    </recurringPrice>
+                </recurring>
+            </finalPhase>
+        </plan>
+
+
+        <!-- pure usage plan   -->
+        <plan name="water-monthly">
+            <product>Water</product>
+            <finalPhase type="EVERGREEN">
+                <duration>
+                    <unit>UNLIMITED</unit>
+                </duration>
+                <usages>
+                    <usage name="water-monthly-usage" billingMode="IN_ARREAR" usageType="CONSUMABLE" tierBlockPolicy="ALL_TIERS">
+                        <billingPeriod>MONTHLY</billingPeriod>
+                        <tiers>
+                            <tier>
+                                <blocks>
+                                    <tieredBlock>
+                                        <unit>liter</unit>
+                                        <size>1</size>
+                                        <prices>
+                                            <price>
+                                                <currency>USD</currency>
+                                                <value>1.50</value>
+                                            </price>
+                                        </prices>
+                                        <max>1000</max>
+                                    </tieredBlock>
+                                </blocks>
+                            </tier>
+                            <tier>
+                                <blocks>
+                                    <tieredBlock>
+                                        <unit>liter</unit>
+                                        <size>1</size>
+                                        <prices>
+                                            <price>
+                                                <currency>USD</currency>
+                                                <value>2.00</value>
+                                            </price>
+                                        </prices>
+                                        <max>-1</max>
+                                    </tieredBlock>
+                                </blocks>
+                            </tier>
+                        </tiers>
+                    </usage>
+                </usages>
+            </finalPhase>
+        </plan>
+    </plans>
+    <priceLists>
+        <defaultPriceList name="DEFAULT">
+            <plans>
+                <plan>plumber-insurance-monthly-no-trial</plan>
+                <plan>water-monthly</plan>
+            </plans>
+        </defaultPriceList>
+    </priceLists>
+</catalog>
diff --git a/beatrix/src/test/resources/catalogs/testCatalogWithEffectiveDateForExistingSubscriptions/WaterUtility-v2.xml b/beatrix/src/test/resources/catalogs/testCatalogWithEffectiveDateForExistingSubscriptions/WaterUtility-v2.xml
new file mode 100644
index 0000000..c6b7481
--- /dev/null
+++ b/beatrix/src/test/resources/catalogs/testCatalogWithEffectiveDateForExistingSubscriptions/WaterUtility-v2.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+  ~ Copyright 2014 The Billing Project, 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.
+  -->
+
+<!--
+  Price increase for both plans and effectiveDateForExistingSubscriptions set to 1 month after catalog effective date
+  -->
+<catalog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="CatalogSchema.xsd ">
+
+    <effectiveDate>2018-04-01T00:00:00+00:00</effectiveDate>
+    <catalogName>MyCatalog</catalogName>
+
+    <recurringBillingMode>IN_ADVANCE</recurringBillingMode>
+
+    <currencies>
+        <currency>USD</currency>
+    </currencies>
+
+    <units>
+        <unit name="liter"/>
+    </units>
+
+    <products>
+        <product name="PlumberInsurance">
+            <category>BASE</category>
+        </product>
+        <product name="Water">
+            <category>BASE</category>
+        </product>
+    </products>
+
+    <rules>
+        <changePolicy>
+            <changePolicyCase>
+                <policy>IMMEDIATE</policy>
+            </changePolicyCase>
+        </changePolicy>
+        <cancelPolicy>
+            <cancelPolicyCase>
+                <policy>IMMEDIATE</policy>
+            </cancelPolicyCase>
+        </cancelPolicy>
+    </rules>
+
+    <plans>
+        <plan name="plumber-insurance-monthly-no-trial">
+            <effectiveDateForExistingSubscriptions>2018-05-01T00:00:00+00:00</effectiveDateForExistingSubscriptions>
+            <product>PlumberInsurance</product>
+            <initialPhases>
+            </initialPhases>
+            <finalPhase type="EVERGREEN">
+                <duration>
+                    <unit>UNLIMITED</unit>
+                </duration>
+                <recurring>
+                    <billingPeriod>MONTHLY</billingPeriod>
+                    <recurringPrice>
+                        <price>
+                            <currency>GBP</currency>
+                            <value>59.95</value>
+                        </price>
+                        <price>
+                            <currency>EUR</currency>
+                            <value>59.95</value>
+                        </price>
+                        <price>
+                            <currency>USD</currency>
+                            <value>59.95</value>
+                        </price>
+                    </recurringPrice>
+                </recurring>
+            </finalPhase>
+        </plan>
+
+
+        <!-- pure usage plan   -->
+        <plan name="water-monthly">
+            <effectiveDateForExistingSubscriptions>2018-05-01T00:00:00+00:00</effectiveDateForExistingSubscriptions>
+            <product>Water</product>
+            <finalPhase type="EVERGREEN">
+                <duration>
+                    <unit>UNLIMITED</unit>
+                </duration>
+                <usages>
+                    <usage name="water-monthly-usage" billingMode="IN_ARREAR" usageType="CONSUMABLE" tierBlockPolicy="ALL_TIERS">
+                        <billingPeriod>MONTHLY</billingPeriod>
+                        <tiers>
+                            <tier>
+                                <blocks>
+                                    <tieredBlock>
+                                        <unit>liter</unit>
+                                        <size>1</size>
+                                        <prices>
+                                            <price>
+                                                <currency>USD</currency>
+                                                <value>2.50</value>
+                                            </price>
+                                        </prices>
+                                        <max>1000</max>
+                                    </tieredBlock>
+                                </blocks>
+                            </tier>
+                            <tier>
+                                <blocks>
+                                    <tieredBlock>
+                                        <unit>liter</unit>
+                                        <size>1</size>
+                                        <prices>
+                                            <price>
+                                                <currency>USD</currency>
+                                                <value>3.00</value>
+                                            </price>
+                                        </prices>
+                                        <max>-1</max>
+                                    </tieredBlock>
+                                </blocks>
+                            </tier>
+                        </tiers>
+                    </usage>
+                </usages>
+            </finalPhase>
+        </plan>
+    </plans>
+    <priceLists>
+        <defaultPriceList name="DEFAULT">
+            <plans>
+                <plan>plumber-insurance-monthly-no-trial</plan>
+                <plan>water-monthly</plan>
+            </plans>
+        </defaultPriceList>
+    </priceLists>
+</catalog>
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultVersionedCatalog.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultVersionedCatalog.java
index f6badd5..4d76881 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultVersionedCatalog.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultVersionedCatalog.java
@@ -156,7 +156,7 @@ public class DefaultVersionedCatalog extends ValidatingConfig<DefaultVersionedCa
             } else { // It's an existing subscription
                 if (plan.getEffectiveDateForExistingSubscriptions() != null) { // If it is null, any change to this catalog does not apply to existing subscriptions
                     final DateTime existingSubscriptionDate = CatalogDateHelper.toUTCDateTime(plan.getEffectiveDateForExistingSubscriptions());
-                    if (requestedDate.isAfter(existingSubscriptionDate)) { // This plan is now applicable to existing subs
+                    if (requestedDate.compareTo(existingSubscriptionDate) >= 0) { // This plan is now applicable to existing subs
                         return new CatalogPlanEntry(c, plan);
                     }
                 } else if (candidateInSubsequentCatalog == null) {
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/generator/FixedAndRecurringInvoiceItemGenerator.java b/invoice/src/main/java/org/killbill/billing/invoice/generator/FixedAndRecurringInvoiceItemGenerator.java
index 24ad2ee..90223d7 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/generator/FixedAndRecurringInvoiceItemGenerator.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/generator/FixedAndRecurringInvoiceItemGenerator.java
@@ -231,7 +231,8 @@ public class FixedAndRecurringInvoiceItemGenerator extends InvoiceItemGenerator 
                         if (maxEndDate != null && maxEndDate.compareTo(itemDatum.getEndDate()) < 0) {
                             break;
                         }
-                        final BigDecimal rate = thisEvent.getRecurringPrice();
+
+                        final BigDecimal rate = thisEvent.getRecurringPrice(internalCallContext.toUTCDateTime(itemDatum.getStartDate()));
                         if (rate != null) {
                             final BigDecimal amount = KillBillMoney.of(itemDatum.getNumberOfCycles().multiply(rate), currency);
                             final RecurringInvoiceItem recurringItem = new RecurringInvoiceItem(invoiceId,
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceHelper.java b/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceHelper.java
index d8ad91e..eeba00d 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceHelper.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceHelper.java
@@ -409,7 +409,7 @@ public class TestInvoiceHelper {
             }
 
             @Override
-            public BigDecimal getRecurringPrice() {
+            public BigDecimal getRecurringPrice(DateTime requestedDate) {
                 return recurringPrice;
             }
 
@@ -419,6 +419,11 @@ public class TestInvoiceHelper {
             }
 
             @Override
+            public DateTime getLastChangePlanDate() {
+                return effectiveDate;
+            }
+
+            @Override
             public SubscriptionBaseTransitionType getTransitionType() {
                 return type;
             }
diff --git a/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/BlockingCalculator.java b/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/BlockingCalculator.java
index 4f130dc..7ab83c6 100644
--- a/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/BlockingCalculator.java
+++ b/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/BlockingCalculator.java
@@ -257,14 +257,15 @@ public class BlockingCalculator {
                                        plan,
                                        planPhase,
                                        fixedPrice,
-                                       recurringPrice,
                                        currency,
                                        billingPeriod,
+                                       previousEvent.getLastChangePlanDate(),
                                        billCycleDay,
                                        description,
                                        totalOrdering,
                                        type,
-                                       true);
+                                       true,
+                                       catalog);
     }
 
     protected BillingEvent createNewReenableEvent(final DateTime odEventTime, final BillingEvent previousEvent, final Catalog catalog, final InternalTenantContext context) throws CatalogApiException {
@@ -273,7 +274,6 @@ public class BlockingCalculator {
         final DateTime effectiveDate = odEventTime;
         final PlanPhase planPhase = previousEvent.getPlanPhase();
         final BigDecimal fixedPrice = previousEvent.getFixedPrice();
-        final BigDecimal recurringPrice = previousEvent.getRecurringPrice();
         final Plan plan = previousEvent.getPlan();
         final Currency currency = previousEvent.getCurrency();
         final String description = "";
@@ -287,14 +287,15 @@ public class BlockingCalculator {
                                        plan,
                                        planPhase,
                                        fixedPrice,
-                                       recurringPrice,
                                        currency,
                                        billingPeriod,
+                                       previousEvent.getLastChangePlanDate(),
                                        billCycleDay,
                                        description,
                                        totalOrdering,
                                        type,
-                                       false);
+                                       false,
+                                       catalog);
     }
 
     // In ascending order
diff --git a/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultBillingEvent.java b/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultBillingEvent.java
index 31f7851..51bb4d8 100644
--- a/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultBillingEvent.java
+++ b/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultBillingEvent.java
@@ -54,17 +54,16 @@ public class DefaultBillingEvent implements BillingEvent {
     private final BillingPeriod billingPeriod;
 
     private final BigDecimal fixedPrice;
-    private final BigDecimal recurringPrice;
     private final Currency currency;
     private final String description;
     private final SubscriptionBaseTransitionType type;
     private final Long totalOrdering;
 
-    private final List<Usage> usages;
-
     private final boolean isCancelledOrBlocked;
 
     private final DateTime catalogEffectiveDate;
+    private final Catalog catalog;
+    private final DateTime lastChangePlanDate;
 
     public DefaultBillingEvent(final SubscriptionBillingEvent inputEvent,
                                final SubscriptionBase subscription,
@@ -77,10 +76,12 @@ public class DefaultBillingEvent implements BillingEvent {
 
         this.isCancelledOrBlocked = inputEvent.getType() == SubscriptionBaseTransitionType.CANCEL;
 
+        this.lastChangePlanDate = inputEvent.getLastChangePlanDate();
         this.type = inputEvent.getType();
-        this.plan = catalog.findPlan(inputEvent.getPlanName(), inputEvent.getEffectiveDate(), inputEvent.getLastChangePlanDate());
+        this.plan = catalog.findPlan(inputEvent.getPlanName(), inputEvent.getEffectiveDate(), lastChangePlanDate);
         this.planPhase = this.plan.findPhase(inputEvent.getPlanPhaseName());
 
+        this.catalog = catalog;
         this.catalogEffectiveDate = new DateTime(plan.getCatalog().getEffectiveDate());
 
         this.currency = currency;
@@ -90,10 +91,10 @@ public class DefaultBillingEvent implements BillingEvent {
         this.effectiveDate = inputEvent.getEffectiveDate();
         this.totalOrdering = inputEvent.getTotalOrdering();
 
-        this.billingPeriod = computeRecurringBillingPeriod();
-        this.fixedPrice = computeFixedPrice();
-        this.recurringPrice = computeRecurringPrice();
-        this.usages = computeUsages();
+        // Those 2, billingPeriod and fixedPrice can be computed once and for all as they don't move for all invoicing period
+        // related to this billing event.
+        this.billingPeriod = computeRecurringBillingPeriod(planPhase);
+        this.fixedPrice = computeFixedPrice(isCancelledOrBlocked, planPhase, currency, type);
     }
 
     public DefaultBillingEvent(final UUID subscriptionId,
@@ -102,17 +103,23 @@ public class DefaultBillingEvent implements BillingEvent {
                                final Plan plan,
                                final PlanPhase planPhase,
                                final BigDecimal fixedPrice,
-                               final BigDecimal recurringPrice,
                                final Currency currency,
                                final BillingPeriod billingPeriod,
+                               final DateTime lastChangePlanDate,
                                final int billCycleDayLocal,
                                final String description,
                                final long totalOrdering,
                                final SubscriptionBaseTransitionType type,
-                               final boolean isDisableEvent) throws CatalogApiException {
+                               final boolean isDisableEvent,
+                               final Catalog catalog) throws CatalogApiException {
         this.subscriptionId = subscriptionId;
         this.bundleId = bundleId;
+
+        this.catalog = catalog;
+        this.catalogEffectiveDate = new DateTime(plan.getCatalog().getEffectiveDate());
+
         this.effectiveDate = effectiveDate;
+        this.lastChangePlanDate = lastChangePlanDate;
 
         this.isCancelledOrBlocked = isDisableEvent;
 
@@ -120,50 +127,13 @@ public class DefaultBillingEvent implements BillingEvent {
         this.planPhase = planPhase;
         this.billingPeriod = billingPeriod;
         this.fixedPrice = fixedPrice;
-        this.recurringPrice = recurringPrice;
         this.currency = currency;
         this.billCycleDayLocal = billCycleDayLocal;
         this.description = description;
         this.type = type;
         this.totalOrdering = totalOrdering;
-        this.usages = computeUsages();
-        this.catalogEffectiveDate = new DateTime(plan.getCatalog().getEffectiveDate());
         this.billingAlignment = null;
-    }
 
-
-
-    private BigDecimal computeFixedPrice() throws CatalogApiException {
-        if (isCancelledOrBlocked ||
-            type == SubscriptionBaseTransitionType.BCD_CHANGE /* We don't want to bill twice for the same fixed price */) {
-            return null;
-        }
-        return (planPhase.getFixed() != null && planPhase.getFixed().getPrice() != null) ? planPhase.getFixed().getPrice().getPrice(currency) : null;
-    }
-
-    private BigDecimal computeRecurringPrice() throws CatalogApiException {
-        if (isCancelledOrBlocked) {
-            return null;
-        }
-        return (planPhase.getRecurring() != null && planPhase.getRecurring().getRecurringPrice() != null) ? planPhase.getRecurring().getRecurringPrice().getPrice(currency) : null;
-    }
-
-    private BillingPeriod computeRecurringBillingPeriod() {
-        return planPhase.getRecurring() != null ? planPhase.getRecurring().getBillingPeriod() : BillingPeriod.NO_BILLING_PERIOD;
-    }
-
-    private List<Usage> computeUsages() {
-        List<Usage> result = ImmutableList.<Usage>of();
-        if (isCancelledOrBlocked) {
-            return result;
-        }
-        if (planPhase.getUsages().length > 0) {
-            result = Lists.newArrayList();
-            for (Usage usage : planPhase.getUsages()) {
-                result.add(usage);
-            }
-        }
-        return result;
     }
 
 
@@ -264,8 +234,14 @@ public class DefaultBillingEvent implements BillingEvent {
     }
 
     @Override
-    public BigDecimal getRecurringPrice() {
-        return recurringPrice;
+    public BigDecimal getRecurringPrice(final DateTime requestedDate) throws CatalogApiException {
+        final PlanPhase effectivePlanPhase = catalog.findPhase(planPhase.getName(), requestedDate, lastChangePlanDate);
+        return computeRecurringPrice(isCancelledOrBlocked, effectivePlanPhase, currency);
+    }
+
+    @Override
+    public DateTime getLastChangePlanDate() {
+        return lastChangePlanDate;
     }
 
     @Override
@@ -283,9 +259,10 @@ public class DefaultBillingEvent implements BillingEvent {
         return totalOrdering;
     }
 
+    // TODO add final DateTime requestedDate -- see #1060
     @Override
     public List<Usage> getUsages() {
-        return usages;
+        return computeUsages(isCancelledOrBlocked, planPhase);
     }
 
     @Override
@@ -371,6 +348,41 @@ public class DefaultBillingEvent implements BillingEvent {
         return result;
     }
 
+
+    private static BigDecimal computeFixedPrice(final boolean isCancelledOrBlocked, final PlanPhase effectivePlanPhase, final Currency currency, final SubscriptionBaseTransitionType type) throws CatalogApiException {
+        if (isCancelledOrBlocked ||
+            type == SubscriptionBaseTransitionType.BCD_CHANGE /* We don't want to bill twice for the same fixed price */) {
+            return null;
+        }
+        return (effectivePlanPhase.getFixed() != null && effectivePlanPhase.getFixed().getPrice() != null) ? effectivePlanPhase.getFixed().getPrice().getPrice(currency) : null;
+    }
+
+    private static BigDecimal computeRecurringPrice(final boolean isCancelledOrBlocked, final PlanPhase effectivePlanPhase, final Currency currency) throws CatalogApiException {
+        if (isCancelledOrBlocked) {
+            return null;
+        }
+        return (effectivePlanPhase.getRecurring() != null && effectivePlanPhase.getRecurring().getRecurringPrice() != null) ? effectivePlanPhase.getRecurring().getRecurringPrice().getPrice(currency) : null;
+    }
+
+    private static BillingPeriod computeRecurringBillingPeriod(final PlanPhase effectivePlanPhase) {
+        return effectivePlanPhase.getRecurring() != null ? effectivePlanPhase.getRecurring().getBillingPeriod() : BillingPeriod.NO_BILLING_PERIOD;
+    }
+
+    private static List<Usage> computeUsages(final boolean isCancelledOrBlocked, final PlanPhase effectivePlanPhase) {
+        if (isCancelledOrBlocked) {
+            return ImmutableList.<Usage>of();
+        }
+
+        final List<Usage> result = (effectivePlanPhase.getUsages().length > 0) ?
+                             Lists.newArrayList() : ImmutableList.<Usage>of();
+        for (Usage usage : effectivePlanPhase.getUsages()) {
+            result.add(usage);
+        }
+        return result;
+    }
+
+
+
     @Override
     public DateTime getCatalogEffectiveDate() {
         // TODO Can that go ?
diff --git a/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultInternalBillingApi.java b/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultInternalBillingApi.java
index bb8f477..a1c0391 100644
--- a/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultInternalBillingApi.java
+++ b/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultInternalBillingApi.java
@@ -241,7 +241,7 @@ public class DefaultInternalBillingApi implements BillingInternalApi {
                 continue;
             }
 
-            final BigDecimal recurringPrice = event.getRecurringPrice();
+            final BigDecimal recurringPrice = event.getRecurringPrice(event.getEffectiveDate());
             final boolean hasRecurringPrice = recurringPrice != null; // Note: could be zero (BCD would still be set, by convention)
             final boolean hasUsage = event.getUsages() != null && !event.getUsages().isEmpty();
             if (!hasRecurringPrice &&
diff --git a/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestBillingApi.java b/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestBillingApi.java
index fcdecdf..6cb0306 100644
--- a/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestBillingApi.java
+++ b/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestBillingApi.java
@@ -265,9 +265,9 @@ public class TestBillingApi extends JunctionTestSuiteNoDB {
         }
 
         if (recurringPrice != null) {
-            Assert.assertEquals(recurringPrice.getPrice(Currency.USD), event.getRecurringPrice());
+            Assert.assertEquals(recurringPrice.getPrice(Currency.USD), event.getRecurringPrice(time));
         } else {
-            assertNull(event.getRecurringPrice());
+            assertNull(event.getRecurringPrice(time));
         }
 
         Assert.assertEquals(BCD, event.getBillCycleDayLocal());
diff --git a/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestBlockingCalculator.java b/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestBlockingCalculator.java
index a2331ce..5f199f1 100644
--- a/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestBlockingCalculator.java
+++ b/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestBlockingCalculator.java
@@ -34,9 +34,13 @@ import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 import org.joda.time.LocalDate;
 import org.killbill.billing.account.api.Account;
+import org.killbill.billing.callcontext.InternalCallContext;
 import org.killbill.billing.catalog.DefaultUsage;
+import org.killbill.billing.catalog.DefaultVersionedCatalog;
+import org.killbill.billing.catalog.MockCatalog;
 import org.killbill.billing.catalog.MockPlan;
 import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.Catalog;
 import org.killbill.billing.catalog.api.CatalogApiException;
 import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.catalog.api.InternationalPrice;
@@ -51,6 +55,7 @@ import org.killbill.billing.junction.DefaultBlockingState;
 import org.killbill.billing.junction.JunctionTestSuiteNoDB;
 import org.killbill.billing.subscription.api.SubscriptionBase;
 import org.killbill.billing.subscription.api.SubscriptionBaseTransitionType;
+import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
@@ -78,6 +83,8 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
     private SubscriptionBase subscription4;
     private Map<UUID, List<SubscriptionBase>> subscriptionsForAccount;
 
+    private Catalog catalog;
+
     @BeforeMethod(groups = "fast")
     public void beforeMethod() throws Exception {
         if (hasFailed()) {
@@ -115,6 +122,8 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         Mockito.when(subscription4.getId()).thenReturn(UUID.randomUUID());
 
 
+        catalog = Mockito.mock(Catalog.class);
+
 
         ((MockBlockingStateDao) blockingStateDao).clear();
     }
@@ -150,7 +159,7 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
                                                                                                                         blockingState2, Optional.<UUID>absent()),
                                                                          internalCallContext);
 
-        blockingCalculator.insertBlockingEvents(billingEvents, new HashSet<UUID>(), subscriptionsForAccount, catalogInternalApi.getFullCatalog(true, true, internalCallContext), internalCallContext);
+        blockingCalculator.insertBlockingEvents(billingEvents, new HashSet<UUID>(), subscriptionsForAccount, catalog, internalCallContext);
 
         assertEquals(billingEvents.size(), 7);
 
@@ -371,12 +380,12 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         disabledDuration.add(new DisabledDuration(now, null));
         billingEvents.add(createRealEvent(subscription1, now.minusDays(1)));
 
-        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalogInternalApi.getFullCatalog(true, true, internalCallContext),  internalCallContext);
+        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalog,  internalCallContext);
 
         assertEquals(results.size(), 1);
         assertEquals(results.first().getEffectiveDate(), now);
         assertNull(results.first().getFixedPrice());
-        assertNull(results.first().getRecurringPrice());
+        assertNull(results.first().getRecurringPrice(now));
         assertEquals(results.first().getBillingPeriod(), BillingPeriod.NO_BILLING_PERIOD);
         assertEquals(results.first().getTransitionType(), SubscriptionBaseTransitionType.START_BILLING_DISABLED);
     }
@@ -393,12 +402,12 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         billingEvents.add(createRealEvent(subscription1, now.minusDays(1)));
         billingEvents.add(createRealEvent(subscription1, now.plusDays(1)));
 
-        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalogInternalApi.getFullCatalog(true, true, internalCallContext), internalCallContext);
+        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalog, internalCallContext);
 
         assertEquals(results.size(), 1);
         assertEquals(results.first().getEffectiveDate(), now);
         assertNull(results.first().getFixedPrice());
-        assertNull(results.first().getRecurringPrice());
+        assertNull(results.first().getRecurringPrice(now));
         assertEquals(results.first().getBillingPeriod(), BillingPeriod.NO_BILLING_PERIOD);
         assertEquals(results.first().getTransitionType(), SubscriptionBaseTransitionType.START_BILLING_DISABLED);
     }
@@ -414,7 +423,7 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         disabledDuration.add(new DisabledDuration(now, null));
         billingEvents.add(createRealEvent(subscription1, now.plusDays(1)));
 
-        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalogInternalApi.getFullCatalog(true, true, internalCallContext), internalCallContext);
+        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalog, internalCallContext);
 
         assertEquals(results.size(), 0);
     }
@@ -430,7 +439,7 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         disabledDuration.add(new DisabledDuration(now, null));
         billingEvents.add(createRealEvent(subscription1, now));
 
-        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalogInternalApi.getFullCatalog(true, true, internalCallContext), internalCallContext);
+        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalog, internalCallContext);
 
         assertEquals(results.size(), 0);
     }
@@ -446,17 +455,17 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
         billingEvents.add(createRealEvent(subscription1, now.minusDays(1)));
 
-        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalogInternalApi.getFullCatalog(true, true, internalCallContext), internalCallContext);
+        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalog, internalCallContext);
 
 
         assertEquals(results.size(), 2);
         assertEquals(results.first().getEffectiveDate(), now);
         assertNull(results.first().getFixedPrice());
-        assertNull(results.first().getRecurringPrice());
+        assertNull(results.first().getRecurringPrice(now));
         assertEquals(results.first().getBillingPeriod(), BillingPeriod.NO_BILLING_PERIOD);
         assertEquals(results.first().getTransitionType(), SubscriptionBaseTransitionType.START_BILLING_DISABLED);
         assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
-        assertEquals(results.last().getRecurringPrice(), billingEvents.first().getRecurringPrice());
+        assertEquals(results.last().getRecurringPrice(now), billingEvents.first().getRecurringPrice(now));
         assertEquals(results.last().getTransitionType(), SubscriptionBaseTransitionType.END_BILLING_DISABLED);
     }
 
@@ -472,16 +481,16 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         billingEvents.add(createRealEvent(subscription1, now.minusDays(1)));
         billingEvents.add(createRealEvent(subscription1, now.plusDays(1)));
 
-        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalogInternalApi.getFullCatalog(true, true, internalCallContext), internalCallContext);
+        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalog, internalCallContext);
 
         assertEquals(results.size(), 2);
         assertEquals(results.first().getEffectiveDate(), now);
         assertNull(results.first().getFixedPrice());
-        assertNull(results.first().getRecurringPrice());
+        assertNull(results.first().getRecurringPrice(now));
         assertEquals(results.first().getBillingPeriod(), BillingPeriod.NO_BILLING_PERIOD);
         assertEquals(results.first().getTransitionType(), SubscriptionBaseTransitionType.START_BILLING_DISABLED);
         assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
-        assertEquals(results.last().getRecurringPrice(), billingEvents.first().getRecurringPrice());
+        assertEquals(results.last().getRecurringPrice(now), billingEvents.first().getRecurringPrice(now));
         assertEquals(results.last().getTransitionType(), SubscriptionBaseTransitionType.END_BILLING_DISABLED);
     }
 
@@ -498,16 +507,16 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         billingEvents.add(createRealEvent(subscription1, now.plusDays(1)));
         billingEvents.add(createRealEvent(subscription1, now.plusDays(3)));
 
-        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalogInternalApi.getFullCatalog(true, true, internalCallContext), internalCallContext);
+        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalog, internalCallContext);
 
         assertEquals(results.size(), 2);
         assertEquals(results.first().getEffectiveDate(), now);
         assertNull(results.first().getFixedPrice());
-        assertNull(results.first().getRecurringPrice());
+        assertNull(results.first().getRecurringPrice(now));
         assertEquals(results.first().getBillingPeriod(), BillingPeriod.NO_BILLING_PERIOD);
         assertEquals(results.first().getTransitionType(), SubscriptionBaseTransitionType.START_BILLING_DISABLED);
         assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
-        assertEquals(results.last().getRecurringPrice(), billingEvents.first().getRecurringPrice());
+        assertEquals(results.last().getRecurringPrice(now), billingEvents.first().getRecurringPrice(now));
         assertEquals(results.last().getTransitionType(), SubscriptionBaseTransitionType.END_BILLING_DISABLED);
     }
 
@@ -522,11 +531,11 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
         billingEvents.add(createRealEvent(subscription1, now.plusDays(1)));
 
-        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalogInternalApi.getFullCatalog(true, true, internalCallContext), internalCallContext);
+        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalog, internalCallContext);
 
         assertEquals(results.size(), 1);
         assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
-        assertEquals(results.last().getRecurringPrice(), billingEvents.first().getRecurringPrice());
+        assertEquals(results.last().getRecurringPrice(now), billingEvents.first().getRecurringPrice(now));
         assertEquals(results.last().getTransitionType(), SubscriptionBaseTransitionType.END_BILLING_DISABLED);
     }
 
@@ -541,11 +550,11 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
         billingEvents.add(createRealEvent(subscription1, now.plusDays(1)));
 
-        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalogInternalApi.getFullCatalog(true, true, internalCallContext), internalCallContext);
+        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalog, internalCallContext);
 
         assertEquals(results.size(), 1);
         assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
-        assertEquals(results.last().getRecurringPrice(), billingEvents.first().getRecurringPrice());
+        assertEquals(results.last().getRecurringPrice(now), billingEvents.first().getRecurringPrice(now));
         assertEquals(results.last().getTransitionType(), SubscriptionBaseTransitionType.END_BILLING_DISABLED);
     }
 
@@ -560,7 +569,7 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
         billingEvents.add(createRealEvent(subscription1, now.plusDays(3)));
 
-        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalogInternalApi.getFullCatalog(true, true, internalCallContext), internalCallContext);
+        final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, catalog, internalCallContext);
 
         assertEquals(results.size(), 0);
     }
@@ -607,15 +616,16 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
     public void testCreateNewDisableEvent() throws CatalogApiException {
         final DateTime now = clock.getUTCNow();
 
+
         final BillingEvent event = createRealEvent(subscription1, now);
 
-        final BillingEvent result = blockingCalculator.createNewDisableEvent(now, event, null);
+        final BillingEvent result = blockingCalculator.createNewDisableEvent(now, event, catalog);
         assertEquals(result.getBillCycleDayLocal(), event.getBillCycleDayLocal());
         assertEquals(result.getEffectiveDate(), now);
         assertEquals(result.getPlanPhase(), event.getPlanPhase());
         assertEquals(result.getPlan(), event.getPlan());
         assertNull(result.getFixedPrice());
-        assertNull(result.getRecurringPrice());
+        assertNull(result.getRecurringPrice(now));
         assertEquals(result.getCurrency(), event.getCurrency());
         assertEquals(result.getDescription(), "");
         assertEquals(result.getBillingPeriod(), BillingPeriod.NO_BILLING_PERIOD);
@@ -629,13 +639,13 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         final DateTime now = clock.getUTCNow();
         final BillingEvent event = createRealEvent(subscription1, now);
 
-        final BillingEvent result = blockingCalculator.createNewReenableEvent(now, event, null, internalCallContext);
+        final BillingEvent result = blockingCalculator.createNewReenableEvent(now, event, catalog, internalCallContext);
         assertEquals(result.getBillCycleDayLocal(), event.getBillCycleDayLocal());
         assertEquals(result.getEffectiveDate(), now);
         assertEquals(result.getPlanPhase(), event.getPlanPhase());
         assertEquals(result.getPlan(), event.getPlan());
         assertEquals(result.getFixedPrice(), event.getFixedPrice());
-        assertEquals(result.getRecurringPrice(), event.getRecurringPrice());
+        assertEquals(result.getRecurringPrice(now), event.getRecurringPrice(now));
         assertEquals(result.getCurrency(), event.getCurrency());
         assertEquals(result.getDescription(), "");
         assertEquals(result.getBillingPeriod(), event.getBillingPeriod());
@@ -799,7 +809,7 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
                                                                          internalCallContext);
 
 
-        blockingCalculator.insertBlockingEvents(billingEvents, new HashSet<UUID>(), subscriptionsForAccount, catalogInternalApi.getFullCatalog(true, true, internalCallContext), internalCallContext);
+        blockingCalculator.insertBlockingEvents(billingEvents, new HashSet<UUID>(), subscriptionsForAccount, catalog, internalCallContext);
 
         assertEquals(billingEvents.size(), 5);
         final List<BillingEvent> events = new ArrayList<BillingEvent>(billingEvents);
@@ -846,6 +856,8 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
             Mockito.when(planPhase.getRecurring()).thenReturn(recurring);
             Mockito.when(planPhase.getUsages()).thenReturn(new DefaultUsage[0]);
 
+            Mockito.when(catalog.findPhase(Mockito.<String>any(), Mockito.<DateTime>any(), Mockito.<DateTime>any())).thenReturn(planPhase);
+
             final BigDecimal fixedPrice = BigDecimal.TEN;
 
             return new DefaultBillingEvent(subscription.getId(),
@@ -854,14 +866,15 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
                                            plan,
                                            planPhase,
                                            fixedPrice,
-                                           BigDecimal.TEN,
                                            currency,
                                            billingPeriod,
+                                           effectiveDate,
                                            billCycleDay,
                                            description,
                                            totalOrdering,
                                            type,
-                                           false);
+                                           false,
+                                           catalog);
 
         } catch (final CatalogApiException e) {
             Assert.fail("", e);
diff --git a/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestDefaultBillingEvent.java b/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestDefaultBillingEvent.java
index 6b30758..10e178f 100644
--- a/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestDefaultBillingEvent.java
+++ b/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestDefaultBillingEvent.java
@@ -185,9 +185,9 @@ public class TestDefaultBillingEvent extends JunctionTestSuiteNoDB {
         final PlanPhase shotgunMonthly = createMockMonthlyPlanPhase(null, BigDecimal.ZERO, PhaseType.TRIAL);
 
         return new DefaultBillingEvent(sub.getId(), sub.getBundleId(), effectiveDate,
-                                       shotgun, shotgunMonthly, BigDecimal.ZERO, BigDecimal.ZERO,
-                                       Currency.USD, BillingPeriod.NO_BILLING_PERIOD, billCycleDay,
-                                       "Test Event 1", totalOrdering, type, false);
+                                       shotgun, shotgunMonthly, BigDecimal.ZERO,
+                                       Currency.USD, BillingPeriod.NO_BILLING_PERIOD, effectiveDate, billCycleDay,
+                                       "Test Event 1", totalOrdering, type, false, null);
     }
 
     private MockPlanPhase createMockMonthlyPlanPhase(@Nullable final BigDecimal recurringRate,