killbill-memoizeit

Fix issue with missing context in catalog (for price override) Implement

3/26/2015 4:45:17 PM

Changes

Details

diff --git a/catalog/src/main/java/org/killbill/billing/catalog/caching/EhCacheCatalogCache.java b/catalog/src/main/java/org/killbill/billing/catalog/caching/EhCacheCatalogCache.java
index c3351c9..b43e99d 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/caching/EhCacheCatalogCache.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/caching/EhCacheCatalogCache.java
@@ -55,7 +55,7 @@ public class EhCacheCatalogCache implements CatalogCache {
 
     @Override
     public void loadDefaultCatalog(final String url) throws CatalogApiException {
-        defaultCatalog = (url != null) ? loader.load(url) : null;
+        defaultCatalog = (url != null) ? loader.loadDefaultCatalog(url) : null;
     }
 
     @Override
@@ -92,8 +92,8 @@ public class EhCacheCatalogCache implements CatalogCache {
     private CacheLoaderArgument initializeCacheLoaderArgument(final EhCacheCatalogCache parentCache) {
         final LoaderCallback loaderCallback = new LoaderCallback() {
             @Override
-            public Object loadCatalog(final List<String> catalogXMLs) throws CatalogApiException {
-                return loader.load(catalogXMLs);
+            public Object loadCatalog(final List<String> catalogXMLs, final Long tenantRecordId) throws CatalogApiException {
+                return loader.load(catalogXMLs, tenantRecordId);
             }
         };
         final Object[] args = new Object[1];
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/dao/CatalogOverrideDao.java b/catalog/src/main/java/org/killbill/billing/catalog/dao/CatalogOverrideDao.java
index f4ffbc0..eaef9b1 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/dao/CatalogOverrideDao.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/dao/CatalogOverrideDao.java
@@ -17,11 +17,17 @@
 
 package org.killbill.billing.catalog.dao;
 
+import java.util.List;
+
 import org.joda.time.DateTime;
 import org.killbill.billing.callcontext.InternalCallContext;
+import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
 
 public interface CatalogOverrideDao {
 
     public CatalogOverridePlanDefinitionModelDao getOrCreateOverridePlanDefinition(String parentPlanName, DateTime catalogEffectiveDate, PlanPhasePriceOverride[] resolvedOverride, InternalCallContext context);
+
+    public List<CatalogOverridePhaseDefinitionModelDao> getOverriddenPlanPhases(final Long planDefRecordId, final InternalTenantContext context);
+
 }
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/dao/CatalogOverridePhaseDefinitionSqlDao.java b/catalog/src/main/java/org/killbill/billing/catalog/dao/CatalogOverridePhaseDefinitionSqlDao.java
index eb46a31..2e70525 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/dao/CatalogOverridePhaseDefinitionSqlDao.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/dao/CatalogOverridePhaseDefinitionSqlDao.java
@@ -18,6 +18,7 @@
 package org.killbill.billing.catalog.dao;
 
 import java.math.BigDecimal;
+import java.util.List;
 
 import org.killbill.billing.callcontext.InternalCallContext;
 import org.killbill.billing.callcontext.InternalTenantContext;
@@ -25,28 +26,32 @@ import org.killbill.commons.jdbi.binder.SmartBindBean;
 import org.skife.jdbi.v2.sqlobject.Bind;
 import org.skife.jdbi.v2.sqlobject.SqlQuery;
 import org.skife.jdbi.v2.sqlobject.SqlUpdate;
-import org.skife.jdbi.v2.sqlobject.customizers.Define;
 import org.skife.jdbi.v2.sqlobject.mixins.CloseMe;
 import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
 import org.skife.jdbi.v2.sqlobject.stringtemplate.UseStringTemplate3StatementLocator;
 
 @UseStringTemplate3StatementLocator
 public interface CatalogOverridePhaseDefinitionSqlDao extends Transactional<CatalogOverridePhaseDefinitionSqlDao>, CloseMe {
+
     @SqlUpdate
     public void create(@SmartBindBean final CatalogOverridePhaseDefinitionModelDao entity,
                        @SmartBindBean final InternalCallContext context);
 
-
     @SqlQuery
     public CatalogOverridePhaseDefinitionModelDao getByRecordId(@Bind("recordId") final Long recordId,
-                                                               @SmartBindBean final InternalTenantContext context);
+                                                                @SmartBindBean final InternalTenantContext context);
 
     @SqlQuery
     public CatalogOverridePhaseDefinitionModelDao getByAttributes(@Bind("parentPhaseName") String parentPhaseName,
-                                                                 @Bind("currency") String currency,
-                                                                 @Bind("fixedPrice") BigDecimal fixedPrice,
-                                                                 @Bind("recurringPrice") BigDecimal recurringPrice,
-                                                                 @SmartBindBean final InternalTenantContext context);
+                                                                  @Bind("currency") String currency,
+                                                                  @Bind("fixedPrice") BigDecimal fixedPrice,
+                                                                  @Bind("recurringPrice") BigDecimal recurringPrice,
+                                                                  @SmartBindBean final InternalTenantContext context);
+
+    @SqlQuery
+    public List<CatalogOverridePhaseDefinitionModelDao> getOverriddenPlanPhases(@Bind("targetPlanDefRecordId") Long targetPlanDefRecordId,
+                                                                                @SmartBindBean final InternalTenantContext context);
+
 
     @SqlQuery
     public Long getLastInsertId();
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/dao/DefaultCatalogOverrideDao.java b/catalog/src/main/java/org/killbill/billing/catalog/dao/DefaultCatalogOverrideDao.java
index 39d4150..3494b7b 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/dao/DefaultCatalogOverrideDao.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/dao/DefaultCatalogOverrideDao.java
@@ -22,6 +22,7 @@ import java.util.List;
 
 import org.joda.time.DateTime;
 import org.killbill.billing.callcontext.InternalCallContext;
+import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
 import org.killbill.clock.Clock;
 import org.killbill.commons.jdbi.mapper.LowerToCamelBeanMapperFactory;
@@ -85,7 +86,16 @@ public class DefaultCatalogOverrideDao implements CatalogOverrideDao {
         });
     }
 
-
+    @Override
+    public List<CatalogOverridePhaseDefinitionModelDao> getOverriddenPlanPhases(final Long planDefRecordId, final InternalTenantContext context) {
+        return dbi.inTransaction(new TransactionCallback<List<CatalogOverridePhaseDefinitionModelDao>>() {
+            @Override
+            public List<CatalogOverridePhaseDefinitionModelDao> inTransaction(final Handle handle, final TransactionStatus status) throws Exception {
+                final CatalogOverridePhaseDefinitionSqlDao sqlDao = handle.attach(CatalogOverridePhaseDefinitionSqlDao.class);
+                return sqlDao.getOverriddenPlanPhases(planDefRecordId, context);
+            }
+        });
+    }
 
     private Long getOverridePlanDefinitionFromTransaction(final CatalogOverridePhaseDefinitionModelDao[] overridePhaseDefinitionModelDaos, final Handle inTransactionHandle, final InternalCallContext context) {
         final CatalogOverridePlanPhaseSqlDao sqlDao = inTransactionHandle.attach(CatalogOverridePlanPhaseSqlDao.class);
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/io/CatalogLoader.java b/catalog/src/main/java/org/killbill/billing/catalog/io/CatalogLoader.java
index 642cf6f..953dfe3 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/io/CatalogLoader.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/io/CatalogLoader.java
@@ -23,6 +23,6 @@ import org.killbill.billing.catalog.api.CatalogApiException;
 
 public interface CatalogLoader {
 
-    public abstract VersionedCatalog load(String urlString)
+    public abstract VersionedCatalog loadDefaultCatalog(String urlString)
             throws CatalogApiException;
 }
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/io/VersionedCatalogLoader.java b/catalog/src/main/java/org/killbill/billing/catalog/io/VersionedCatalogLoader.java
index bf4c557..632d393 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/io/VersionedCatalogLoader.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/io/VersionedCatalogLoader.java
@@ -30,6 +30,7 @@ import org.killbill.billing.catalog.StandaloneCatalogWithPriceOverride;
 import org.killbill.billing.catalog.VersionedCatalog;
 import org.killbill.billing.catalog.api.CatalogApiException;
 import org.killbill.billing.catalog.override.PriceOverride;
+import org.killbill.billing.util.callcontext.InternalCallContextFactory;
 import org.killbill.clock.Clock;
 import org.killbill.xmlloader.UriAccessor;
 import org.killbill.xmlloader.XMLLoader;
@@ -44,18 +45,20 @@ public class VersionedCatalogLoader implements CatalogLoader {
 
     private final Clock clock;
     private final PriceOverride priceOverride;
+    private final InternalCallContextFactory internalCallContextFactory;
 
     @Inject
-    public VersionedCatalogLoader(final Clock clock, final PriceOverride priceOverride) {
+    public VersionedCatalogLoader(final Clock clock, final PriceOverride priceOverride, final InternalCallContextFactory internalCallContextFactory) {
         this.clock = clock;
         this.priceOverride = priceOverride;
+        this.internalCallContextFactory = internalCallContextFactory;
     }
 
     /* (non-Javadoc)
-      * @see org.killbill.billing.catalog.io.ICatalogLoader#load(java.lang.String)
+      * @see org.killbill.billing.catalog.io.ICatalogLoader#loadDefaultCatalog(java.lang.String)
       */
     @Override
-    public VersionedCatalog load(final String uriString) throws CatalogApiException {
+    public VersionedCatalog loadDefaultCatalog(final String uriString) throws CatalogApiException {
         try {
             List<URI> xmlURIs;
             if (uriString.endsWith(XML_EXTENSION)) { // Assume its an xml file
@@ -79,10 +82,10 @@ public class VersionedCatalogLoader implements CatalogLoader {
                 xmlURIs = findXmlReferences(directoryContents, new URL(uriString));
             }
 
-            final VersionedCatalog result = new VersionedCatalog(clock);
+            final VersionedCatalog result = new VersionedCatalog(clock, InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID);
             for (final URI u : xmlURIs) {
                 final StandaloneCatalog catalog = XMLLoader.getObjectFromUri(u, StandaloneCatalog.class);
-                result.add(new StandaloneCatalogWithPriceOverride(catalog, priceOverride));
+                result.add(new StandaloneCatalogWithPriceOverride(catalog, priceOverride, InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID, internalCallContextFactory));
             }
             return result;
         } catch (Exception e) {
@@ -90,15 +93,15 @@ public class VersionedCatalogLoader implements CatalogLoader {
         }
     }
 
-    public VersionedCatalog load(final List<String> catalogXMLs) throws CatalogApiException {
-        final VersionedCatalog result = new VersionedCatalog(clock);
+    public VersionedCatalog load(final List<String> catalogXMLs, final Long tenantRecordId) throws CatalogApiException {
+        final VersionedCatalog result = new VersionedCatalog(clock, tenantRecordId);
         final URI uri;
         try {
             uri = new URI("/tenantCatalog");
             for (final String cur : catalogXMLs) {
                 final InputStream curCatalogStream = new ByteArrayInputStream(cur.getBytes());
                 final StandaloneCatalog catalog = XMLLoader.getObjectFromStream(uri, curCatalogStream, StandaloneCatalog.class);
-                result.add(new StandaloneCatalogWithPriceOverride(catalog, priceOverride));
+                result.add(new StandaloneCatalogWithPriceOverride(catalog, priceOverride, tenantRecordId, internalCallContextFactory));
             }
             return result;
         } catch (Exception e) {
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/override/DefaultPriceOverride.java b/catalog/src/main/java/org/killbill/billing/catalog/override/DefaultPriceOverride.java
index 6dcb2e1..b1b20b4 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/override/DefaultPriceOverride.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/override/DefaultPriceOverride.java
@@ -18,17 +18,23 @@
 package org.killbill.billing.catalog.override;
 
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.joda.time.DateTime;
 import org.killbill.billing.callcontext.InternalCallContext;
+import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.catalog.DefaultPlan;
 import org.killbill.billing.catalog.DefaultPlanPhasePriceOverride;
 import org.killbill.billing.catalog.api.CatalogApiException;
+import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.catalog.api.Plan;
 import org.killbill.billing.catalog.api.PlanPhase;
 import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
 import org.killbill.billing.catalog.api.PlanPhaseSpecifier;
+import org.killbill.billing.catalog.api.StaticCatalog;
 import org.killbill.billing.catalog.dao.CatalogOverrideDao;
+import org.killbill.billing.catalog.dao.CatalogOverridePhaseDefinitionModelDao;
 import org.killbill.billing.catalog.dao.CatalogOverridePlanDefinitionModelDao;
 
 import com.google.common.base.Predicate;
@@ -37,6 +43,8 @@ import com.google.inject.Inject;
 
 public class DefaultPriceOverride implements PriceOverride {
 
+    final Pattern CUSTOM_PLAN_NAME_PATTERN = Pattern.compile("(.*)-(\\d+)$");
+
     private final CatalogOverrideDao overrideDao;
 
     @Inject
@@ -48,7 +56,7 @@ public class DefaultPriceOverride implements PriceOverride {
     public DefaultPlan getOrCreateOverriddenPlan(final Plan parentPlan, final DateTime catalogEffectiveDate, final List<PlanPhasePriceOverride> overrides, final InternalCallContext context) throws CatalogApiException {
 
         final PlanPhasePriceOverride[] resolvedOverride = new PlanPhasePriceOverride[parentPlan.getAllPhases().length];
-        int index  = 0;
+        int index = 0;
         for (final PlanPhase curPhase : parentPlan.getAllPhases()) {
             final PlanPhasePriceOverride curOverride = Iterables.tryFind(overrides, new Predicate<PlanPhasePriceOverride>() {
                 @Override
@@ -72,7 +80,42 @@ public class DefaultPriceOverride implements PriceOverride {
 
         final CatalogOverridePlanDefinitionModelDao overriddenPlan = overrideDao.getOrCreateOverridePlanDefinition(parentPlan.getName(), catalogEffectiveDate, resolvedOverride, context);
         final String planName = new StringBuffer(parentPlan.getName()).append("-").append(overriddenPlan.getRecordId()).toString();
-        final DefaultPlan result  = new DefaultPlan(planName, (DefaultPlan) parentPlan, resolvedOverride);
+        final DefaultPlan result = new DefaultPlan(planName, (DefaultPlan) parentPlan, resolvedOverride);
+        return result;
+    }
+
+    @Override
+    public DefaultPlan getOverriddenPlan(final String planName, final StaticCatalog catalog, final InternalTenantContext context) throws CatalogApiException {
+
+        final Matcher m = CUSTOM_PLAN_NAME_PATTERN.matcher(planName);
+        final String parentPlanName = m.group(1);
+        final Long planDefRecordId = Long.parseLong(m.group(2));
+
+        final List<CatalogOverridePhaseDefinitionModelDao> phaseDefs = overrideDao.getOverriddenPlanPhases(planDefRecordId, context);
+        final DefaultPlan defaultPlan = (DefaultPlan) catalog.findCurrentPlan(parentPlanName);
+
+        final PlanPhasePriceOverride[] overrides = createOverrides(defaultPlan, phaseDefs);
+        return new DefaultPlan(planName, defaultPlan, overrides);
+    }
+
+    private PlanPhasePriceOverride[] createOverrides(final Plan defaultPlan, final List<CatalogOverridePhaseDefinitionModelDao> phaseDefs) {
+
+        final PlanPhasePriceOverride[] result = new PlanPhasePriceOverride[defaultPlan.getAllPhases().length];
+
+        for (int i = 0; i < defaultPlan.getAllPhases().length; i++) {
+
+            final PlanPhase curPhase = defaultPlan.getAllPhases()[i];
+            final CatalogOverridePhaseDefinitionModelDao overriddenPhase = Iterables.tryFind(phaseDefs, new Predicate<CatalogOverridePhaseDefinitionModelDao>() {
+                @Override
+                public boolean apply(final CatalogOverridePhaseDefinitionModelDao input) {
+                    return input.getParentPhaseName().equals(curPhase.getName());
+                }
+            }).orNull();
+            result[i] = (overriddenPhase != null) ?
+                        new DefaultPlanPhasePriceOverride(curPhase.getName(), Currency.valueOf(overriddenPhase.getCurrency()), overriddenPhase.getFixedPrice(), overriddenPhase.getRecurringPrice()) :
+                        null;
+        }
         return result;
     }
+
 }
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/override/PriceOverride.java b/catalog/src/main/java/org/killbill/billing/catalog/override/PriceOverride.java
index b60befe..49cdbc8 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/override/PriceOverride.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/override/PriceOverride.java
@@ -21,12 +21,17 @@ import java.util.List;
 
 import org.joda.time.DateTime;
 import org.killbill.billing.callcontext.InternalCallContext;
+import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.catalog.DefaultPlan;
 import org.killbill.billing.catalog.api.CatalogApiException;
 import org.killbill.billing.catalog.api.Plan;
 import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
+import org.killbill.billing.catalog.api.StaticCatalog;
 
 public interface PriceOverride {
 
     DefaultPlan getOrCreateOverriddenPlan(final Plan parentPlan, final DateTime catalogEffectiveDate, final List<PlanPhasePriceOverride> overrides, final InternalCallContext context) throws CatalogApiException;
+
+
+    DefaultPlan getOverriddenPlan(final String planName, final StaticCatalog catalog, final InternalTenantContext context) throws CatalogApiException;
 }
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 a603547..596c5cd 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalog.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalog.java
@@ -42,13 +42,13 @@ import org.killbill.billing.catalog.api.PlanAlignmentCreate;
 import org.killbill.billing.catalog.api.PlanChangeResult;
 import org.killbill.billing.catalog.api.PlanPhase;
 import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
+import org.killbill.billing.catalog.api.PlanPhasePriceOverridesWithCallContext;
 import org.killbill.billing.catalog.api.PlanPhaseSpecifier;
 import org.killbill.billing.catalog.api.PlanSpecifier;
 import org.killbill.billing.catalog.api.PriceList;
 import org.killbill.billing.catalog.api.Product;
 import org.killbill.billing.catalog.api.ProductCategory;
 import org.killbill.billing.catalog.api.StaticCatalog;
-import org.killbill.billing.catalog.override.PriceOverride;
 import org.killbill.billing.catalog.rules.PlanRules;
 import org.killbill.xmlloader.ValidatingConfig;
 import org.killbill.xmlloader.ValidationErrors;
@@ -58,6 +58,7 @@ import com.google.common.collect.ImmutableList;
 @XmlRootElement(name = "catalog")
 @XmlAccessorType(XmlAccessType.NONE)
 public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> implements StaticCatalog {
+
     @XmlElement(required = true)
     private Date effectiveDate;
 
@@ -89,7 +90,6 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
     @XmlElement(name = "priceLists", required = true)
     private DefaultPriceListSet priceLists;
 
-
     private URI catalogURI;
 
     public StandaloneCatalog() {
@@ -120,14 +120,14 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
     /* (non-Javadoc)
      * @see org.killbill.billing.catalog.ICatalog#getProducts()
      */
-   @Override
-   public DefaultProduct[] getCurrentProducts() {
-       return products;
-   }
-
-   /* (non-Javadoc)
-    * @see org.killbill.billing.catalog.ICatalog#getProducts()
-    */
+    @Override
+    public DefaultProduct[] getCurrentProducts() {
+        return products;
+    }
+
+    /* (non-Javadoc)
+     * @see org.killbill.billing.catalog.ICatalog#getProducts()
+     */
     @Override
     public DefaultUnit[] getCurrentUnits() {
         return units;
@@ -163,7 +163,7 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
       * @see org.killbill.billing.catalog.ICatalog#getPlan(java.lang.String, java.lang.String)
       */
     @Override
-    public DefaultPlan findCurrentPlan(final String productName, final BillingPeriod period, final String priceListName, final List<PlanPhasePriceOverride> nullOverrides) throws CatalogApiException {
+    public DefaultPlan findCurrentPlan(final String productName, final BillingPeriod period, final String priceListName, final PlanPhasePriceOverridesWithCallContext unused) throws CatalogApiException {
         if (productName == null) {
             throw new CatalogApiException(ErrorCode.CAT_NULL_PRODUCT_NAME);
         }
@@ -226,7 +226,6 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
         return priceLists.findPriceListFrom(name);
     }
 
-
     //////////////////////////////////////////////////////////////////////////////
     //
     // RULES
@@ -272,7 +271,6 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
         return errors;
     }
 
-
     @Override
     public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
         catalogURI = sourceURI;
@@ -288,13 +286,12 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
 
     }
 
-
     //////////////////////////////////////////////////////////////////////////////
     //
     // UNIT LIMIT
     //
     //////////////////////////////////////////////////////////////////////////////
-    
+
     @Override
     public boolean compliesWithLimits(final String phaseName, final String unit, final double value) throws CatalogApiException {
         PlanPhase phase = findCurrentPhase(phaseName);
@@ -349,12 +346,12 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
     @Override
     public boolean canCreatePlan(final PlanSpecifier specifier) throws CatalogApiException {
         final Product product = findCurrentProduct(specifier.getProductName());
-        final Plan plan = findCurrentPlan(specifier.getProductName(), specifier.getBillingPeriod(), specifier.getPriceListName(), ImmutableList.<PlanPhasePriceOverride>of());
+        final Plan plan = findCurrentPlan(specifier.getProductName(), specifier.getBillingPeriod(), specifier.getPriceListName(), null);
         final DefaultPriceList priceList = findCurrentPriceList(specifier.getPriceListName());
 
         return (!product.isRetired()) &&
-                (!plan.isRetired()) &&
-                (!priceList.isRetired());
+               (!plan.isRetired()) &&
+               (!priceList.isRetired());
     }
 
     @Override
@@ -363,13 +360,13 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
 
         try {
             Product product = findCurrentProduct(baseProductName);
-            if ( product != null ) {
-                for ( Product availAddon : product.getAvailable() ) {
-                    for ( BillingPeriod billingPeriod : BillingPeriod.values()) {
-                        for( PriceList priceList : getPriceLists().getAllPriceLists()) {
+            if (product != null) {
+                for (Product availAddon : product.getAvailable()) {
+                    for (BillingPeriod billingPeriod : BillingPeriod.values()) {
+                        for (PriceList priceList : getPriceLists().getAllPriceLists()) {
                             if (priceListName == null || priceListName.equals(priceList.getName())) {
                                 Plan addonInList = priceList.findPlan(availAddon, billingPeriod);
-                                if ( (addonInList != null) ) {
+                                if ((addonInList != null)) {
                                     availAddons.add(new DefaultListing(addonInList, priceList));
                                 }
                             }
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 3564fb1..a95c5f8 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalogWithPriceOverride.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalogWithPriceOverride.java
@@ -38,6 +38,7 @@ import org.killbill.billing.catalog.api.PlanAlignmentCreate;
 import org.killbill.billing.catalog.api.PlanChangeResult;
 import org.killbill.billing.catalog.api.PlanPhase;
 import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
+import org.killbill.billing.catalog.api.PlanPhasePriceOverridesWithCallContext;
 import org.killbill.billing.catalog.api.PlanPhaseSpecifier;
 import org.killbill.billing.catalog.api.PlanSpecifier;
 import org.killbill.billing.catalog.api.PriceList;
@@ -45,6 +46,7 @@ import org.killbill.billing.catalog.api.Product;
 import org.killbill.billing.catalog.api.StaticCatalog;
 import org.killbill.billing.catalog.api.Unit;
 import org.killbill.billing.catalog.override.PriceOverride;
+import org.killbill.billing.util.callcontext.InternalCallContextFactory;
 import org.killbill.xmlloader.ValidatingConfig;
 import org.killbill.xmlloader.ValidationErrors;
 
@@ -52,10 +54,15 @@ public class StandaloneCatalogWithPriceOverride extends ValidatingConfig<Standal
 
     private final StandaloneCatalog standaloneCatalog;
     private final PriceOverride priceOverride;
+    private final Long tenantRecordId;
 
-    public StandaloneCatalogWithPriceOverride(final StandaloneCatalog staticCatalog, final PriceOverride priceOverride) {
+    private final InternalCallContextFactory internalCallContextFactory;
+
+    public StandaloneCatalogWithPriceOverride(final StandaloneCatalog staticCatalog, final PriceOverride priceOverride, final Long tenantRecordId, final InternalCallContextFactory internalCallContextFactory) {
+        this.tenantRecordId = tenantRecordId;
         this.standaloneCatalog = staticCatalog;
         this.priceOverride = priceOverride;
+        this.internalCallContextFactory = internalCallContextFactory;
     }
 
     @Override
@@ -94,19 +101,27 @@ public class StandaloneCatalogWithPriceOverride extends ValidatingConfig<Standal
     }
 
     @Override
-    public Plan findCurrentPlan(final String productName, final BillingPeriod period, final String priceListName, final List<PlanPhasePriceOverride> overrides) throws CatalogApiException {
+    public Plan findCurrentPlan(final String productName, final BillingPeriod period, final String priceListName, final PlanPhasePriceOverridesWithCallContext overrides) throws CatalogApiException {
         final Plan defaultPlan = standaloneCatalog.findCurrentPlan(productName, period, priceListName, null);
-        if (overrides == null || overrides.isEmpty()) {
+
+        if (overrides == null ||
+            overrides.getOverrides() == null ||
+            overrides.getOverrides().isEmpty()) {
             return defaultPlan;
         }
-        // STEPH_PO Hum, how am i supposed to create a context here???
-        final InternalCallContext context = null;
-        return priceOverride.getOrCreateOverriddenPlan(defaultPlan, new DateTime(getEffectiveDate()), overrides, context);
+
+        final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(overrides.getCallContext());
+        return priceOverride.getOrCreateOverriddenPlan(defaultPlan, new DateTime(getEffectiveDate()), overrides.getOverrides(), internalCallContext);
     }
 
     @Override
     public Plan findCurrentPlan(final String planName) throws CatalogApiException {
-        return standaloneCatalog.findCurrentPlan(planName);
+        final Plan defaultPlan =  standaloneCatalog.findCurrentPlan(planName);
+        if (defaultPlan != null) {
+            return defaultPlan;
+        }
+        return null; // STEPH_PO
+     //   priceOverride.
     }
 
     @Override
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 e647ad5..9170593 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/VersionedCatalog.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/VersionedCatalog.java
@@ -48,6 +48,7 @@ import org.killbill.billing.catalog.api.PlanAlignmentCreate;
 import org.killbill.billing.catalog.api.PlanChangeResult;
 import org.killbill.billing.catalog.api.PlanPhase;
 import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
+import org.killbill.billing.catalog.api.PlanPhasePriceOverridesWithCallContext;
 import org.killbill.billing.catalog.api.PlanPhaseSpecifier;
 import org.killbill.billing.catalog.api.PlanSpecifier;
 import org.killbill.billing.catalog.api.PriceList;
@@ -65,17 +66,20 @@ public class VersionedCatalog extends ValidatingConfig<StandaloneCatalogWithPric
     private final Clock clock;
     private String catalogName;
     private BillingMode recurringBillingMode;
+    private final Long tenantRecordId;
 
     @XmlElement(name = "catalogVersion", required = true)
     private final List<StandaloneCatalogWithPriceOverride> versions = new ArrayList<StandaloneCatalogWithPriceOverride>();
 
-    // Default CTOR for XMLWriter.writeXML
+    // Required for JAXB deserialization
     public VersionedCatalog() {
         this.clock = null;
+        this.tenantRecordId = null;
     }
 
-    public VersionedCatalog(final Clock clock) {
+    public VersionedCatalog(final Clock clock, final Long tenantRecordId) {
         this.clock = clock;
+        this.tenantRecordId = tenantRecordId;
     }
 
 
@@ -111,14 +115,14 @@ public class VersionedCatalog extends ValidatingConfig<StandaloneCatalogWithPric
         String productName;
         BillingPeriod bp;
         String priceListName;
-        List<PlanPhasePriceOverride> overrides;
+        PlanPhasePriceOverridesWithCallContext overrides;
 
         public PlanRequestWrapper(final String name) {
             this.name = name;
         }
 
         public PlanRequestWrapper(final String productName, final BillingPeriod bp,
-                                  final String priceListName, List<PlanPhasePriceOverride> overrides) {
+                                  final String priceListName, final PlanPhasePriceOverridesWithCallContext overrides) {
             this.productName = productName;
             this.bp = bp;
             this.priceListName = priceListName;
@@ -245,7 +249,7 @@ public class VersionedCatalog extends ValidatingConfig<StandaloneCatalogWithPric
     public Plan findPlan(final String productName,
                          final BillingPeriod term,
                          final String priceListName,
-                         final List<PlanPhasePriceOverride> overrides,
+                         final PlanPhasePriceOverridesWithCallContext overrides,
                          final DateTime requestedDate)
             throws CatalogApiException {
         return versionForDate(requestedDate).findCurrentPlan(productName, term, priceListName, overrides);
@@ -263,7 +267,7 @@ public class VersionedCatalog extends ValidatingConfig<StandaloneCatalogWithPric
     public Plan findPlan(final String productName,
                          final BillingPeriod term,
                          final String priceListName,
-                         final List<PlanPhasePriceOverride> overrides,
+                         final PlanPhasePriceOverridesWithCallContext overrides,
                          final DateTime requestedDate,
                          final DateTime subscriptionStartDate)
             throws CatalogApiException {
@@ -401,7 +405,7 @@ public class VersionedCatalog extends ValidatingConfig<StandaloneCatalogWithPric
 
     @Override
     public Plan findCurrentPlan(final String productName, final BillingPeriod term,
-                                final String priceList, List<PlanPhasePriceOverride> overrides) throws CatalogApiException {
+                                final String priceList, PlanPhasePriceOverridesWithCallContext overrides) throws CatalogApiException {
         return versionForDate(clock.getUTCNow()).findCurrentPlan(productName, term, priceList, overrides);
     }
 
diff --git a/catalog/src/main/resources/org/killbill/billing/catalog/dao/CatalogOverridePhaseDefinitionSqlDao.sql.stg b/catalog/src/main/resources/org/killbill/billing/catalog/dao/CatalogOverridePhaseDefinitionSqlDao.sql.stg
index 554f8d2..7f27b07 100644
--- a/catalog/src/main/resources/org/killbill/billing/catalog/dao/CatalogOverridePhaseDefinitionSqlDao.sql.stg
+++ b/catalog/src/main/resources/org/killbill/billing/catalog/dao/CatalogOverridePhaseDefinitionSqlDao.sql.stg
@@ -67,6 +67,19 @@ and tenant_record_id = :tenantRecordId
 >>
 
 
+getOverriddenPlanPhases() ::= <<
+select <allTableFields("pdef.")>
+from <tableName()> pdef
+join catalog_override_plan_phase pp
+on pdef.record_id = pp.phase_def_record_id
+where
+pp.target_plan_def_record_id = :targetPlanDefRecordId
+and pp.tenant_record_id = :tenantRecordId
+order by pp.phase_number asc
+;
+>>
+
+
 getLastInsertId() ::= <<
 select LAST_INSERT_ID();
 >>
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/dao/TestCatalogOverrideDao.java b/catalog/src/test/java/org/killbill/billing/catalog/dao/TestCatalogOverrideDao.java
index 7f96efb..ee92a26 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/dao/TestCatalogOverrideDao.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/dao/TestCatalogOverrideDao.java
@@ -18,6 +18,7 @@
 package org.killbill.billing.catalog.dao;
 
 import java.math.BigDecimal;
+import java.util.List;
 
 import org.joda.time.DateTime;
 import org.killbill.billing.catalog.CatalogTestSuiteWithEmbeddedDB;
@@ -27,7 +28,6 @@ import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.catalog.api.Plan;
 import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
 import org.killbill.xmlloader.XMLLoader;
-import org.skife.jdbi.v2.Handle;
 import org.skife.jdbi.v2.tweak.HandleCallback;
 import org.testng.annotations.Test;
 
@@ -66,6 +66,34 @@ public class TestCatalogOverrideDao extends CatalogTestSuiteWithEmbeddedDB {
         assertEquals(newPlan.getParentPlanName(), "discount-standard-monthly");
         assertTrue(newPlan.getIsActive());
 
+        final List<CatalogOverridePhaseDefinitionModelDao> phases = catalogOverrideDao.getOverriddenPlanPhases(1L, internalCallContext);
+        assertEquals(phases.size(), 2);
     }
+
+
+    @Test(groups = "slow")
+    public void testGetOverriddenPlanPhases() throws Exception {
+
+        final StandaloneCatalog catalog = XMLLoader.getObjectFromString(Resources.getResource("SpyCarAdvanced.xml").toExternalForm(), StandaloneCatalog.class);
+        final Plan plan = catalog.findCurrentPlan("discount-standard-monthly");
+
+        final PlanPhasePriceOverride[] resolvedOverrides = new PlanPhasePriceOverride[plan.getAllPhases().length];
+        resolvedOverrides[0] = new DefaultPlanPhasePriceOverride(plan.getAllPhases()[0].getName(), Currency.USD, BigDecimal.TEN, BigDecimal.ONE);
+        resolvedOverrides[1] = new DefaultPlanPhasePriceOverride(plan.getAllPhases()[1].getName(), Currency.USD, BigDecimal.ONE, BigDecimal.TEN);
+        resolvedOverrides[2] = new DefaultPlanPhasePriceOverride(plan.getFinalPhase().getName(), Currency.USD, BigDecimal.ZERO, new BigDecimal("348.64"));
+
+        final CatalogOverridePlanDefinitionModelDao newPlan = catalogOverrideDao.getOrCreateOverridePlanDefinition(plan.getName(), new DateTime(catalog.getEffectiveDate()), resolvedOverrides, internalCallContext);
+
+        final List<CatalogOverridePhaseDefinitionModelDao> phases = catalogOverrideDao.getOverriddenPlanPhases(newPlan.getRecordId(), internalCallContext);
+        assertEquals(phases.size(), 3);
+        for (int i = 0; i < 3; i++) {
+            final CatalogOverridePhaseDefinitionModelDao curPhase = phases.get(i);
+            assertEquals(curPhase.getCurrency(), resolvedOverrides[i].getCurrency().name());
+            assertEquals(curPhase.getFixedPrice().compareTo(resolvedOverrides[i].getFixedPrice()), 0);
+            assertEquals(curPhase.getRecurringPrice().compareTo(resolvedOverrides[i].getRecurringPrice()), 0);
+            assertEquals(curPhase.getParentPhaseName(), resolvedOverrides[i].getPhaseName());
+        }
+    }
+
 }
 
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/io/TestVersionedCatalogLoader.java b/catalog/src/test/java/org/killbill/billing/catalog/io/TestVersionedCatalogLoader.java
index 9f0d0f9..d6f212e 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/io/TestVersionedCatalogLoader.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/io/TestVersionedCatalogLoader.java
@@ -31,12 +31,10 @@ import javax.xml.transform.TransformerException;
 
 import org.joda.time.DateTime;
 import org.killbill.billing.catalog.CatalogTestSuiteNoDB;
-import org.killbill.billing.catalog.StandaloneCatalog;
 import org.killbill.billing.catalog.StandaloneCatalogWithPriceOverride;
 import org.killbill.billing.catalog.VersionedCatalog;
 import org.killbill.billing.catalog.api.CatalogApiException;
 import org.killbill.billing.catalog.api.InvalidConfigException;
-import org.killbill.billing.platform.api.KillbillService.ServiceException;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 import org.xml.sax.SAXException;
@@ -118,7 +116,7 @@ public class TestVersionedCatalogLoader extends CatalogTestSuiteNoDB {
 
     @Test(groups = "fast")
     public void testLoad() throws IOException, SAXException, InvalidConfigException, JAXBException, TransformerException, URISyntaxException, CatalogApiException {
-        final VersionedCatalog c = loader.load(Resources.getResource("versionedCatalog").toString());
+        final VersionedCatalog c = loader.loadDefaultCatalog(Resources.getResource("versionedCatalog").toString());
         Assert.assertEquals(c.size(), 3);
         final Iterator<StandaloneCatalogWithPriceOverride> it = c.iterator();
         DateTime dt = new DateTime("2011-01-01T00:00:00+00:00");
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/MockCatalog.java b/catalog/src/test/java/org/killbill/billing/catalog/MockCatalog.java
index f4b0fb1..88e6cd6 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/MockCatalog.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/MockCatalog.java
@@ -33,6 +33,7 @@ import org.killbill.billing.catalog.api.PlanAlignmentCreate;
 import org.killbill.billing.catalog.api.PlanChangeResult;
 import org.killbill.billing.catalog.api.PlanPhase;
 import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
+import org.killbill.billing.catalog.api.PlanPhasePriceOverridesWithCallContext;
 import org.killbill.billing.catalog.api.PlanPhaseSpecifier;
 import org.killbill.billing.catalog.api.PlanSpecifier;
 import org.killbill.billing.catalog.api.PriceList;
@@ -111,7 +112,7 @@ public class MockCatalog extends StandaloneCatalog implements Catalog {
     }
 
     @Override
-    public Plan findPlan(final String productName, final BillingPeriod term, final String priceListName, List<PlanPhasePriceOverride> overrides, final DateTime requestedDate)
+    public Plan findPlan(final String productName, final BillingPeriod term, final String priceListName, PlanPhasePriceOverridesWithCallContext overrides, final DateTime requestedDate)
             throws CatalogApiException {
         return findCurrentPlan(productName, term, priceListName, overrides);
     }
@@ -123,7 +124,7 @@ public class MockCatalog extends StandaloneCatalog implements Catalog {
     }
 
     @Override
-    public Plan findPlan(final String productName, final BillingPeriod term, final String priceListName, List<PlanPhasePriceOverride> overrides, final DateTime requestedDate,
+    public Plan findPlan(final String productName, final BillingPeriod term, final String priceListName, PlanPhasePriceOverridesWithCallContext overrides, final DateTime requestedDate,
                          final DateTime subscriptionStartDate) throws CatalogApiException {
         return findCurrentPlan(productName, term, priceListName, overrides);
     }
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/TestLimits.java b/catalog/src/test/java/org/killbill/billing/catalog/TestLimits.java
index 7cfe30c..bd730c4 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/TestLimits.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/TestLimits.java
@@ -30,7 +30,7 @@ public class TestLimits extends CatalogTestSuiteNoDB {
     @BeforeClass(groups = "fast")
     public void beforeClass() throws Exception {
         super.beforeClass();
-        catalog = loader.load(Resources.getResource("WeaponsHireSmall.xml").toString());
+        catalog = loader.loadDefaultCatalog(Resources.getResource("WeaponsHireSmall.xml").toString());
     }
 
     @Test(groups = "fast")
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/TestVersionedCatalog.java b/catalog/src/test/java/org/killbill/billing/catalog/TestVersionedCatalog.java
index 08adf80..12d60f5 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/TestVersionedCatalog.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/TestVersionedCatalog.java
@@ -47,12 +47,12 @@ public class TestVersionedCatalog extends CatalogTestSuiteNoDB {
     @BeforeClass(groups = "fast")
     public void beforeClass() throws Exception {
         super.beforeClass();
-        vc = loader.load(Resources.getResource("versionedCatalog").toString());
+        vc = loader.loadDefaultCatalog(Resources.getResource("versionedCatalog").toString());
     }
 
     @Test(groups = "fast")
     public void testAddCatalog() throws IOException, SAXException, InvalidConfigException, JAXBException, TransformerException, URISyntaxException, ServiceException, CatalogApiException {
-        vc.add(new StandaloneCatalogWithPriceOverride(new StandaloneCatalog(new Date()).setCatalogName(vc.getCatalogName()).setRecurringBillingMode(vc.getRecurringBillingMode()), null));
+        vc.add(new StandaloneCatalogWithPriceOverride(new StandaloneCatalog(new Date()).setCatalogName(vc.getCatalogName()).setRecurringBillingMode(vc.getRecurringBillingMode()), null, 0L, null));
         Assert.assertEquals(vc.size(), 4);
     }
 
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/template/bundles/DefaultResourceBundleFactory.java b/invoice/src/main/java/org/killbill/billing/invoice/template/bundles/DefaultResourceBundleFactory.java
index 3a6fc9f..f989471 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/template/bundles/DefaultResourceBundleFactory.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/template/bundles/DefaultResourceBundleFactory.java
@@ -82,11 +82,11 @@ public class DefaultResourceBundleFactory implements ResourceBundleFactory {
 
     private ResourceBundle getGlobalBundle(final Locale locale, final String bundlePath) {
         try {
-            // Try to load the bundle from the classpath first
+            // Try to loadDefaultCatalog the bundle from the classpath first
             return ResourceBundle.getBundle(bundlePath, locale);
         } catch (MissingResourceException ignored) {
         }
-        // Try to load it from a properties file
+        // Try to loadDefaultCatalog it from a properties file
         final String propertiesFileNameWithCountry = bundlePath + "_" + locale.getLanguage() + "_" + locale.getCountry() + ".properties";
         ResourceBundle bundle = getBundleFromPropertiesFile(propertiesFileNameWithCountry);
         if (bundle != null) {
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/caching/EhCacheOverdueConfigCache.java b/overdue/src/main/java/org/killbill/billing/overdue/caching/EhCacheOverdueConfigCache.java
index 2624064..27b51f1 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/caching/EhCacheOverdueConfigCache.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/caching/EhCacheOverdueConfigCache.java
@@ -72,7 +72,7 @@ public class EhCacheOverdueConfigCache implements OverdueConfigCache {
         }
         if (missingOrCorruptedDefaultConfig) {
             defaultOverdueConfig = new DefaultOverdueConfig();
-            log.warn("Overdue system disabled: unable to load the overdue config from " + configURI);
+            log.warn("Overdue system disabled: unable to loadDefaultCatalog the overdue config from " + configURI);
         }
     }
 
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/service/DefaultOverdueService.java b/overdue/src/main/java/org/killbill/billing/overdue/service/DefaultOverdueService.java
index 011eb4f..87cc174 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/service/DefaultOverdueService.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/service/DefaultOverdueService.java
@@ -91,7 +91,7 @@ public class DefaultOverdueService implements OverdueService {
                 overdueConfigCache.loadDefaultOverdueConfig(properties.getConfigURI());
                 isConfigLoaded = true;
             } catch (OverdueApiException e) {
-                log.warn("Overdue system disabled: unable to load the overdue config from " + properties.getConfigURI(), e);
+                log.warn("Overdue system disabled: unable to loadDefaultCatalog the overdue config from " + properties.getConfigURI(), e);
                 e.printStackTrace();
             }
         }
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/alignment/PlanAligner.java b/subscription/src/main/java/org/killbill/billing/subscription/alignment/PlanAligner.java
index 16a32fa..8d76cbd 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/alignment/PlanAligner.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/alignment/PlanAligner.java
@@ -70,7 +70,7 @@ public class PlanAligner extends BaseAligner {
      * @param plan            the current Plan
      * @param initialPhase    the initialPhase on which we should create that subscription. can be null
      * @param priceList       the priceList
-     * @param requestedDate   the requested date (only used to load the catalog)
+     * @param requestedDate   the requested date (only used to loadDefaultCatalog the catalog)
      * @param effectiveDate   the effective creation date (driven by the catalog policy, i.e. when the creation occurs)
      * @return the current and next phases
      * @throws CatalogApiException         for catalog errors
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultPlanPhasePriceOverridesWithCallContext.java b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultPlanPhasePriceOverridesWithCallContext.java
new file mode 100644
index 0000000..cdfb2fd
--- /dev/null
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultPlanPhasePriceOverridesWithCallContext.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 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.subscription.api.svcs;
+
+import java.util.List;
+
+import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
+import org.killbill.billing.catalog.api.PlanPhasePriceOverridesWithCallContext;
+import org.killbill.billing.util.callcontext.CallContext;
+
+public class DefaultPlanPhasePriceOverridesWithCallContext implements PlanPhasePriceOverridesWithCallContext {
+
+    private final List<PlanPhasePriceOverride> overrides;
+    private final CallContext callContext;
+
+    public DefaultPlanPhasePriceOverridesWithCallContext(final List<PlanPhasePriceOverride> overrides, final CallContext callContext) {
+        this.overrides = overrides;
+        this.callContext = callContext;
+    }
+
+    @Override
+    public List<PlanPhasePriceOverride> getOverrides() {
+        return overrides;
+    }
+
+    @Override
+    public CallContext getCallContext() {
+        return callContext;
+    }
+}
\ No newline at end of file
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
index 213dfac..2819f8b 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
@@ -39,6 +39,7 @@ import org.killbill.billing.catalog.api.Plan;
 import org.killbill.billing.catalog.api.PlanChangeResult;
 import org.killbill.billing.catalog.api.PlanPhase;
 import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
+import org.killbill.billing.catalog.api.PlanPhasePriceOverridesWithCallContext;
 import org.killbill.billing.catalog.api.PlanPhaseSpecifier;
 import org.killbill.billing.catalog.api.PriceListSet;
 import org.killbill.billing.catalog.api.ProductCategory;
@@ -112,8 +113,11 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
             }
             final DateTime effectiveDate = requestedDate;
 
+            final CallContext callContext = internalCallContextFactory.createCallContext(context);
             final Catalog catalog = catalogService.getFullCatalog(context);
-            final Plan plan = catalog.findPlan(spec.getProductName(), spec.getBillingPeriod(), realPriceList, overrides, requestedDate);
+            final PlanPhasePriceOverridesWithCallContext overridesWithContext = new DefaultPlanPhasePriceOverridesWithCallContext(overrides, callContext);
+
+            final Plan plan = catalog.findPlan(spec.getProductName(), spec.getBillingPeriod(), realPriceList, overridesWithContext, requestedDate);
             final PlanPhase phase = plan.getAllPhases()[0];
             if (phase == null) {
                 throw new SubscriptionBaseError(String.format("No initial PlanPhase for Product %s, term %s and set %s does not exist in the catalog",
@@ -127,7 +131,6 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
 
             final DefaultSubscriptionBase baseSubscription = (DefaultSubscriptionBase) dao.getBaseSubscription(bundleId, context);
             final DateTime bundleStartDate = getBundleStartDateWithSanity(bundleId, baseSubscription, plan, requestedDate, effectiveDate, context);
-            final CallContext callContext = internalCallContextFactory.createCallContext(context);
             return apiService.createPlan(new SubscriptionBuilder()
                                                  .setId(UUID.randomUUID())
                                                  .setBundleId(bundleId)
@@ -397,8 +400,10 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
             final PlanPhaseSpecifier inputSpec = dryRunArguments.getPlanPhaseSpecifier();
             final String realPriceList = (inputSpec != null && inputSpec.getPriceListName() != null) ? inputSpec.getPriceListName() : PriceListSet.DEFAULT_PRICELIST_NAME;
             final Catalog catalog = catalogService.getFullCatalog(context);
+
+            final PlanPhasePriceOverridesWithCallContext overridesWithContext = null; // TODO not supported to dryRun with custom price
             final Plan plan = (inputSpec != null && inputSpec.getProductName() != null && inputSpec.getBillingPeriod() != null) ?
-                              catalog.findPlan(inputSpec.getProductName(), inputSpec.getBillingPeriod(), realPriceList, dryRunArguments.getPlanPhasePriceoverrides(), utcNow) : null;
+                              catalog.findPlan(inputSpec.getProductName(), inputSpec.getBillingPeriod(), realPriceList, overridesWithContext, utcNow) : null;
             final TenantContext tenantContext = internalCallContextFactory.createTenantContext(context);
 
             if (dryRunArguments != null) {
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java b/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java
index 0b19c8c..cf1be9b 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java
@@ -38,6 +38,7 @@ import org.killbill.billing.catalog.api.Plan;
 import org.killbill.billing.catalog.api.PlanChangeResult;
 import org.killbill.billing.catalog.api.PlanPhase;
 import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
+import org.killbill.billing.catalog.api.PlanPhasePriceOverridesWithCallContext;
 import org.killbill.billing.catalog.api.PlanPhaseSpecifier;
 import org.killbill.billing.catalog.api.PlanSpecifier;
 import org.killbill.billing.catalog.api.PriceList;
@@ -49,6 +50,7 @@ import org.killbill.billing.subscription.alignment.PlanAligner;
 import org.killbill.billing.subscription.alignment.TimedPhase;
 import org.killbill.billing.subscription.api.SubscriptionBase;
 import org.killbill.billing.subscription.api.SubscriptionBaseApiService;
+import org.killbill.billing.subscription.api.svcs.DefaultPlanPhasePriceOverridesWithCallContext;
 import org.killbill.billing.subscription.engine.addon.AddonUtils;
 import org.killbill.billing.subscription.engine.dao.SubscriptionDao;
 import org.killbill.billing.subscription.events.SubscriptionBaseEvent;
@@ -118,7 +120,8 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
         try {
             final String realPriceList = (spec.getPriceListName() == null) ? PriceListSet.DEFAULT_PRICELIST_NAME : spec.getPriceListName();
             final InternalTenantContext internalCallContext = createTenantContextFromBundleId(subscription.getBundleId(), context);
-            final Plan plan = catalogService.getFullCatalog(internalCallContext).findPlan(spec.getProductName(), spec.getBillingPeriod(), realPriceList, overrides, effectiveDate);
+            final PlanPhasePriceOverridesWithCallContext overridesWithContext = new DefaultPlanPhasePriceOverridesWithCallContext(overrides, context);
+            final Plan plan = catalogService.getFullCatalog(internalCallContext).findPlan(spec.getProductName(), spec.getBillingPeriod(), realPriceList, overridesWithContext, effectiveDate);
             final PlanPhase phase = plan.getAllPhases()[0];
             if (phase == null) {
                 throw new SubscriptionBaseError(String.format("No initial PlanPhase for Product %s, term %s and set %s does not exist in the catalog",
@@ -349,7 +352,8 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
                                   final DateTime effectiveDate,
                                   final CallContext context) throws SubscriptionBaseApiException, CatalogApiException {
         final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
-        final Plan newPlan = catalogService.getFullCatalog(internalCallContext).findPlan(newProductName, newBillingPeriod, newPriceList, overrides, effectiveDate, subscription.getStartDate());
+        final PlanPhasePriceOverridesWithCallContext overridesWithContext = new DefaultPlanPhasePriceOverridesWithCallContext(overrides, context);
+        final Plan newPlan = catalogService.getFullCatalog(internalCallContext).findPlan(newProductName, newBillingPeriod, newPriceList, overridesWithContext, effectiveDate, subscription.getStartDate());
 
         final List<SubscriptionBaseEvent> changeEvents = getEventsOnChangePlan(subscription, newPlan, newPriceList, now, effectiveDate, now, false, internalCallContext);
         dao.changePlan(subscription, changeEvents, internalCallContext);
diff --git a/util/src/main/java/org/killbill/billing/util/cache/TenantCatalogCacheLoader.java b/util/src/main/java/org/killbill/billing/util/cache/TenantCatalogCacheLoader.java
index a3a3130..6a1accf 100644
--- a/util/src/main/java/org/killbill/billing/util/cache/TenantCatalogCacheLoader.java
+++ b/util/src/main/java/org/killbill/billing/util/cache/TenantCatalogCacheLoader.java
@@ -73,7 +73,7 @@ public class TenantCatalogCacheLoader extends BaseCacheLoader {
         }
         try {
             log.info("Loading catalog cache for tenant " + internalTenantContext.getTenantRecordId());
-            return callback.loadCatalog(catalogXMLs);
+            return callback.loadCatalog(catalogXMLs, tenantRecordId);
         } catch (final CatalogApiException e) {
             throw new IllegalStateException(String.format("Failed to de-serialize catalog for tenant %s : %s",
                                                           internalTenantContext.getTenantRecordId(), e.getMessage()), e);
@@ -82,6 +82,6 @@ public class TenantCatalogCacheLoader extends BaseCacheLoader {
 
     public interface LoaderCallback {
 
-        public Object loadCatalog(final List<String> catalogXMLs) throws CatalogApiException;
+        public Object loadCatalog(final List<String> catalogXMLs, final Long tenantRecordId) throws CatalogApiException;
     }
 }