killbill-aplcache

catalog: Add recurringBillingMode on a per Plan level Keep

9/8/2017 7:11:27 PM

Changes

Details

diff --git a/api/src/main/java/org/killbill/billing/junction/BillingEventSet.java b/api/src/main/java/org/killbill/billing/junction/BillingEventSet.java
index 5ecadbf..3f760c2 100644
--- a/api/src/main/java/org/killbill/billing/junction/BillingEventSet.java
+++ b/api/src/main/java/org/killbill/billing/junction/BillingEventSet.java
@@ -34,8 +34,6 @@ public interface BillingEventSet extends SortedSet<BillingEvent> {
 
     public boolean isAccountAutoInvoiceReuseDraft();
 
-    public BillingMode getRecurringBillingMode();
-
     public List<UUID> getSubscriptionIdsWithAutoInvoiceOff();
 
     public Map<String, Usage> getUsages();
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 a67a191..134819d 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
@@ -207,7 +207,7 @@ public class TestWithCatalogPlugin extends TestIntegrationBase {
         public VersionedPluginCatalog getVersionedPluginCatalog(final Iterable<PluginProperty> properties, final TenantContext tenantContext) {
             nbVersionedPluginCatalogApiCalls++;
             Assert.assertNotNull(versionedCatalog, "test did not initialize plugin catalog");
-            return new TestModelVersionedPluginCatalog(versionedCatalog.getCatalogName(), versionedCatalog.getRecurringBillingMode(), toStandalonePluginCatalogs(versionedCatalog.getVersions()));
+            return new TestModelVersionedPluginCatalog(versionedCatalog.getCatalogName(), toStandalonePluginCatalogs(versionedCatalog.getVersions()));
         }
 
         public void addCatalogVersion(final String catalogResource) throws Exception {
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/api/user/DefaultCatalogUserApi.java b/catalog/src/main/java/org/killbill/billing/catalog/api/user/DefaultCatalogUserApi.java
index 7a82864..0373e89 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/api/user/DefaultCatalogUserApi.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/api/user/DefaultCatalogUserApi.java
@@ -175,7 +175,7 @@ public class DefaultCatalogUserApi implements CatalogUserApi {
             final StandaloneCatalog currentCatalog = getCurrentStandaloneCatalogForTenant(internalTenantContext);
             final CatalogUpdater catalogUpdater = (currentCatalog != null) ?
                                                   new CatalogUpdater(currentCatalog) :
-                                                  new CatalogUpdater(BillingMode.IN_ADVANCE, getSafeFirstCatalogEffectiveDate(effectiveDate), null);
+                                                  new CatalogUpdater(getSafeFirstCatalogEffectiveDate(effectiveDate), null);
 
             catalogCache.clearCatalog(internalTenantContext);
             tenantApi.updateTenantKeyValue(TenantKey.CATALOG.toString(), catalogUpdater.getCatalogXML(), callContext);
@@ -192,7 +192,7 @@ public class DefaultCatalogUserApi implements CatalogUserApi {
             final StandaloneCatalog currentCatalog = getCurrentStandaloneCatalogForTenant(internalTenantContext);
             final CatalogUpdater catalogUpdater = (currentCatalog != null) ?
                                                   new CatalogUpdater(currentCatalog) :
-                                                  new CatalogUpdater(BillingMode.IN_ADVANCE, getSafeFirstCatalogEffectiveDate(effectiveDate), descriptor.getCurrency());
+                                                  new CatalogUpdater(getSafeFirstCatalogEffectiveDate(effectiveDate), descriptor.getCurrency());
             catalogUpdater.addSimplePlanDescriptor(descriptor);
 
             catalogCache.clearCatalog(internalTenantContext);
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/CatalogUpdater.java b/catalog/src/main/java/org/killbill/billing/catalog/CatalogUpdater.java
index 154949e..6f53186 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/CatalogUpdater.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/CatalogUpdater.java
@@ -68,15 +68,17 @@ public class CatalogUpdater {
 
     public CatalogUpdater(final StandaloneCatalog standaloneCatalog) {
         this.catalog = new DefaultMutableStaticCatalog(standaloneCatalog);
+        this.catalog.setRecurringBillingMode(BillingMode.IN_ADVANCE);
+
     }
 
-    public CatalogUpdater(final BillingMode billingMode, final DateTime effectiveDate, final Currency... currencies) {
+    public CatalogUpdater(final DateTime effectiveDate, final Currency... currencies) {
 
         final DefaultPriceList defaultPriceList = new DefaultPriceList().setName(PriceListSet.DEFAULT_PRICELIST_NAME);
         final StandaloneCatalog tmp = new StandaloneCatalog()
                 .setCatalogName(DEFAULT_CATALOG_NAME)
                 .setEffectiveDate(effectiveDate.toDate())
-                .setRecurringBillingMode(billingMode)
+                .setRecurringBillingMode(BillingMode.IN_ADVANCE)
                 .setProducts(ImmutableList.<Product>of())
                 .setPlans(ImmutableList.<Plan>of())
                 .setPriceLists(new DefaultPriceListSet(defaultPriceList, new DefaultPriceList[0]))
@@ -132,6 +134,7 @@ public class CatalogUpdater {
             plan.setName(desc.getPlanId());
             plan.setPriceListName(PriceListSet.DEFAULT_PRICELIST_NAME);
             plan.setProduct(product);
+            plan.setRecurringBillingMode(catalog.getRecurringBillingMode());
 
             if (desc.getTrialLength() > 0 && desc.getTrialTimeUnit() != TimeUnit.UNLIMITED) {
                 final DefaultPlanPhase trialPhase = new DefaultPlanPhase();
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultMutableStaticCatalog.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultMutableStaticCatalog.java
index 8e83016..c6d9a6c 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultMutableStaticCatalog.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultMutableStaticCatalog.java
@@ -42,12 +42,12 @@ public class DefaultMutableStaticCatalog extends StandaloneCatalog implements Mu
 
     public DefaultMutableStaticCatalog(final StandaloneCatalog input) {
         this.setCatalogName(input.getCatalogName())
+            .setRecurringBillingMode(input.getRecurringBillingMode())
             .setEffectiveDate(input.getEffectiveDate())
             .setSupportedCurrencies(input.getCurrentSupportedCurrencies())
             .setUnits(input.getCurrentUnits())
             .setProducts(input.getCurrentProducts())
             .setPlans(input.getCurrentPlans())
-            .setRecurringBillingMode(input.getRecurringBillingMode())
             .setPlanRules(input.getPlanRules())
             .setPriceLists(input.getPriceLists());
         initialize(this, null);
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlan.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlan.java
index 5afa415..a61fa3c 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlan.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlan.java
@@ -40,6 +40,7 @@ import javax.xml.bind.annotation.XmlIDREF;
 
 import org.joda.time.DateTime;
 import org.killbill.billing.ErrorCode;
+import org.killbill.billing.catalog.api.BillingMode;
 import org.killbill.billing.catalog.api.BillingPeriod;
 import org.killbill.billing.catalog.api.CatalogApiException;
 import org.killbill.billing.catalog.api.PhaseType;
@@ -76,6 +77,10 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements 
     @XmlIDREF
     private DefaultProduct product;
 
+    // In order to support older versions where recurringBillingMode is defined at the StandaloneCatalog level, we don't require that field.
+    @XmlElement(required = false)
+    private BillingMode recurringBillingMode;
+
     @XmlElementWrapper(name = "initialPhases", required = false)
     @XmlElement(name = "phase", required = false)
     private DefaultPlanPhase[] initialPhases;
@@ -108,6 +113,7 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements 
         }
         this.finalPhase = new DefaultPlanPhase(this, in.getFinalPhase(), overrides[overrides.length - 1]);
         this.priceListName = in.getPriceListName();
+        this.recurringBillingMode = in.getRecurringBillingMode();
     }
 
     @Override
@@ -115,6 +121,10 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements 
         return effectiveDateForExistingSubscriptions;
     }
 
+    @Override
+    public BillingMode getRecurringBillingMode() {
+        return recurringBillingMode;
+    }
 
     @Override
     public DefaultPlanPhase[] getInitialPhases() {
@@ -204,6 +214,10 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements 
             p.setPlan(this);
             p.initialize(catalog, sourceURI);
         }
+        if (recurringBillingMode == null) {
+            this.recurringBillingMode = catalog.getRecurringBillingMode();
+        }
+
         this.priceListName = this.priceListName != null ? this.priceListName : findPriceListForPlan(catalog);
     }
 
@@ -217,6 +231,10 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements 
                                            catalog.getCatalogURI(), DefaultPlan.class, ""));
         }
 
+        if (recurringBillingMode == null) {
+            errors.add(new ValidationError(String.format("Invalid reccuring billingMode for plan '%s'", name), catalog.getCatalogURI(), DefaultPlan.class, ""));
+        }
+
         if (product == null) {
             errors.add(new ValidationError(String.format("Invalid product for plan '%s'", name), catalog.getCatalogURI(), DefaultPlan.class, ""));
         }
@@ -284,6 +302,11 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements 
         return this;
     }
 
+    public DefaultPlan setRecurringBillingMode(final BillingMode billingMode) {
+        this.recurringBillingMode = billingMode;
+        return this;
+    }
+
     @Override
     public DateTime dateOfFirstRecurringNonZeroCharge(final DateTime subscriptionStartDate, final PhaseType initialPhaseType) {
         DateTime result = subscriptionStartDate;
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/plugin/StandaloneCatalogMapper.java b/catalog/src/main/java/org/killbill/billing/catalog/plugin/StandaloneCatalogMapper.java
index 4d715cf..c8bf3d4 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/plugin/StandaloneCatalogMapper.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/plugin/StandaloneCatalogMapper.java
@@ -44,7 +44,6 @@ import org.killbill.billing.catalog.DefaultTieredBlock;
 import org.killbill.billing.catalog.DefaultUnit;
 import org.killbill.billing.catalog.DefaultUsage;
 import org.killbill.billing.catalog.StandaloneCatalog;
-import org.killbill.billing.catalog.api.BillingMode;
 import org.killbill.billing.catalog.api.Block;
 import org.killbill.billing.catalog.api.CurrencyValueNull;
 import org.killbill.billing.catalog.api.Duration;
@@ -91,16 +90,13 @@ import com.google.common.collect.Iterables;
 public class StandaloneCatalogMapper {
 
     private final String catalogName;
-    private final BillingMode recurringBillingMode;
-
     private Map<String, Product> tmpDefaultProducts;
     private Map<String, Plan> tmpDefaultPlans;
     private DefaultPriceListSet tmpDefaultPriceListSet;
     private Map<String, DefaultPriceList> tmpDefaultPriceListMap;
 
-    public StandaloneCatalogMapper(final String catalogName, final BillingMode recurringBillingMode) {
+    public StandaloneCatalogMapper(final String catalogName) {
         this.catalogName = catalogName;
-        this.recurringBillingMode = recurringBillingMode;
         this.tmpDefaultProducts = null;
         this.tmpDefaultPlans = null;
         this.tmpDefaultPriceListMap = new HashMap<String, DefaultPriceList>();
@@ -114,7 +110,6 @@ public class StandaloneCatalogMapper {
         result.setProducts(toDefaultProducts(pluginCatalog.getProducts()));
         result.setPlans(toDefaultPlans(pluginCatalog.getPlans()));
         result.setPriceLists(toDefaultPriceListSet(pluginCatalog.getDefaultPriceList(), pluginCatalog.getChildrenPriceList()));
-        result.setRecurringBillingMode(recurringBillingMode);
         result.setSupportedCurrencies(toArray(pluginCatalog.getCurrencies()));
         result.setUnits(toDefaultUnits(pluginCatalog.getUnits()));
         result.setPlanRules(toDefaultPlanRules(pluginCatalog.getPlanRules()));
@@ -403,6 +398,7 @@ public class StandaloneCatalogMapper {
         final DefaultPlan result = new DefaultPlan();
         result.setName(input.getName());
         result.setPrettyName(input.getPrettyName());
+        result.setRecurringBillingMode(input.getRecurringBillingMode());
         result.setEffectiveDateForExistingSubscriptions(input.getEffectiveDateForExistingSubscriptions());
         result.setFinalPhase(toDefaultPlanPhase(input.getFinalPhase()));
         result.setInitialPhases(toDefaultPlanPhases(ImmutableList.copyOf(input.getInitialPhases())));
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/plugin/VersionedCatalogMapper.java b/catalog/src/main/java/org/killbill/billing/catalog/plugin/VersionedCatalogMapper.java
index 1ee8470..eb170ce 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/plugin/VersionedCatalogMapper.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/plugin/VersionedCatalogMapper.java
@@ -59,7 +59,7 @@ public class VersionedCatalogMapper {
     }
 
     private StandaloneCatalogWithPriceOverride toStandaloneCatalogWithPriceOverride(final VersionedPluginCatalog pluginCatalog, final StandalonePluginCatalog input, final InternalTenantContext internalTenantContext) {
-        final StandaloneCatalogMapper mapper = new StandaloneCatalogMapper(pluginCatalog.getCatalogName(), pluginCatalog.getRecurringBillingMode());
+        final StandaloneCatalogMapper mapper = new StandaloneCatalogMapper(pluginCatalog.getCatalogName());
         final StandaloneCatalog catalog = mapper.toStandaloneCatalog(input, null);
         final StandaloneCatalogWithPriceOverride result = new StandaloneCatalogWithPriceOverride(catalog, priceOverride, internalTenantContext.getTenantRecordId(), internalCallContextFactory);
         return result;
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalog.java b/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalog.java
index 96869e4..db734df 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalog.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalog.java
@@ -65,7 +65,7 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
     @XmlElement(required = true)
     private String catalogName;
 
-    @XmlElement(required = true)
+    @XmlElement(required = false)
     private BillingMode recurringBillingMode;
 
     @XmlElementWrapper(name = "currencies", required = true)
@@ -114,11 +114,6 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
         return effectiveDate;
     }
 
-    @Override
-    public BillingMode getRecurringBillingMode() {
-        return recurringBillingMode;
-    }
-
     /* (non-Javadoc)
      * @see org.killbill.billing.catalog.ICatalog#getProducts()
      */
@@ -316,6 +311,9 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
         }
     }
 
+    public BillingMode getRecurringBillingMode() {
+        return recurringBillingMode;
+    }
 
     //////////////////////////////////////////////////////////////////////////////
     //
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalogWithPriceOverride.java b/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalogWithPriceOverride.java
index d7a2d9b..1d77860 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalogWithPriceOverride.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalogWithPriceOverride.java
@@ -49,7 +49,6 @@ public class StandaloneCatalogWithPriceOverride extends StandaloneCatalog implem
         // Initialize from input catalog
         setCatalogName(catalog.getCatalogName());
         setEffectiveDate(catalog.getEffectiveDate());
-        setRecurringBillingMode(catalog.getRecurringBillingMode());
         setProducts(catalog.getCurrentProducts());
         setPlans(catalog.getCurrentPlans());
         setPriceLists(catalog.getPriceLists());
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/VersionedCatalog.java b/catalog/src/main/java/org/killbill/billing/catalog/VersionedCatalog.java
index 4586e4a..73dfb28 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/VersionedCatalog.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/VersionedCatalog.java
@@ -85,9 +85,6 @@ public class VersionedCatalog extends ValidatingConfig<VersionedCatalog> impleme
     @XmlElement(required = true)
     private String catalogName;
 
-    @XmlElement(required = true)
-    private BillingMode recurringBillingMode;
-
     // Required for JAXB deserialization
     public VersionedCatalog() {
         this.clock = null;
@@ -246,9 +243,6 @@ public class VersionedCatalog extends ValidatingConfig<VersionedCatalog> impleme
         if (catalogName == null && e.getCatalogName() != null) {
             catalogName = e.getCatalogName();
         }
-        if (recurringBillingMode == null) {
-            recurringBillingMode = e.getRecurringBillingMode();
-        }
         versions.add(e);
         Collections.sort(versions, new Comparator<StandaloneCatalog>() {
             @Override
@@ -447,10 +441,6 @@ public class VersionedCatalog extends ValidatingConfig<VersionedCatalog> impleme
                 errors.add(new ValidationError(String.format("Catalog name '%s' is not consistent across versions ", c.getCatalogName()),
                                                c.getCatalogURI(), VersionedCatalog.class, ""));
             }
-            if (!c.getRecurringBillingMode().equals(recurringBillingMode)) {
-                errors.add(new ValidationError(String.format("Catalog recurringBillingMode '%s' is not consistent across versions ", c.getCatalogName()),
-                                               c.getCatalogURI(), VersionedCatalog.class, ""));
-            }
             errors.addAll(c.validate(c, errors));
         }
         return errors;
@@ -470,11 +460,6 @@ public class VersionedCatalog extends ValidatingConfig<VersionedCatalog> impleme
     }
 
     @Override
-    public BillingMode getRecurringBillingMode() {
-        return recurringBillingMode;
-    }
-
-    @Override
     public Currency[] getCurrentSupportedCurrencies() throws CatalogApiException {
         return versionForDate(clock.getUTCNow()).getCurrentSupportedCurrencies();
     }
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/io/TestXMLWriter.java b/catalog/src/test/java/org/killbill/billing/catalog/io/TestXMLWriter.java
index b431e9a..7a3c905 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/io/TestXMLWriter.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/io/TestXMLWriter.java
@@ -36,6 +36,7 @@ import org.killbill.billing.catalog.DefaultRecurring;
 import org.killbill.billing.catalog.StandaloneCatalog;
 import org.killbill.billing.catalog.StandaloneCatalogWithPriceOverride;
 import org.killbill.billing.catalog.VersionedCatalog;
+import org.killbill.billing.catalog.api.BillingMode;
 import org.killbill.billing.catalog.api.BillingPeriod;
 import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.catalog.api.MutableStaticCatalog;
@@ -111,6 +112,7 @@ public class TestXMLWriter extends CatalogTestSuiteNoDB {
         newPlan.setProduct(newProduct);
         newPlan.setInitialPhases(new DefaultPlanPhase[]{trialPhase});
         newPlan.setFinalPhase(evergreenPhase);
+        newPlan.setRecurringBillingMode(BillingMode.IN_ADVANCE);
         // TODO Ordering breaks
         mutableCatalog.addPlan(newPlan);
         newPlan.initialize((StandaloneCatalog) mutableCatalog, new URI("dummy"));
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/MockPlan.java b/catalog/src/test/java/org/killbill/billing/catalog/MockPlan.java
index 54a95ba..9fde075 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/MockPlan.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/MockPlan.java
@@ -18,6 +18,7 @@ package org.killbill.billing.catalog;
 
 import java.util.Collection;
 
+import org.killbill.billing.catalog.api.BillingMode;
 import org.killbill.billing.catalog.api.Plan;
 
 import com.google.common.collect.ImmutableList;
@@ -94,6 +95,7 @@ public class MockPlan extends DefaultPlan {
         setFinalPhase(finalPhase);
         setInitialPhases(planPhases);
         setPlansAllowedInBundle(plansAllowedInBundle);
+        setRecurringBillingMode(BillingMode.IN_ADVANCE);
 
         finalPhase.setPlan(this);
         for (final DefaultPlanPhase pp : planPhases) {
@@ -113,7 +115,7 @@ public class MockPlan extends DefaultPlan {
         setName("Test");
         setProduct(MockProduct.createBicycle());
         setFinalPhase(mockPlanPhase);
-
+        setRecurringBillingMode(BillingMode.IN_ADVANCE);
         mockPlanPhase.setPlan(this);
     }
 
@@ -122,6 +124,7 @@ public class MockPlan extends DefaultPlan {
         setProduct(new MockProduct());
         setFinalPhase(new MockPlanPhase(this));
         setInitialPhases(null);
+        setRecurringBillingMode(BillingMode.IN_ADVANCE);
         setPlansAllowedInBundle(1);
     }
 
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestCatalogPluginMapping.java b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestCatalogPluginMapping.java
index ff48895..ed37579 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestCatalogPluginMapping.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestCatalogPluginMapping.java
@@ -46,9 +46,10 @@ public class TestCatalogPluginMapping extends CatalogTestSuiteNoDB {
         final StandaloneCatalog inputCatalog = XMLLoader.getObjectFromString(Resources.getResource("SpyCarAdvanced.xml").toExternalForm(), StandaloneCatalog.class);
         final StandalonePluginCatalog pluginCatalog = buildStandalonePluginCatalog(inputCatalog);
 
-        final StandaloneCatalogMapper mapper = new StandaloneCatalogMapper(inputCatalog.getCatalogName(), inputCatalog.getRecurringBillingMode());
+        final StandaloneCatalogMapper mapper = new StandaloneCatalogMapper(inputCatalog.getCatalogName());
 
         final StandaloneCatalog output = mapper.toStandaloneCatalog(pluginCatalog, inputCatalog.getCatalogURI());
+        output.setRecurringBillingMode(inputCatalog.getRecurringBillingMode());
         Assert.assertEquals(output, inputCatalog);
 
     }
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelVersionedPluginCatalog.java b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelVersionedPluginCatalog.java
index 18de96f..660e234 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelVersionedPluginCatalog.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelVersionedPluginCatalog.java
@@ -24,15 +24,11 @@ import org.killbill.billing.catalog.plugin.api.VersionedPluginCatalog;
 public class TestModelVersionedPluginCatalog implements VersionedPluginCatalog {
     private final String catalogName;
 
-    private final BillingMode billingMode;
-
     private final Iterable<StandalonePluginCatalog> standalonePluginCatalogs;
 
     public TestModelVersionedPluginCatalog(final String catalogName,
-                                      final BillingMode billingMode,
                                       final Iterable<StandalonePluginCatalog> standalonePluginCatalogs) {
         this.catalogName = catalogName;
-        this.billingMode = billingMode;
         this.standalonePluginCatalogs = standalonePluginCatalogs;
     }
 
@@ -41,10 +37,6 @@ public class TestModelVersionedPluginCatalog implements VersionedPluginCatalog {
         return catalogName;
     }
 
-    @Override
-    public BillingMode getRecurringBillingMode() {
-        return billingMode;
-    }
 
     @Override
     public Iterable<StandalonePluginCatalog> getStandalonePluginCatalogs() {
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogUpdater.java b/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogUpdater.java
index e66e48d..3963bd1 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogUpdater.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogUpdater.java
@@ -56,7 +56,7 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
 
         final DateTime now = clock.getUTCNow();
 
-        final CatalogUpdater catalogUpdater = new CatalogUpdater(BillingMode.IN_ADVANCE, now, null);
+        final CatalogUpdater catalogUpdater = new CatalogUpdater(now, null);
         final String catalogXML = catalogUpdater.getCatalogXML();
         final StandaloneCatalog catalog = XMLLoader.getObjectFromStream(new URI("dummy"), new ByteArrayInputStream(catalogXML.getBytes(Charset.forName("UTF-8"))), StandaloneCatalog.class);
         assertEquals(catalog.getCurrentPlans().size(), 0);
@@ -68,7 +68,7 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
         final DateTime now = clock.getUTCNow();
         final SimplePlanDescriptor desc = new DefaultSimplePlanDescriptor("foo-monthly", "Foo", ProductCategory.BASE, Currency.EUR, BigDecimal.TEN, BillingPeriod.MONTHLY, 0, TimeUnit.UNLIMITED, ImmutableList.<String>of());
 
-        final CatalogUpdater catalogUpdater = new CatalogUpdater(BillingMode.IN_ADVANCE, now, desc.getCurrency());
+        final CatalogUpdater catalogUpdater = new CatalogUpdater(now, desc.getCurrency());
 
         catalogUpdater.addSimplePlanDescriptor(desc);
 
@@ -109,7 +109,7 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
         final DateTime now = clock.getUTCNow();
         final SimplePlanDescriptor desc = new DefaultSimplePlanDescriptor("foo-monthly", "Foo", ProductCategory.BASE, Currency.EUR, BigDecimal.TEN, BillingPeriod.MONTHLY, 14, TimeUnit.DAYS, ImmutableList.<String>of());
 
-        final CatalogUpdater catalogUpdater = new CatalogUpdater(BillingMode.IN_ADVANCE, now, desc.getCurrency());
+        final CatalogUpdater catalogUpdater = new CatalogUpdater(now, desc.getCurrency());
 
         catalogUpdater.addSimplePlanDescriptor(desc);
 
@@ -328,7 +328,6 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "<catalog>\n" +
                                    "    <effectiveDate>2013-02-08T00:00:00Z</effectiveDate>\n" +
                                    "    <catalogName>SpyCarBasic</catalogName>\n" +
-                                   "    <recurringBillingMode>IN_ADVANCE</recurringBillingMode>\n" +
                                    "    <currencies>\n" +
                                    "        <currency>USD</currency>\n" +
                                    "        <currency>GBP</currency>\n" +
@@ -432,6 +431,7 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "        </plan>\n" +
                                    "        <plan name=\"sports-monthly\" prettyName=\"sports-monthly\">\n" +
                                    "            <product>Sports</product>\n" +
+                                   "            <recurringBillingMode>IN_ADVANCE</recurringBillingMode>\n" +
                                    "            <initialPhases>\n" +
                                    "                <phase type=\"TRIAL\">\n" +
                                    "                    <duration>\n" +
@@ -468,6 +468,7 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "        </plan>\n" +
                                    "        <plan name=\"standard-monthly\" prettyName=\"standard-monthly\">\n" +
                                    "            <product>Standard</product>\n" +
+                                   "            <recurringBillingMode>IN_ADVANCE</recurringBillingMode>\n" +
                                    "            <initialPhases>\n" +
                                    "                <phase type=\"TRIAL\">\n" +
                                    "                    <duration>\n" +
@@ -504,6 +505,7 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "        </plan>\n" +
                                    "        <plan name=\"super-monthly\" prettyName=\"super-monthly\">\n" +
                                    "            <product>Super</product>\n" +
+                                   "            <recurringBillingMode>IN_ADVANCE</recurringBillingMode>\n" +
                                    "            <initialPhases>\n" +
                                    "                <phase type=\"TRIAL\">\n" +
                                    "                    <duration>\n" +
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 6a22b6a..6ff69c5 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
@@ -141,11 +141,11 @@ public class FixedAndRecurringInvoiceItemGenerator extends InvoiceItemGenerator 
             if (!events.getSubscriptionIdsWithAutoInvoiceOff().
                     contains(thisEvent.getSubscription().getId())) { // don't consider events for subscriptions that have auto_invoice_off
                 final BillingEvent adjustedNextEvent = (thisEvent.getSubscription().getId() == nextEvent.getSubscription().getId()) ? nextEvent : null;
-                final List<InvoiceItem> newProposedItems = processRecurringEvent(invoiceId, accountId, thisEvent, adjustedNextEvent, targetDate, currency, invoiceItemGeneratorLogger, events.getRecurringBillingMode(), perSubscriptionFutureNotificationDate, internalCallContext);
+                final List<InvoiceItem> newProposedItems = processRecurringEvent(invoiceId, accountId, thisEvent, adjustedNextEvent, targetDate, currency, invoiceItemGeneratorLogger, thisEvent.getPlan().getRecurringBillingMode(), perSubscriptionFutureNotificationDate, internalCallContext);
                 proposedItems.addAll(newProposedItems);
             }
         }
-        final List<InvoiceItem> newProposedItems = processRecurringEvent(invoiceId, accountId, nextEvent, null, targetDate, currency, invoiceItemGeneratorLogger, events.getRecurringBillingMode(), perSubscriptionFutureNotificationDate, internalCallContext);
+        final List<InvoiceItem> newProposedItems = processRecurringEvent(invoiceId, accountId, nextEvent, null, targetDate, currency, invoiceItemGeneratorLogger, nextEvent.getPlan().getRecurringBillingMode(), perSubscriptionFutureNotificationDate, internalCallContext);
 
         proposedItems.addAll(newProposedItems);
 
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/dao/TestInvoiceDao.java b/invoice/src/test/java/org/killbill/billing/invoice/dao/TestInvoiceDao.java
index ec684f1..9f4ae9d 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/dao/TestInvoiceDao.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/dao/TestInvoiceDao.java
@@ -1476,6 +1476,7 @@ public class TestInvoiceDao extends InvoiceTestSuiteWithEmbeddedDB {
 
         final Plan plan = Mockito.mock(Plan.class);
         Mockito.when(plan.getName()).thenReturn("plan");
+        Mockito.when(plan.getRecurringBillingMode()).thenReturn(BillingMode.IN_ADVANCE);
 
         final PlanPhase phase1 = Mockito.mock(PlanPhase.class);
         Mockito.when(phase1.getName()).thenReturn("plan-phase1");
@@ -1505,6 +1506,7 @@ public class TestInvoiceDao extends InvoiceTestSuiteWithEmbeddedDB {
 
         final Plan plan = Mockito.mock(Plan.class);
         Mockito.when(plan.getName()).thenReturn("plan");
+        Mockito.when(plan.getRecurringBillingMode()).thenReturn(BillingMode.IN_ADVANCE);
 
         final PlanPhase phase1 = Mockito.mock(PlanPhase.class);
         Mockito.when(phase1.getName()).thenReturn("plan-phase1");
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/generator/TestDefaultInvoiceGenerator.java b/invoice/src/test/java/org/killbill/billing/invoice/generator/TestDefaultInvoiceGenerator.java
index d7aa3d4..45f8c46 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/generator/TestDefaultInvoiceGenerator.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/generator/TestDefaultInvoiceGenerator.java
@@ -1118,7 +1118,7 @@ public class TestDefaultInvoiceGenerator extends InvoiceTestSuiteNoDB {
 
         // Cancel EOT and Add the item adjustment
         final BillingEvent event2 = invoiceUtil.createMockBillingEvent(account, sub, endDate.toDateTimeAtStartOfDay(),
-                                                                       null, phase,
+                                                                       plan, phase,
                                                                        ZERO, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 9,
                                                                        BillingMode.IN_ADVANCE, "Cancel", 2L,
                                                                        SubscriptionBaseTransitionType.CANCEL);
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/MockBillingEventSet.java b/invoice/src/test/java/org/killbill/billing/invoice/MockBillingEventSet.java
index 5dac9bb..2826c25 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/MockBillingEventSet.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/MockBillingEventSet.java
@@ -68,11 +68,6 @@ public class MockBillingEventSet extends TreeSet<BillingEvent> implements Billin
     }
 
     @Override
-    public BillingMode getRecurringBillingMode() {
-        return BillingMode.IN_ADVANCE;
-    }
-
-    @Override
     public List<UUID> getSubscriptionIdsWithAutoInvoiceOff() {
         return subscriptionIdsWithAutoInvoiceOff;
     }
diff --git a/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultBillingEventSet.java b/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultBillingEventSet.java
index 7eec199..0522fb1 100644
--- a/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultBillingEventSet.java
+++ b/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultBillingEventSet.java
@@ -44,13 +44,12 @@ public class DefaultBillingEventSet extends TreeSet<BillingEvent> implements Sor
     private final boolean accountAutoInvoiceDraft;
     private final boolean accountAutoInvoiceReuseDraft;
     private final List<UUID> subscriptionIdsWithAutoInvoiceOff;
-    private final BillingMode recurringBillingMode;
 
-    public DefaultBillingEventSet(final boolean accountAutoInvoiceOff, final boolean accountAutoInvoiceDraft, final boolean accountAutoInvoiceReuseDraft, final BillingMode recurringBillingMode) {
+
+    public DefaultBillingEventSet(final boolean accountAutoInvoiceOff, final boolean accountAutoInvoiceDraft, final boolean accountAutoInvoiceReuseDraft) {
         this.accountAutoInvoiceOff = accountAutoInvoiceOff;
         this.accountAutoInvoiceDraft = accountAutoInvoiceDraft;
         this.accountAutoInvoiceReuseDraft = accountAutoInvoiceReuseDraft;
-        this.recurringBillingMode = recurringBillingMode;
         this.subscriptionIdsWithAutoInvoiceOff = new ArrayList<UUID>();
     }
 
@@ -70,11 +69,6 @@ public class DefaultBillingEventSet extends TreeSet<BillingEvent> implements Sor
     }
 
     @Override
-    public BillingMode getRecurringBillingMode() {
-        return recurringBillingMode;
-    }
-
-    @Override
     public List<UUID> getSubscriptionIdsWithAutoInvoiceOff() {
         return subscriptionIdsWithAutoInvoiceOff;
     }
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 530cf8d..a3499b5 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
@@ -102,12 +102,12 @@ public class DefaultInternalBillingApi implements BillingInternalApi {
         final DefaultBillingEventSet result;
 
         if (found_AUTO_INVOICING_OFF) {
-            result = new DefaultBillingEventSet(true, found_INVOICING_DRAFT, found_INVOICING_REUSE_DRAFT, ((StaticCatalog) currentCatalog).getRecurringBillingMode()); // billing is off, we are done
+            result = new DefaultBillingEventSet(true, found_INVOICING_DRAFT, found_INVOICING_REUSE_DRAFT); // billing is off, we are done
         } else {
             final List<SubscriptionBaseBundle> bundles = subscriptionApi.getBundlesForAccount(accountId, context);
 
             final ImmutableAccountData account = accountApi.getImmutableAccountDataById(accountId, context);
-            result = new DefaultBillingEventSet(false, found_INVOICING_DRAFT, found_INVOICING_REUSE_DRAFT, ((StaticCatalog) currentCatalog).getRecurringBillingMode());
+            result = new DefaultBillingEventSet(false, found_INVOICING_DRAFT, found_INVOICING_REUSE_DRAFT);
             addBillingEventsForBundles(bundles, account, dryRunArguments, context, result, skippedSubscriptions, currentCatalog);
         }
 
diff --git a/util/src/test/java/org/killbill/billing/mock/MockPlan.java b/util/src/test/java/org/killbill/billing/mock/MockPlan.java
index dc78dea..d02457c 100644
--- a/util/src/test/java/org/killbill/billing/mock/MockPlan.java
+++ b/util/src/test/java/org/killbill/billing/mock/MockPlan.java
@@ -21,6 +21,7 @@ import java.util.Iterator;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
+import org.killbill.billing.catalog.api.BillingMode;
 import org.killbill.billing.catalog.api.BillingPeriod;
 import org.killbill.billing.catalog.api.CatalogApiException;
 import org.killbill.billing.catalog.api.PhaseType;
@@ -43,6 +44,11 @@ public class MockPlan implements Plan {
     }
 
     @Override
+    public BillingMode getRecurringBillingMode() {
+        return BillingMode.IN_ADVANCE;
+    }
+
+    @Override
     public PlanPhase[] getInitialPhases() {
         throw new UnsupportedOperationException();
     }