killbill-memoizeit
Changes
subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseApiService.java 36(+25 -11)
subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java 196(+117 -79)
subscription/src/main/java/org/killbill/billing/subscription/api/timeline/DefaultSubscriptionBaseTimelineApi.java 13(+9 -4)
subscription/src/main/java/org/killbill/billing/subscription/api/transfer/DefaultSubscriptionBaseTransferApi.java 31(+17 -14)
subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java 206(+112 -94)
subscription/src/main/java/org/killbill/billing/subscription/engine/addon/AddonUtils.java 25(+12 -13)
subscription/src/main/java/org/killbill/billing/subscription/engine/core/DefaultSubscriptionBaseService.java 26(+17 -9)
subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java 111(+50 -61)
subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java 27(+14 -13)
subscription/src/test/java/org/killbill/billing/subscription/alignment/TestPlanAligner.java 44(+22 -22)
subscription/src/test/java/org/killbill/billing/subscription/api/transfer/TestDefaultSubscriptionTransferApi.java 6(+4 -2)
Details
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 1bf7beb..1ce9758 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
@@ -53,11 +53,9 @@ import com.google.common.collect.Iterables;
*/
public class PlanAligner extends BaseAligner {
- private final CatalogInternalApi catalogInternalApi;
@Inject
- public PlanAligner(final CatalogInternalApi catalogInternalApi) {
- this.catalogInternalApi = catalogInternalApi;
+ public PlanAligner() {
}
private enum WhichPhase {
@@ -84,12 +82,14 @@ public class PlanAligner extends BaseAligner {
@Nullable final PhaseType initialPhase,
final String priceList,
final DateTime effectiveDate,
+ final Catalog catalog,
final InternalTenantContext context) throws CatalogApiException, SubscriptionBaseApiException {
final List<TimedPhase> timedPhases = getTimedPhaseOnCreate(alignStartDate,
bundleStartDate,
plan,
initialPhase,
effectiveDate,
+ catalog,
context);
final TimedPhase[] result = new TimedPhase[2];
result[0] = getTimedPhase(timedPhases, effectiveDate, WhichPhase.CURRENT);
@@ -113,9 +113,10 @@ public class PlanAligner extends BaseAligner {
final Plan plan,
final DateTime effectiveDate,
final PhaseType newPlanInitialPhaseType,
+ final Catalog catalog,
final InternalTenantContext context) throws CatalogApiException, SubscriptionBaseApiException {
- return getTimedPhaseOnChange(subscription, plan, effectiveDate, newPlanInitialPhaseType, WhichPhase.CURRENT, context);
+ return getTimedPhaseOnChange(subscription, plan, effectiveDate, newPlanInitialPhaseType, WhichPhase.CURRENT, catalog, context);
}
/**
@@ -134,8 +135,9 @@ public class PlanAligner extends BaseAligner {
final Plan plan,
final DateTime effectiveDate,
final PhaseType newPlanInitialPhaseType,
+ final Catalog catalog,
final InternalTenantContext context) throws CatalogApiException, SubscriptionBaseApiException {
- return getTimedPhaseOnChange(subscription, plan, effectiveDate, newPlanInitialPhaseType, WhichPhase.NEXT, context);
+ return getTimedPhaseOnChange(subscription, plan, effectiveDate, newPlanInitialPhaseType, WhichPhase.NEXT, catalog, context);
}
/**
@@ -144,7 +146,7 @@ public class PlanAligner extends BaseAligner {
* @param subscription the subscription for which we need to compute the next Phase event
* @return the next phase
*/
- public TimedPhase getNextTimedPhase(final DefaultSubscriptionBase subscription, final DateTime effectiveDate, final InternalTenantContext context) {
+ public TimedPhase getNextTimedPhase(final DefaultSubscriptionBase subscription, final DateTime effectiveDate, final Catalog catalog, final InternalTenantContext context) {
try {
final SubscriptionBaseTransition pendingOrLastPlanTransition;
@@ -163,6 +165,7 @@ public class PlanAligner extends BaseAligner {
pendingOrLastPlanTransition.getNextPlan(),
pendingOrLastPlanTransition.getNextPhase().getPhaseType(),
effectiveDate,
+ catalog,
context);
return getTimedPhase(timedPhases, effectiveDate, WhichPhase.NEXT);
case CHANGE:
@@ -176,6 +179,7 @@ public class PlanAligner extends BaseAligner {
subscription.getAllTransitions().get(0).getNextPhase().getPhaseType(),
null,
WhichPhase.NEXT,
+ catalog,
context);
default:
throw new SubscriptionBaseError(String.format("Unexpected initial transition %s for current plan %s on subscription %s",
@@ -191,10 +195,9 @@ public class PlanAligner extends BaseAligner {
final Plan plan,
@Nullable final PhaseType initialPhase,
final DateTime effectiveDate,
+ final Catalog catalog,
final InternalTenantContext context)
throws CatalogApiException, SubscriptionBaseApiException {
- final Catalog catalog = catalogInternalApi.getFullCatalog(true, true, context);
-
final PlanSpecifier planSpecifier = new PlanSpecifier(plan.getName());
final DateTime planStartDate;
@@ -218,6 +221,7 @@ public class PlanAligner extends BaseAligner {
final DateTime effectiveDate,
final PhaseType newPlanInitialPhaseType,
final WhichPhase which,
+ final Catalog catalog,
final InternalTenantContext context) throws CatalogApiException, SubscriptionBaseApiException {
final SubscriptionBaseTransition pendingOrLastPlanTransition;
if (subscription.getState() == EntitlementState.PENDING) {
@@ -236,6 +240,7 @@ public class PlanAligner extends BaseAligner {
subscription.getAllTransitions().get(0).getNextPhase().getPhaseType(),
newPlanInitialPhaseType,
which,
+ catalog,
context);
}
@@ -249,8 +254,8 @@ public class PlanAligner extends BaseAligner {
final PhaseType originalInitialPhase,
@Nullable final PhaseType newPlanInitialPhaseType,
final WhichPhase which,
+ final Catalog catalog,
final InternalTenantContext context) throws CatalogApiException, SubscriptionBaseApiException {
- final Catalog catalog = catalogInternalApi.getFullCatalog(true, true, context);
final PlanPhaseSpecifier fromPlanPhaseSpecifier = new PlanPhaseSpecifier(currentPlan.getName(),
currentPhase.getPhaseType());
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionApiBase.java b/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionApiBase.java
index 0d28e58..82cc967 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionApiBase.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionApiBase.java
@@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.List;
import org.killbill.billing.callcontext.InternalTenantContext;
+import org.killbill.billing.catalog.api.Catalog;
import org.killbill.billing.catalog.api.CatalogApiException;
import org.killbill.billing.catalog.api.CatalogInternalApi;
import org.killbill.billing.subscription.api.user.DefaultSubscriptionBase;
@@ -37,15 +38,12 @@ public class SubscriptionApiBase {
protected final SubscriptionBaseApiService apiService;
protected final Clock clock;
- protected final CatalogInternalApi catalogInternalApi;
- public SubscriptionApiBase(final SubscriptionDao dao, final SubscriptionBaseApiService apiService, final Clock clock, final CatalogInternalApi catalogInternalApi) {
+ public SubscriptionApiBase(final SubscriptionDao dao, final SubscriptionBaseApiService apiService, final Clock clock) {
this.dao = dao;
this.apiService = apiService;
this.clock = clock;
- this.catalogInternalApi = catalogInternalApi;
}
-
protected List<SubscriptionBase> createSubscriptionsForApiUse(final List<SubscriptionBase> internalSubscriptions) {
return new ArrayList<SubscriptionBase>(Collections2.transform(internalSubscriptions, new Function<SubscriptionBase, SubscriptionBase>() {
@Override
@@ -59,10 +57,10 @@ public class SubscriptionApiBase {
return new DefaultSubscriptionBase((DefaultSubscriptionBase) internalSubscription, apiService, clock);
}
- protected DefaultSubscriptionBase createSubscriptionForApiUse(SubscriptionBuilder builder, List<SubscriptionBaseEvent> events, final InternalTenantContext context) throws CatalogApiException {
+ protected DefaultSubscriptionBase createSubscriptionForApiUse(SubscriptionBuilder builder, List<SubscriptionBaseEvent> events, final Catalog catalog, final InternalTenantContext context) throws CatalogApiException {
final DefaultSubscriptionBase subscription = new DefaultSubscriptionBase(builder, apiService, clock);
if (events.size() > 0) {
- subscription.rebuildTransitions(events, catalogInternalApi.getFullCatalog(true, true, context));
+ subscription.rebuildTransitions(events, catalog);
}
return subscription;
}
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseApiService.java b/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseApiService.java
index d02731d..4d304a4 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseApiService.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/SubscriptionBaseApiService.java
@@ -25,6 +25,7 @@ import org.joda.time.DateTime;
import org.killbill.billing.callcontext.InternalCallContext;
import org.killbill.billing.callcontext.InternalTenantContext;
import org.killbill.billing.catalog.api.BillingActionPolicy;
+import org.killbill.billing.catalog.api.Catalog;
import org.killbill.billing.catalog.api.CatalogApiException;
import org.killbill.billing.catalog.api.PhaseType;
import org.killbill.billing.catalog.api.Plan;
@@ -42,11 +43,11 @@ import org.killbill.billing.util.callcontext.TenantContext;
public interface SubscriptionBaseApiService {
public DefaultSubscriptionBase createPlan(SubscriptionBuilder builder, Plan plan, PhaseType initialPhase,
- String realPriceList, DateTime effectiveDate, DateTime processedDate,
- CallContext context)
+ String realPriceList, DateTime effectiveDate,
+ Catalog catalog, CallContext context)
throws SubscriptionBaseApiException;
- public List<SubscriptionBaseWithAddOns> createPlansWithAddOns(UUID accountId, Iterable<SubscriptionAndAddOnsSpecifier> subscriptionsAndAddOns, CallContext context)
+ public List<SubscriptionBaseWithAddOns> createPlansWithAddOns(UUID accountId, Iterable<SubscriptionAndAddOnsSpecifier> subscriptionsAndAddOns, Catalog catalog, CallContext context)
throws SubscriptionBaseApiException;
public boolean cancel(DefaultSubscriptionBase subscription, CallContext context)
@@ -58,7 +59,7 @@ public interface SubscriptionBaseApiService {
public boolean cancelWithPolicy(DefaultSubscriptionBase subscription, BillingActionPolicy policy, int accountBillCycleDayLocal, CallContext context)
throws SubscriptionBaseApiException;
- public boolean cancelWithPolicyNoValidation(Iterable<DefaultSubscriptionBase> subscriptions, BillingActionPolicy policy, int accountBillCycleDayLocal, InternalCallContext context)
+ public boolean cancelWithPolicyNoValidationAndCatalog(Iterable<DefaultSubscriptionBase> subscriptions, BillingActionPolicy policy, int accountBillCycleDayLocal, Catalog catalog, InternalCallContext context)
throws SubscriptionBaseApiException;
public boolean uncancel(DefaultSubscriptionBase subscription, CallContext context)
@@ -81,25 +82,38 @@ public interface SubscriptionBaseApiService {
List<PlanPhasePriceOverride> overrides, BillingActionPolicy policy, CallContext context)
throws SubscriptionBaseApiException;
- public int handleBasePlanEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, final CallContext context) throws CatalogApiException;
+ public int handleBasePlanEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, Catalog fullCatalog, final CallContext context) throws CatalogApiException;
public PlanChangeResult getPlanChangeResult(final DefaultSubscriptionBase subscription, PlanSpecifier spec, final DateTime effectiveDate, TenantContext context) throws SubscriptionBaseApiException;
//
// Lower level APIs for dryRun functionality
//
- public List<SubscriptionBaseEvent> getEventsOnCreation(UUID bundleId, UUID subscriptionId, DateTime alignStartDate, DateTime bundleStartDate,
+
+ public List<SubscriptionBaseEvent> getEventsOnCreation(UUID subscriptionId, DateTime alignStartDate, DateTime bundleStartDate,
Plan plan, PhaseType initialPhase,
- String realPriceList, DateTime effectiveDate, DateTime processedDate,
+ String realPriceList, DateTime effectiveDate,
+ Catalog fullCatalog,
InternalTenantContext context)
throws CatalogApiException, SubscriptionBaseApiException;
+ /*
+ public List<SubscriptionBaseEvent> getEventsOnChangePlan(final DefaultSubscriptionBase subscription, final Plan newPlan,
+ final String newPriceList, final DateTime effectiveDate,
+ final boolean addCancellationAddOnForEventsIfRequired, final InternalTenantContext internalTenantContext) throws CatalogApiException, SubscriptionBaseApiException {
+
+ */
+
public List<SubscriptionBaseEvent> getEventsOnChangePlan(DefaultSubscriptionBase subscription, Plan newPlan,
- String newPriceList, DateTime effectiveDate, DateTime processedDate,
- boolean addCancellationAddOnForEventsIfRequired, InternalTenantContext context)
+ String newPriceList, DateTime effectiveDate,
+ boolean addCancellationAddOnForEventsIfRequired,
+ final Catalog fullCatalog,
+ InternalTenantContext context)
throws CatalogApiException, SubscriptionBaseApiException;
public List<SubscriptionBaseEvent> getEventsOnCancelPlan(final DefaultSubscriptionBase subscription,
- final DateTime effectiveDate, final DateTime processedDate,
- final boolean addCancellationAddOnForEventsIfRequired, final InternalTenantContext internalTenantContext) throws CatalogApiException;
+ final DateTime effectiveDate,
+ final boolean addCancellationAddOnForEventsIfRequired,
+ final Catalog fullCatalog,
+ final InternalTenantContext internalTenantContext) throws CatalogApiException;
}
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 17e695d..7c6384d 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
@@ -115,8 +115,8 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
private final AddonUtils addonUtils;
private final InternalCallContextFactory internalCallContextFactory;
-
private final NotificationQueueService notificationQueueService;
+ private final CatalogInternalApi catalogInternalApi;
public static final Comparator<SubscriptionBase> SUBSCRIPTIONS_COMPARATOR = new Comparator<SubscriptionBase>() {
@@ -140,10 +140,11 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
final CatalogInternalApi catalogInternalApi,
final AddonUtils addonUtils,
final InternalCallContextFactory internalCallContextFactory) {
- super(dao, apiService, clock, catalogInternalApi);
+ super(dao, apiService, clock);
this.addonUtils = addonUtils;
this.internalCallContextFactory = internalCallContextFactory;
this.notificationQueueService = notificationQueueService;
+ this.catalogInternalApi = catalogInternalApi;
}
@Override
@@ -173,7 +174,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_NO_BUNDLE, bundleId);
}
- final DefaultSubscriptionBase baseSubscription = (DefaultSubscriptionBase) dao.getBaseSubscription(bundleId, context);
+ final DefaultSubscriptionBase baseSubscription = (DefaultSubscriptionBase) dao.getBaseSubscription(bundleId, catalog, context);
// verify the number of subscriptions (of the same kind) allowed per bundle
if (ProductCategory.ADD_ON.toString().equalsIgnoreCase(plan.getProduct().getCategory().toString())) {
@@ -186,7 +187,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
}
}
- final DateTime bundleStartDate = getBundleStartDateWithSanity(bundleId, baseSubscription, plan, effectiveDate, context);
+ final DateTime bundleStartDate = getBundleStartDateWithSanity(bundleId, baseSubscription, plan, effectiveDate, catalog, context);
return apiService.createPlan(new SubscriptionBuilder()
.setId(UUIDs.randomUUID())
.setBundleId(bundleId)
@@ -195,7 +196,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
.setBundleStartDate(bundleStartDate)
.setAlignStartDate(effectiveDate)
.setMigrated(isMigrated),
- plan, spec.getPhaseType(), plan.getPriceListName(), effectiveDate, now, callContext);
+ plan, spec.getPhaseType(), plan.getPriceListName(), effectiveDate, catalog, callContext);
} catch (final CatalogApiException e) {
throw new SubscriptionBaseApiException(e);
}
@@ -303,7 +304,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
bundle = createBundleForAccount(accountId, entitlementWithAddOnsSpecifier.getExternalKey(), context);
} else {
final List<SubscriptionBaseBundle> existingBundles = dao.getSubscriptionBundlesForKey(entitlementWithAddOnsSpecifier.getExternalKey(), context);
- final SubscriptionBaseBundle tmp = getActiveBundleForKeyNotException(existingBundles, dao, clock, context);
+ final SubscriptionBaseBundle tmp = getActiveBundleForKeyNotException(existingBundles, dao, clock, catalog, context);
if (tmp == null) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_NO_BP, entitlementWithAddOnsSpecifier.getExternalKey());
} else if (!tmp.getAccountId().equals(accountId)) {
@@ -329,7 +330,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
subscriptionAndAddOns.add(subscriptionAndAddOnsSpecifier);
}
- return apiService.createPlansWithAddOns(accountId, subscriptionAndAddOns, callContext);
+ return apiService.createPlansWithAddOns(accountId, subscriptionAndAddOns, catalog, callContext);
} catch (final CatalogApiException e) {
throw new SubscriptionBaseApiException(e);
}
@@ -356,61 +357,76 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
@Override
public void cancelBaseSubscriptions(final Iterable<SubscriptionBase> subscriptions, final BillingActionPolicy policy, int accountBillCycleDayLocal, final InternalCallContext context) throws SubscriptionBaseApiException {
- apiService.cancelWithPolicyNoValidation(Iterables.<SubscriptionBase, DefaultSubscriptionBase>transform(subscriptions,
- new Function<SubscriptionBase, DefaultSubscriptionBase>() {
- @Override
- public DefaultSubscriptionBase apply(final SubscriptionBase subscriptionBase) {
- try {
- return getDefaultSubscriptionBase(subscriptionBase, context);
- } catch (final CatalogApiException e) {
- throw new RuntimeException(e);
+
+ try {
+ final Catalog catalog = catalogInternalApi.getFullCatalog(true, true, context);
+ apiService.cancelWithPolicyNoValidationAndCatalog(Iterables.<SubscriptionBase, DefaultSubscriptionBase>transform(subscriptions,
+ new Function<SubscriptionBase, DefaultSubscriptionBase>() {
+ @Override
+ public DefaultSubscriptionBase apply(final SubscriptionBase subscriptionBase) {
+ try {
+ return getDefaultSubscriptionBase(subscriptionBase, catalog, context);
+ } catch (final CatalogApiException e) {
+ throw new RuntimeException(e);
+ }
}
- }
- }),
- policy,
- accountBillCycleDayLocal,
- context);
+ }),
+ policy,
+ accountBillCycleDayLocal,
+ catalog,
+ context);
+ } catch (CatalogApiException e) {
+ throw new SubscriptionBaseApiException(e);
+ }
+
}
@Override
public SubscriptionBaseBundle createBundleForAccount(final UUID accountId, final String bundleKey, final InternalCallContext context) throws SubscriptionBaseApiException {
- final List<SubscriptionBaseBundle> existingBundles = dao.getSubscriptionBundlesForKey(bundleKey, context);
+ try {
+ final Catalog catalog = catalogInternalApi.getFullCatalog(true, true, context);
- //
- // Because the creation of the SubscriptionBundle is not atomic (with creation of Subscription/SubscriptionEvent), we verify if we were left
- // with an empty SubscriptionBaseBundle form a past failing operation (See #684). We only allow reuse if such SubscriptionBaseBundle is fully
- // empty (and don't allow use case where all Subscription are cancelled, which is the condition for that key to be re-used)
- // Such condition should have been checked upstream (to decide whether that key is valid or not)
- //
- final SubscriptionBaseBundle existingBundleForAccount = Iterables.tryFind(existingBundles, new Predicate<SubscriptionBaseBundle>() {
- @Override
- public boolean apply(final SubscriptionBaseBundle input) {
- return input.getAccountId().equals(accountId);
- }
- }).orNull();
+ final List<SubscriptionBaseBundle> existingBundles = dao.getSubscriptionBundlesForKey(bundleKey, context);
- // If Bundle already exists, and there is 0 Subscription, we reuse
- if (existingBundleForAccount != null) {
- try {
- final Map<UUID, List<SubscriptionBase>> accountSubscriptions = dao.getSubscriptionsForAccount(context);
- final List<SubscriptionBase> subscriptions = accountSubscriptions.get(existingBundleForAccount.getId());
- if (subscriptions == null || subscriptions.size() == 0) {
- return existingBundleForAccount;
+ //
+ // Because the creation of the SubscriptionBundle is not atomic (with creation of Subscription/SubscriptionEvent), we verify if we were left
+ // with an empty SubscriptionBaseBundle form a past failing operation (See #684). We only allow reuse if such SubscriptionBaseBundle is fully
+ // empty (and don't allow use case where all Subscription are cancelled, which is the condition for that key to be re-used)
+ // Such condition should have been checked upstream (to decide whether that key is valid or not)
+ //
+ final SubscriptionBaseBundle existingBundleForAccount = Iterables.tryFind(existingBundles, new Predicate<SubscriptionBaseBundle>() {
+ @Override
+ public boolean apply(final SubscriptionBaseBundle input) {
+ return input.getAccountId().equals(accountId);
+ }
+ }).orNull();
+
+ // If Bundle already exists, and there is 0 Subscription, we reuse
+ if (existingBundleForAccount != null) {
+ try {
+ final Map<UUID, List<SubscriptionBase>> accountSubscriptions = dao.getSubscriptionsForAccount(catalog, context);
+ final List<SubscriptionBase> subscriptions = accountSubscriptions.get(existingBundleForAccount.getId());
+ if (subscriptions == null || subscriptions.size() == 0) {
+ return existingBundleForAccount;
+ }
+ } catch (final CatalogApiException e) {
+ throw new SubscriptionBaseApiException(e);
}
- } catch (final CatalogApiException e) {
- throw new SubscriptionBaseApiException(e);
}
- }
- final DateTime now = clock.getUTCNow();
- final DateTime originalCreatedDate = !existingBundles.isEmpty() ? existingBundles.get(0).getCreatedDate() : now;
- final DefaultSubscriptionBaseBundle bundle = new DefaultSubscriptionBaseBundle(bundleKey, accountId, now, originalCreatedDate, now, now);
+ final DateTime now = clock.getUTCNow();
+ final DateTime originalCreatedDate = !existingBundles.isEmpty() ? existingBundles.get(0).getCreatedDate() : now;
+ final DefaultSubscriptionBaseBundle bundle = new DefaultSubscriptionBaseBundle(bundleKey, accountId, now, originalCreatedDate, now, now);
+
+ if (null != bundleKey && bundleKey.length() > 255) {
+ throw new SubscriptionBaseApiException(ErrorCode.EXTERNAL_KEY_LIMIT_EXCEEDED);
+ }
+ return dao.createSubscriptionBundle(bundle, context);
- if (null != bundleKey && bundleKey.length() > 255) {
- throw new SubscriptionBaseApiException(ErrorCode.EXTERNAL_KEY_LIMIT_EXCEEDED);
+ } catch (CatalogApiException e) {
+ throw new SubscriptionBaseApiException(e);
}
- return dao.createSubscriptionBundle(bundle, context);
}
@Override
@@ -470,11 +486,11 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
return dao.getNonAOSubscriptionIdsForKey(bundleKey, context);
}
- public static SubscriptionBaseBundle getActiveBundleForKeyNotException(final Iterable<SubscriptionBaseBundle> existingBundles, final SubscriptionDao dao, final Clock clock, final InternalTenantContext context) {
+ public static SubscriptionBaseBundle getActiveBundleForKeyNotException(final Iterable<SubscriptionBaseBundle> existingBundles, final SubscriptionDao dao, final Clock clock, final Catalog catalog, final InternalTenantContext context) {
for (final SubscriptionBaseBundle cur : existingBundles) {
final List<SubscriptionBase> subscriptions;
try {
- subscriptions = dao.getSubscriptions(cur.getId(), ImmutableList.<SubscriptionBaseEvent>of(), context);
+ subscriptions = dao.getSubscriptions(cur.getId(), ImmutableList.<SubscriptionBaseEvent>of(), catalog, context);
for (final SubscriptionBase s : subscriptions) {
if (s.getCategory() == ProductCategory.ADD_ON) {
continue;
@@ -497,12 +513,15 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
final InternalTenantContext context) throws SubscriptionBaseApiException {
try {
+
+ final Catalog catalog = catalogInternalApi.getFullCatalog(true, true, context);
+
final List<SubscriptionBaseEvent> outputDryRunEvents = new ArrayList<SubscriptionBaseEvent>();
final List<SubscriptionBase> outputSubscriptions = new ArrayList<SubscriptionBase>();
- populateDryRunEvents(bundleId, dryRunArguments, outputDryRunEvents, outputSubscriptions, context);
+ populateDryRunEvents(bundleId, dryRunArguments, outputDryRunEvents, outputSubscriptions, catalog, context);
final List<SubscriptionBase> result;
- result = dao.getSubscriptions(bundleId, outputDryRunEvents, context);
+ result = dao.getSubscriptions(bundleId, outputDryRunEvents, catalog, context);
if (result != null && !result.isEmpty()) {
outputSubscriptions.addAll(result);
}
@@ -517,7 +536,9 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
@Override
public Map<UUID, List<SubscriptionBase>> getSubscriptionsForAccount(final InternalTenantContext context) throws SubscriptionBaseApiException {
try {
- final Map<UUID, List<SubscriptionBase>> internalSubscriptions = dao.getSubscriptionsForAccount(context);
+ final Catalog catalog = catalogInternalApi.getFullCatalog(true, true, context);
+
+ final Map<UUID, List<SubscriptionBase>> internalSubscriptions = dao.getSubscriptionsForAccount(catalog, context);
final Map<UUID, List<SubscriptionBase>> result = new HashMap<UUID, List<SubscriptionBase>>();
for (final UUID bundleId : internalSubscriptions.keySet()) {
result.put(bundleId, createSubscriptionsForApiUse(internalSubscriptions.get(bundleId)));
@@ -531,7 +552,9 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
@Override
public SubscriptionBase getBaseSubscription(final UUID bundleId, final InternalTenantContext context) throws SubscriptionBaseApiException {
try {
- final SubscriptionBase result = dao.getBaseSubscription(bundleId, context);
+ final Catalog catalog = catalogInternalApi.getFullCatalog(true, true, context);
+
+ final SubscriptionBase result = dao.getBaseSubscription(bundleId, catalog, context);
if (result == null) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_GET_NO_SUCH_BASE_SUBSCRIPTION, bundleId);
}
@@ -544,7 +567,10 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
@Override
public SubscriptionBase getSubscriptionFromId(final UUID id, final InternalTenantContext context) throws SubscriptionBaseApiException {
try {
- final SubscriptionBase result = dao.getSubscriptionFromId(id, context);
+
+ final Catalog catalog = catalogInternalApi.getFullCatalog(true, true, context);
+
+ final SubscriptionBase result = dao.getSubscriptionFromId(id, catalog, context);
if (result == null) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_INVALID_SUBSCRIPTION_ID, id);
}
@@ -571,7 +597,10 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
@Override
public void setChargedThroughDate(final UUID subscriptionId, final DateTime chargedThruDate, final InternalCallContext context) throws SubscriptionBaseApiException {
try {
- final DefaultSubscriptionBase subscription = (DefaultSubscriptionBase) dao.getSubscriptionFromId(subscriptionId, context);
+
+ final Catalog catalog = catalogInternalApi.getFullCatalog(true, true, context);
+
+ final DefaultSubscriptionBase subscription = (DefaultSubscriptionBase) dao.getSubscriptionFromId(subscriptionId, catalog, context);
final SubscriptionBuilder builder = new SubscriptionBuilder(subscription)
.setChargedThroughDate(chargedThruDate);
@@ -625,7 +654,10 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
@Override
public List<EntitlementAOStatusDryRun> getDryRunChangePlanStatus(final UUID subscriptionId, @Nullable final String baseProductName, final DateTime requestedDate, final InternalTenantContext context) throws SubscriptionBaseApiException {
try {
- final SubscriptionBase subscription = dao.getSubscriptionFromId(subscriptionId, context);
+
+ final Catalog catalog = catalogInternalApi.getFullCatalog(true, true, context);
+
+ final SubscriptionBase subscription = dao.getSubscriptionFromId(subscriptionId, catalog, context);
if (subscription == null) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_INVALID_SUBSCRIPTION_ID, subscriptionId);
}
@@ -635,7 +667,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
final List<EntitlementAOStatusDryRun> result = new LinkedList<EntitlementAOStatusDryRun>();
- final List<SubscriptionBase> bundleSubscriptions = dao.getSubscriptions(subscription.getBundleId(), ImmutableList.<SubscriptionBaseEvent>of(), context);
+ final List<SubscriptionBase> bundleSubscriptions = dao.getSubscriptions(subscription.getBundleId(), ImmutableList.<SubscriptionBaseEvent>of(), catalog, context);
for (final SubscriptionBase cur : bundleSubscriptions) {
if (cur.getId().equals(subscriptionId)) {
continue;
@@ -648,9 +680,9 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
final DryRunChangeReason reason;
// If baseProductName is null, it's a cancellation dry-run. In this case, return all addons, so they are cancelled
- if (baseProductName != null && addonUtils.isAddonIncludedFromProdName(baseProductName, cur.getCurrentPlan(), requestedDate, context)) {
+ if (baseProductName != null && addonUtils.isAddonIncludedFromProdName(baseProductName, cur.getCurrentPlan(), requestedDate, catalog, context)) {
reason = DryRunChangeReason.AO_INCLUDED_IN_NEW_PLAN;
- } else if (baseProductName != null && addonUtils.isAddonAvailableFromProdName(baseProductName, cur.getCurrentPlan(), requestedDate, context)) {
+ } else if (baseProductName != null && addonUtils.isAddonAvailableFromProdName(baseProductName, cur.getCurrentPlan(), requestedDate, catalog, context)) {
reason = DryRunChangeReason.AO_AVAILABLE_IN_NEW_PLAN;
} else {
reason = DryRunChangeReason.AO_NOT_AVAILABLE_IN_NEW_PLAN;
@@ -678,6 +710,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
@Nullable final DryRunArguments dryRunArguments,
final Collection<SubscriptionBaseEvent> outputDryRunEvents,
final Collection<SubscriptionBase> outputSubscriptions,
+ final Catalog catalog,
final InternalTenantContext context) throws SubscriptionBaseApiException {
if (dryRunArguments == null || dryRunArguments.getAction() == null) {
return;
@@ -689,7 +722,6 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
final PlanPhaseSpecifier inputSpec = dryRunArguments.getPlanPhaseSpecifier();
final boolean isInputSpecNullOrEmpty = inputSpec == null ||
(inputSpec.getPlanName() == null && inputSpec.getProductName() == null && inputSpec.getBillingPeriod() == null);
- final Catalog catalog = catalogInternalApi.getFullCatalog(true, true, context);
// Create an overridesWithContext with a null context to indicate this is dryRun and no price overriden plan should be created.
final PlanPhasePriceOverridesWithCallContext overridesWithContext = new DefaultPlanPhasePriceOverridesWithCallContext(dryRunArguments.getPlanPhasePriceOverrides(), null);
@@ -701,12 +733,12 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
switch (dryRunArguments.getAction()) {
case START_BILLING:
- final DefaultSubscriptionBase baseSubscription = (DefaultSubscriptionBase) dao.getBaseSubscription(bundleId, context);
+ final DefaultSubscriptionBase baseSubscription = (DefaultSubscriptionBase) dao.getBaseSubscription(bundleId, catalog, context);
final DateTime startEffectiveDate = dryRunArguments.getEffectiveDate() != null ? context.toUTCDateTime(dryRunArguments.getEffectiveDate()) : utcNow;
- final DateTime bundleStartDate = getBundleStartDateWithSanity(bundleId, baseSubscription, plan, startEffectiveDate, context);
+ final DateTime bundleStartDate = getBundleStartDateWithSanity(bundleId, baseSubscription, plan, startEffectiveDate, catalog, context);
final UUID subscriptionId = UUIDs.randomUUID();
- dryRunEvents = apiService.getEventsOnCreation(bundleId, subscriptionId, startEffectiveDate, bundleStartDate, plan, inputSpec.getPhaseType(), plan.getPriceListName(),
- startEffectiveDate, utcNow, context);
+ dryRunEvents = apiService.getEventsOnCreation(subscriptionId, startEffectiveDate, bundleStartDate, plan, inputSpec.getPhaseType(), plan.getPriceListName(),
+ startEffectiveDate, catalog, context);
final SubscriptionBuilder builder = new SubscriptionBuilder()
.setId(subscriptionId)
.setBundleId(bundleId)
@@ -720,7 +752,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
break;
case CHANGE:
- final DefaultSubscriptionBase subscriptionForChange = (DefaultSubscriptionBase) dao.getSubscriptionFromId(dryRunArguments.getSubscriptionId(), context);
+ final DefaultSubscriptionBase subscriptionForChange = (DefaultSubscriptionBase) dao.getSubscriptionFromId(dryRunArguments.getSubscriptionId(), catalog, context);
DateTime changeEffectiveDate = getDryRunEffectiveDate(dryRunArguments.getEffectiveDate(), subscriptionForChange, context);
if (changeEffectiveDate == null) {
@@ -732,11 +764,11 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
// We pass null for billingAlignment, accountTimezone, account BCD because this is not available which means that dryRun with START_OF_TERM BillingPolicy will fail
changeEffectiveDate = subscriptionForChange.getPlanChangeEffectiveDate(policy, null, -1, context);
}
- dryRunEvents = apiService.getEventsOnChangePlan(subscriptionForChange, plan, plan.getPriceListName(), changeEffectiveDate, utcNow, true, context);
+ dryRunEvents = apiService.getEventsOnChangePlan(subscriptionForChange, plan, plan.getPriceListName(), changeEffectiveDate, true, catalog, context);
break;
case STOP_BILLING:
- final DefaultSubscriptionBase subscriptionForCancellation = (DefaultSubscriptionBase) dao.getSubscriptionFromId(dryRunArguments.getSubscriptionId(), context);
+ final DefaultSubscriptionBase subscriptionForCancellation = (DefaultSubscriptionBase) dao.getSubscriptionFromId(dryRunArguments.getSubscriptionId(), catalog, context);
DateTime cancelEffectiveDate = getDryRunEffectiveDate(dryRunArguments.getEffectiveDate(), subscriptionForCancellation, context);
if (dryRunArguments.getEffectiveDate() == null) {
@@ -746,12 +778,11 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
final Plan currentPlan = subscriptionForCancellation.getCurrentPlan();
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier(currentPlan.getName(),
subscriptionForCancellation.getCurrentPhase().getPhaseType());
- policy = catalogInternalApi.getFullCatalog(true, true, context).planCancelPolicy(spec, utcNow);
}
// We pass null for billingAlignment, accountTimezone, account BCD because this is not available which means that dryRun with START_OF_TERM BillingPolicy will fail
cancelEffectiveDate = subscriptionForCancellation.getPlanChangeEffectiveDate(policy, null, -1, context);
}
- dryRunEvents = apiService.getEventsOnCancelPlan(subscriptionForCancellation, cancelEffectiveDate, utcNow, true, context);
+ dryRunEvents = apiService.getEventsOnCancelPlan(subscriptionForCancellation, cancelEffectiveDate, true, catalog, context);
break;
default:
@@ -827,10 +858,17 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
@Override
public void updateBCD(final UUID subscriptionId, final int bcd, @Nullable final LocalDate effectiveFromDate, final InternalCallContext internalCallContext) throws SubscriptionBaseApiException {
- final DefaultSubscriptionBase subscription = (DefaultSubscriptionBase) getSubscriptionFromId(subscriptionId, internalCallContext);
- final DateTime effectiveDate = getEffectiveDateForNewBCD(bcd, effectiveFromDate, internalCallContext);
- final BCDEvent bcdEvent = BCDEventData.createBCDEvent(subscription, effectiveDate, bcd);
- dao.createBCDChangeEvent(subscription, bcdEvent, internalCallContext);
+
+ final Catalog catalog;
+ try {
+ catalog = catalogInternalApi.getFullCatalog(true, true, internalCallContext);
+ final DefaultSubscriptionBase subscription = (DefaultSubscriptionBase) getSubscriptionFromId(subscriptionId, internalCallContext);
+ final DateTime effectiveDate = getEffectiveDateForNewBCD(bcd, effectiveFromDate, internalCallContext);
+ final BCDEvent bcdEvent = BCDEventData.createBCDEvent(subscription, effectiveDate, bcd);
+ dao.createBCDChangeEvent(subscription, bcdEvent, catalog, internalCallContext);
+ } catch (final CatalogApiException e) {
+ throw new SubscriptionBaseApiException(e);
+ }
}
@Override
@@ -878,7 +916,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
}
private DateTime getBundleStartDateWithSanity(final UUID bundleId, @Nullable final DefaultSubscriptionBase baseSubscription, final Plan plan,
- final DateTime effectiveDate, final InternalTenantContext context) throws SubscriptionBaseApiException, CatalogApiException {
+ final DateTime effectiveDate, final Catalog catalog, final InternalTenantContext context) throws SubscriptionBaseApiException, CatalogApiException {
switch (plan.getProduct().getCategory()) {
case BASE:
if (baseSubscription != null &&
@@ -894,7 +932,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
if (effectiveDate.isBefore(baseSubscription.getStartDate())) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_INVALID_REQUESTED_DATE, effectiveDate.toString(), baseSubscription.getStartDate().toString());
}
- addonUtils.checkAddonCreationRights(baseSubscription, plan, effectiveDate, context);
+ addonUtils.checkAddonCreationRights(baseSubscription, plan, effectiveDate, catalog, context);
return baseSubscription.getStartDate();
case STANDALONE:
@@ -922,12 +960,12 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
}
// For forward-compatibility
- private DefaultSubscriptionBase getDefaultSubscriptionBase(final Entity subscriptionBase, final InternalTenantContext context) throws CatalogApiException {
+ private DefaultSubscriptionBase getDefaultSubscriptionBase(final Entity subscriptionBase, final Catalog catalog, final InternalTenantContext context) throws CatalogApiException {
if (subscriptionBase instanceof DefaultSubscriptionBase) {
return (DefaultSubscriptionBase) subscriptionBase;
} else {
// Safe cast, see above
- return (DefaultSubscriptionBase) dao.getSubscriptionFromId(subscriptionBase.getId(), context);
+ return (DefaultSubscriptionBase) dao.getSubscriptionFromId(subscriptionBase.getId(), catalog, context);
}
}
}
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/timeline/DefaultSubscriptionBaseTimelineApi.java b/subscription/src/main/java/org/killbill/billing/subscription/api/timeline/DefaultSubscriptionBaseTimelineApi.java
index e7d5a5a..2ee1a66 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/timeline/DefaultSubscriptionBaseTimelineApi.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/timeline/DefaultSubscriptionBaseTimelineApi.java
@@ -26,6 +26,7 @@ import java.util.UUID;
import org.joda.time.DateTime;
import org.killbill.billing.ErrorCode;
import org.killbill.billing.callcontext.InternalTenantContext;
+import org.killbill.billing.catalog.api.Catalog;
import org.killbill.billing.catalog.api.CatalogApiException;
import org.killbill.billing.catalog.api.CatalogInternalApi;
import org.killbill.billing.subscription.api.SubscriptionApiBase;
@@ -54,7 +55,7 @@ public class DefaultSubscriptionBaseTimelineApi extends SubscriptionApiBase impl
final SubscriptionDao dao,
final InternalCallContextFactory internalCallContextFactory,
final Clock clock) {
- super(dao, apiService, clock, catalogService);
+ super(dao, apiService, clock);
this.catalogInternalApi = catalogService;
this.internalCallContextFactory = internalCallContextFactory;
}
@@ -63,15 +64,19 @@ public class DefaultSubscriptionBaseTimelineApi extends SubscriptionApiBase impl
public BundleBaseTimeline getBundleTimeline(final SubscriptionBaseBundle bundle, final TenantContext context)
throws SubscriptionBaseRepairException {
try {
+
+
final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(bundle.getAccountId(), context);
+ final Catalog fullCatalog = catalogInternalApi.getFullCatalog(true, true, internalTenantContext);
final List<SubscriptionBase> subscriptions = dao.getSubscriptions(bundle.getId(),
ImmutableList.<SubscriptionBaseEvent>of(),
+ fullCatalog,
internalTenantContext);
if (subscriptions.size() == 0) {
throw new SubscriptionBaseRepairException(ErrorCode.SUB_NO_ACTIVE_SUBSCRIPTIONS, bundle.getId());
}
final String viewId = getViewId(((DefaultSubscriptionBaseBundle) bundle).getLastSysUpdateDate(), subscriptions);
- final List<SubscriptionBaseTimeline> repairs = createGetSubscriptionRepairList(subscriptions, Collections.<SubscriptionBaseTimeline>emptyList(), internalTenantContext);
+ final List<SubscriptionBaseTimeline> repairs = createGetSubscriptionRepairList(subscriptions, Collections.<SubscriptionBaseTimeline>emptyList(), fullCatalog, internalTenantContext);
return createGetBundleRepair(bundle.getId(), bundle.getExternalKey(), viewId, repairs);
} catch (CatalogApiException e) {
throw new SubscriptionBaseRepairException(e);
@@ -125,7 +130,7 @@ public class DefaultSubscriptionBaseTimelineApi extends SubscriptionApiBase impl
};
}
- private List<SubscriptionBaseTimeline> createGetSubscriptionRepairList(final List<SubscriptionBase> subscriptions, final List<SubscriptionBaseTimeline> inRepair, final InternalTenantContext tenantContext) throws CatalogApiException {
+ private List<SubscriptionBaseTimeline> createGetSubscriptionRepairList(final List<SubscriptionBase> subscriptions, final List<SubscriptionBaseTimeline> inRepair, final Catalog fullCatalog, final InternalTenantContext tenantContext) throws CatalogApiException {
final List<SubscriptionBaseTimeline> result = new LinkedList<SubscriptionBaseTimeline>();
final Set<UUID> repairIds = new TreeSet<UUID>();
@@ -136,7 +141,7 @@ public class DefaultSubscriptionBaseTimelineApi extends SubscriptionApiBase impl
for (final SubscriptionBase cur : subscriptions) {
if (!repairIds.contains(cur.getId())) {
- result.add(new DefaultSubscriptionBaseTimeline((DefaultSubscriptionBase) cur, catalogInternalApi.getFullCatalog(true, true, tenantContext)));
+ result.add(new DefaultSubscriptionBaseTimeline((DefaultSubscriptionBase) cur, fullCatalog));
}
}
return result;
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/transfer/DefaultSubscriptionBaseTransferApi.java b/subscription/src/main/java/org/killbill/billing/subscription/api/transfer/DefaultSubscriptionBaseTransferApi.java
index bc01cc5..61f34e9 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/transfer/DefaultSubscriptionBaseTransferApi.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/transfer/DefaultSubscriptionBaseTransferApi.java
@@ -71,19 +71,16 @@ public class DefaultSubscriptionBaseTransferApi extends SubscriptionApiBase impl
@Inject
public DefaultSubscriptionBaseTransferApi(final Clock clock, final SubscriptionDao dao, final SubscriptionBaseTimelineApi timelineApi, final CatalogInternalApi catalogInternalApi,
final SubscriptionBaseApiService apiService, final InternalCallContextFactory internalCallContextFactory) {
- super(dao, apiService, clock, catalogInternalApi);
+ super(dao, apiService, clock);
this.catalogInternalApi = catalogInternalApi;
this.timelineApi = timelineApi;
this.internalCallContextFactory = internalCallContextFactory;
}
- private SubscriptionBaseEvent createEvent(final boolean firstEvent, final ExistingEvent existingEvent, final DefaultSubscriptionBase subscription, final DateTime transferDate, final InternalTenantContext context)
+ private SubscriptionBaseEvent createEvent(final boolean firstEvent, final ExistingEvent existingEvent, final DefaultSubscriptionBase subscription, final DateTime transferDate, final Catalog catalog, final InternalTenantContext context)
throws CatalogApiException {
SubscriptionBaseEvent newEvent = null;
-
- final Catalog catalog = catalogInternalApi.getFullCatalog(true, true, context);
-
final DateTime effectiveDate = existingEvent.getEffectiveDate().isBefore(transferDate) ? transferDate : existingEvent.getEffectiveDate();
final PlanPhaseSpecifier spec = existingEvent.getPlanPhaseSpecifier();
@@ -128,9 +125,11 @@ public class DefaultSubscriptionBaseTransferApi extends SubscriptionApiBase impl
@VisibleForTesting
List<SubscriptionBaseEvent> toEvents(final List<ExistingEvent> existingEvents, final DefaultSubscriptionBase subscription,
- final DateTime transferDate, final InternalTenantContext context) throws SubscriptionBaseTransferApiException {
+ final DateTime transferDate, final Catalog catalog, final InternalTenantContext context) throws SubscriptionBaseTransferApiException {
+
try {
+
final List<SubscriptionBaseEvent> result = new LinkedList<SubscriptionBaseEvent>();
SubscriptionBaseEvent event = null;
@@ -145,7 +144,7 @@ public class DefaultSubscriptionBaseTransferApi extends SubscriptionApiBase impl
// Add previous event the first time if needed
if (prevEvent != null) {
- event = createEvent(firstEvent, prevEvent, subscription, transferDate, context);
+ event = createEvent(firstEvent, prevEvent, subscription, transferDate, catalog, context);
if (event != null) {
result.add(event);
firstEvent = false;
@@ -153,7 +152,7 @@ public class DefaultSubscriptionBaseTransferApi extends SubscriptionApiBase impl
prevEvent = null;
}
- event = createEvent(firstEvent, cur, subscription, transferDate, context);
+ event = createEvent(firstEvent, cur, subscription, transferDate, catalog, context);
if (event != null) {
result.add(event);
firstEvent = false;
@@ -162,7 +161,7 @@ public class DefaultSubscriptionBaseTransferApi extends SubscriptionApiBase impl
// Previous loop did not get anything because transferDate is greater than effectiveDate of last event
if (prevEvent != null) {
- event = createEvent(firstEvent, prevEvent, subscription, transferDate, context);
+ event = createEvent(firstEvent, prevEvent, subscription, transferDate, catalog, context);
if (event != null) {
result.add(event);
}
@@ -182,7 +181,11 @@ public class DefaultSubscriptionBaseTransferApi extends SubscriptionApiBase impl
final InternalCallContext fromInternalCallContext = internalCallContextFactory.createInternalCallContext(sourceAccountId, context);
final InternalCallContext toInternalCallContext = internalCallContextFactory.createInternalCallContext(destAccountId, context);
+
try {
+ final Catalog catalog = catalogInternalApi.getFullCatalog(true, true, fromInternalCallContext);
+
+
final DateTime effectiveTransferDate = transferDate == null ? clock.getUTCNow() : transferDate;
if (effectiveTransferDate.isAfter(clock.getUTCNow())) {
// The transfer event for the migrated bundle will be the first one, which cannot be in the future
@@ -191,7 +194,7 @@ public class DefaultSubscriptionBaseTransferApi extends SubscriptionApiBase impl
}
final List<SubscriptionBaseBundle> bundlesForAccountAndKey = dao.getSubscriptionBundlesForAccountAndKey(sourceAccountId, bundleKey, fromInternalCallContext);
- final SubscriptionBaseBundle bundle = DefaultSubscriptionInternalApi.getActiveBundleForKeyNotException(bundlesForAccountAndKey, dao, clock, fromInternalCallContext);
+ final SubscriptionBaseBundle bundle = DefaultSubscriptionInternalApi.getActiveBundleForKeyNotException(bundlesForAccountAndKey, dao, clock, catalog, fromInternalCallContext);
if (bundle == null) {
throw new SubscriptionBaseTransferApiException(ErrorCode.SUB_CREATE_NO_BUNDLE, bundleKey);
}
@@ -208,7 +211,7 @@ public class DefaultSubscriptionBaseTransferApi extends SubscriptionApiBase impl
DateTime bundleStartdate = null;
for (final SubscriptionBaseTimeline cur : bundleBaseTimeline.getSubscriptions()) {
- final DefaultSubscriptionBase oldSubscription = (DefaultSubscriptionBase) dao.getSubscriptionFromId(cur.getId(), fromInternalCallContext);
+ final DefaultSubscriptionBase oldSubscription = (DefaultSubscriptionBase) dao.getSubscriptionFromId(cur.getId(), catalog, fromInternalCallContext);
// Skip already cancelled subscriptions
if (oldSubscription.getState() == EntitlementState.CANCELLED) {
continue;
@@ -251,16 +254,16 @@ public class DefaultSubscriptionBaseTransferApi extends SubscriptionApiBase impl
.setCategory(productCategory)
.setBundleStartDate(effectiveTransferDate)
.setAlignStartDate(subscriptionAlignStartDate),
- ImmutableList.<SubscriptionBaseEvent>of(), fromInternalCallContext);
+ ImmutableList.<SubscriptionBaseEvent>of(), catalog, fromInternalCallContext);
- final List<SubscriptionBaseEvent> events = toEvents(existingEvents, defaultSubscriptionBase, effectiveTransferDate, fromInternalCallContext);
+ final List<SubscriptionBaseEvent> events = toEvents(existingEvents, defaultSubscriptionBase, effectiveTransferDate, catalog, fromInternalCallContext);
final SubscriptionTransferData curData = new SubscriptionTransferData(defaultSubscriptionBase, events, null);
subscriptionTransferDataList.add(curData);
}
BundleTransferData bundleTransferData = new BundleTransferData(subscriptionBundleData, subscriptionTransferDataList);
// Atomically cancelWithRequestedDate all subscription on old account and create new bundle, subscriptions, events for new account
- dao.transfer(sourceAccountId, destAccountId, bundleTransferData, transferCancelDataList, fromInternalCallContext, toInternalCallContext);
+ dao.transfer(sourceAccountId, destAccountId, bundleTransferData, transferCancelDataList, catalog, fromInternalCallContext, toInternalCallContext);
return bundleTransferData.getData();
} catch (SubscriptionBaseRepairException e) {
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 75b46b0..6fd4439 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
@@ -102,7 +102,7 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
@Override
public DefaultSubscriptionBase createPlan(final SubscriptionBuilder builder, final Plan plan, final PhaseType initialPhase,
- final String realPriceList, final DateTime effectiveDate, final DateTime processedDate,
+ final String realPriceList, final DateTime effectiveDate, final Catalog fullCatalog,
final CallContext context) throws SubscriptionBaseApiException {
final DefaultSubscriptionBase subscription = new DefaultSubscriptionBase(builder, this, clock);
@@ -110,10 +110,10 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
try {
- final List<SubscriptionBaseEvent> events = getEventsOnCreation(subscription.getBundleId(), subscription.getId(), subscription.getAlignStartDate(), subscription.getBundleStartDate(),
- plan, initialPhase, realPriceList, effectiveDate, processedDate, internalCallContext);
- dao.createSubscription(subscription, events, internalCallContext);
- subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId(), internalCallContext), catalogInternalApi.getFullCatalog(true, true, internalCallContext));
+ final List<SubscriptionBaseEvent> events = getEventsOnCreation(subscription.getId(), subscription.getAlignStartDate(), subscription.getBundleStartDate(),
+ plan, initialPhase, realPriceList, effectiveDate, fullCatalog, internalCallContext);
+ dao.createSubscription(subscription, events, fullCatalog, internalCallContext);
+ subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId(), internalCallContext), fullCatalog);
return subscription;
} catch (final CatalogApiException e) {
throw new SubscriptionBaseApiException(e);
@@ -121,30 +121,30 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
}
@Override
- public List<SubscriptionBaseWithAddOns> createPlansWithAddOns(final UUID accountId, final Iterable<SubscriptionAndAddOnsSpecifier> subscriptionsAndAddOns, final CallContext context) throws SubscriptionBaseApiException {
+ public List<SubscriptionBaseWithAddOns> createPlansWithAddOns(final UUID accountId, final Iterable<SubscriptionAndAddOnsSpecifier> subscriptionsAndAddOns, final Catalog fullCatalog, final CallContext context) throws SubscriptionBaseApiException {
final Map<UUID, List<SubscriptionBaseEvent>> eventsMap = new HashMap<UUID, List<SubscriptionBaseEvent>>();
final Collection<List<SubscriptionBase>> subscriptionBaseAndAddOnsList = new ArrayList<List<SubscriptionBase>>();
- final List<SubscriptionBaseWithAddOns> allSubscriptions = new ArrayList<SubscriptionBaseWithAddOns>();
- for (final SubscriptionAndAddOnsSpecifier subscriptionAndAddOns : subscriptionsAndAddOns) {
- final List<SubscriptionBase> subscriptionBaseList = new ArrayList<SubscriptionBase>();
- createEvents(subscriptionAndAddOns.getSubscriptionSpecifiers(), context, eventsMap, subscriptionBaseList);
- subscriptionBaseAndAddOnsList.add(subscriptionBaseList);
+ final InternalCallContext internalCallContext = createCallContextFromAccountId(accountId, context);
+ try {
- final SubscriptionBaseWithAddOns subscriptionBaseWithAddOns = new DefaultSubscriptionBaseWithAddOns(subscriptionAndAddOns.getBundleId(),
- subscriptionBaseList,
- subscriptionAndAddOns.getEffectiveDate());
- allSubscriptions.add(subscriptionBaseWithAddOns);
- }
+ final List<SubscriptionBaseWithAddOns> allSubscriptions = new ArrayList<SubscriptionBaseWithAddOns>();
+ for (final SubscriptionAndAddOnsSpecifier subscriptionAndAddOns : subscriptionsAndAddOns) {
+ final List<SubscriptionBase> subscriptionBaseList = new ArrayList<SubscriptionBase>();
+ createEvents(subscriptionAndAddOns.getSubscriptionSpecifiers(), context, eventsMap, subscriptionBaseList, fullCatalog);
+ subscriptionBaseAndAddOnsList.add(subscriptionBaseList);
- final InternalCallContext internalCallContext = createCallContextFromAccountId(accountId, context);
- dao.createSubscriptionsWithAddOns(allSubscriptions, eventsMap, internalCallContext);
+ final SubscriptionBaseWithAddOns subscriptionBaseWithAddOns = new DefaultSubscriptionBaseWithAddOns(subscriptionAndAddOns.getBundleId(),
+ subscriptionBaseList,
+ subscriptionAndAddOns.getEffectiveDate());
+ allSubscriptions.add(subscriptionBaseWithAddOns);
+ }
+
+ dao.createSubscriptionsWithAddOns(allSubscriptions, eventsMap, fullCatalog, internalCallContext);
- try {
for (final List<SubscriptionBase> subscriptions : subscriptionBaseAndAddOnsList) {
for (final SubscriptionBase input : subscriptions) {
- ((DefaultSubscriptionBase) input).rebuildTransitions(dao.getEventsForSubscription(input.getId(), internalCallContext),
- catalogInternalApi.getFullCatalog(true, true, internalCallContext));
+ ((DefaultSubscriptionBase) input).rebuildTransitions(dao.getEventsForSubscription(input.getId(), internalCallContext), fullCatalog);
}
}
return allSubscriptions;
@@ -153,15 +153,15 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
}
}
- private void createEvents(final Iterable<SubscriptionSpecifier> subscriptions, final CallContext context, final Map<UUID, List<SubscriptionBaseEvent>> eventsMap, final Collection<SubscriptionBase> subscriptionBaseList) throws SubscriptionBaseApiException {
+ private void createEvents(final Iterable<SubscriptionSpecifier> subscriptions, final CallContext context, final Map<UUID, List<SubscriptionBaseEvent>> eventsMap, final Collection<SubscriptionBase> subscriptionBaseList, final Catalog fullCatalog) throws SubscriptionBaseApiException {
for (final SubscriptionSpecifier subscription : subscriptions) {
try {
final DefaultSubscriptionBase subscriptionBase = new DefaultSubscriptionBase(subscription.getBuilder(), this, clock);
final InternalCallContext internalCallContext = createCallContextFromBundleId(subscriptionBase.getBundleId(), context);
- final List<SubscriptionBaseEvent> events = getEventsOnCreation(subscriptionBase.getBundleId(), subscriptionBase.getId(), subscriptionBase.getAlignStartDate(),
+ final List<SubscriptionBaseEvent> events = getEventsOnCreation(subscriptionBase.getId(), subscriptionBase.getAlignStartDate(),
subscriptionBase.getBundleStartDate(), subscription.getPlan(),
subscription.getInitialPhase(), subscription.getRealPriceList(),
- subscription.getEffectiveDate(), subscription.getProcessedDate(), internalCallContext);
+ subscription.getEffectiveDate(), fullCatalog, internalCallContext);
eventsMap.put(subscriptionBase.getId(), events);
subscriptionBaseList.add(subscriptionBase);
} catch (final CatalogApiException e) {
@@ -183,13 +183,14 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
try {
final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
- final BillingActionPolicy policy = catalogInternalApi.getFullCatalog(true, true, internalCallContext).planCancelPolicy(planPhase, now);
+ final Catalog fullCatalog = catalogInternalApi.getFullCatalog(true, true, internalCallContext);
+ final BillingActionPolicy policy = fullCatalog.planCancelPolicy(planPhase, now);
Preconditions.checkState(policy != BillingActionPolicy.START_OF_TERM, "A default START_OF_TERM policy is not availaible");
final DateTime effectiveDate = subscription.getPlanChangeEffectiveDate(policy, null, -1, null);
- return doCancelPlan(ImmutableMap.<DefaultSubscriptionBase, DateTime>of(subscription, effectiveDate), now, internalCallContext);
+ return doCancelPlan(ImmutableMap.<DefaultSubscriptionBase, DateTime>of(subscription, effectiveDate), fullCatalog, internalCallContext);
} catch (final CatalogApiException e) {
throw new SubscriptionBaseApiException(e);
}
@@ -201,11 +202,17 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
if (currentState == EntitlementState.CANCELLED) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_CANCEL_BAD_STATE, subscription.getId(), currentState);
}
- final DateTime now = clock.getUTCNow();
- final DateTime effectiveDate = (requestedDateWithMs != null) ? DefaultClock.truncateMs(requestedDateWithMs) : now;
-
final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
- return doCancelPlan(ImmutableMap.<DefaultSubscriptionBase, DateTime>of(subscription, effectiveDate), now, internalCallContext);
+ final Catalog fullCatalog;
+ try {
+ fullCatalog = catalogInternalApi.getFullCatalog(true, true, internalCallContext);
+ final DateTime now = clock.getUTCNow();
+ final DateTime effectiveDate = (requestedDateWithMs != null) ? DefaultClock.truncateMs(requestedDateWithMs) : now;
+
+ return doCancelPlan(ImmutableMap.<DefaultSubscriptionBase, DateTime>of(subscription, effectiveDate), fullCatalog, internalCallContext);
+ } catch (final CatalogApiException e) {
+ throw new SubscriptionBaseApiException(e);
+ }
}
@Override
@@ -216,29 +223,32 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
}
final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
- return cancelWithPolicyNoValidation(ImmutableList.<DefaultSubscriptionBase>of(subscription), policy, accountBillCycleDayLocal, internalCallContext);
+ final Catalog fullCatalog;
+ try {
+ fullCatalog = catalogInternalApi.getFullCatalog(true, true, internalCallContext);
+ return cancelWithPolicyNoValidationAndCatalog(ImmutableList.<DefaultSubscriptionBase>of(subscription), policy, accountBillCycleDayLocal, fullCatalog, internalCallContext);
+ } catch (CatalogApiException e) {
+ throw new SubscriptionBaseApiException(e);
+ }
}
@Override
- public boolean cancelWithPolicyNoValidation(final Iterable<DefaultSubscriptionBase> subscriptions, final BillingActionPolicy policy, final int accountBillCycleDayLocal, final InternalCallContext context) throws SubscriptionBaseApiException {
+ public boolean cancelWithPolicyNoValidationAndCatalog(final Iterable<DefaultSubscriptionBase> subscriptions, final BillingActionPolicy policy, final int accountBillCycleDayLocal, final Catalog catalog, final InternalCallContext context) throws SubscriptionBaseApiException {
final Map<DefaultSubscriptionBase, DateTime> subscriptionsWithEffectiveDate = new HashMap<DefaultSubscriptionBase, DateTime>();
- final DateTime now = clock.getUTCNow();
try {
-
for (final DefaultSubscriptionBase subscription : subscriptions) {
- final BillingAlignment billingAlignment = (subscription.getState() == EntitlementState.PENDING ? null : catalogInternalApi.getFullCatalog(true, true, context).billingAlignment(new PlanPhaseSpecifier(subscription.getLastActivePlan().getName(), subscription.getLastActivePhase().getPhaseType()), clock.getUTCNow()));
+ final BillingAlignment billingAlignment = (subscription.getState() == EntitlementState.PENDING ? null : catalog.billingAlignment(new PlanPhaseSpecifier(subscription.getLastActivePlan().getName(), subscription.getLastActivePhase().getPhaseType()), clock.getUTCNow()));
final DateTime effectiveDate = subscription.getPlanChangeEffectiveDate(policy, billingAlignment, accountBillCycleDayLocal, context);
subscriptionsWithEffectiveDate.put(subscription, effectiveDate);
}
+ return doCancelPlan(subscriptionsWithEffectiveDate, catalog, context);
} catch (final CatalogApiException e) {
throw new SubscriptionBaseApiException(e);
}
-
- return doCancelPlan(subscriptionsWithEffectiveDate, now, context);
}
- private boolean doCancelPlan(final Map<DefaultSubscriptionBase, DateTime> subscriptions, final DateTime now, final InternalCallContext internalCallContext) throws SubscriptionBaseApiException {
+ private boolean doCancelPlan(final Map<DefaultSubscriptionBase, DateTime> subscriptions, final Catalog fullCatalog, final InternalCallContext internalCallContext) throws SubscriptionBaseApiException {
final List<DefaultSubscriptionBase> subscriptionsToBeCancelled = new LinkedList<DefaultSubscriptionBase>();
final List<SubscriptionBaseEvent> cancelEvents = new LinkedList<SubscriptionBaseEvent>();
@@ -248,18 +258,17 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
validateEffectiveDate(subscription, effectiveDate);
subscriptionsToBeCancelled.add(subscription);
- cancelEvents.addAll(getEventsOnCancelPlan(subscription, effectiveDate, now, false, internalCallContext));
+ cancelEvents.addAll(getEventsOnCancelPlan(subscription, effectiveDate, false, fullCatalog, internalCallContext));
if (subscription.getCategory() == ProductCategory.BASE) {
- subscriptionsToBeCancelled.addAll(computeAddOnsToCancel(cancelEvents, null, subscription.getBundleId(), effectiveDate, internalCallContext));
+ subscriptionsToBeCancelled.addAll(computeAddOnsToCancel(cancelEvents, null, subscription.getBundleId(), effectiveDate, fullCatalog, internalCallContext));
}
}
- dao.cancelSubscriptions(subscriptionsToBeCancelled, cancelEvents, internalCallContext);
+ dao.cancelSubscriptions(subscriptionsToBeCancelled, cancelEvents, fullCatalog, internalCallContext);
boolean allSubscriptionsCancelled = true;
for (final DefaultSubscriptionBase subscription : subscriptions.keySet()) {
- final Catalog fullCatalog = catalogInternalApi.getFullCatalog(true, true, internalCallContext);
subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId(), internalCallContext), fullCatalog);
allSubscriptionsCancelled = allSubscriptionsCancelled && (subscription.getState() == EntitlementState.CANCELLED);
}
@@ -275,35 +284,36 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
if (!subscription.isSubscriptionFutureCancelled()) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_UNCANCEL_BAD_STATE, subscription.getId().toString());
}
+ try {
- final DateTime now = clock.getUTCNow();
- final SubscriptionBaseEvent uncancelEvent = new ApiEventUncancel(new ApiEventBuilder()
- .setSubscriptionId(subscription.getId())
- .setEffectiveDate(now)
- .setFromDisk(true));
+ final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
+ final Catalog fullCatalog = catalogInternalApi.getFullCatalog(true, true, internalCallContext);
- final List<SubscriptionBaseEvent> uncancelEvents = new ArrayList<SubscriptionBaseEvent>();
- uncancelEvents.add(uncancelEvent);
+ final DateTime now = clock.getUTCNow();
+ final SubscriptionBaseEvent uncancelEvent = new ApiEventUncancel(new ApiEventBuilder()
+ .setSubscriptionId(subscription.getId())
+ .setEffectiveDate(now)
+ .setFromDisk(true));
- final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
- //
- // Used to compute effective for next phase (which was set unactive during cancellation).
- // In case of a pending subscription we don't want to pass an effective date prior the CREATE event as we would end up with the wrong
- // transition in PlanAligner (next transition would be CREATE instead of potential next PHASE)
- //
- final DateTime planAlignerEffectiveDate = subscription.getState() == EntitlementState.PENDING ? subscription.getStartDate() : now;
-
- final TimedPhase nextTimedPhase = planAligner.getNextTimedPhase(subscription, planAlignerEffectiveDate, internalCallContext);
- final PhaseEvent nextPhaseEvent = (nextTimedPhase != null) ?
- PhaseEventData.createNextPhaseEvent(subscription.getId(), nextTimedPhase.getPhase().getName(), nextTimedPhase.getStartPhase()) :
- null;
- if (nextPhaseEvent != null) {
- uncancelEvents.add(nextPhaseEvent);
- }
+ final List<SubscriptionBaseEvent> uncancelEvents = new ArrayList<SubscriptionBaseEvent>();
+ uncancelEvents.add(uncancelEvent);
+
+ //
+ // Used to compute effective for next phase (which was set unactive during cancellation).
+ // In case of a pending subscription we don't want to pass an effective date prior the CREATE event as we would end up with the wrong
+ // transition in PlanAligner (next transition would be CREATE instead of potential next PHASE)
+ //
+ final DateTime planAlignerEffectiveDate = subscription.getState() == EntitlementState.PENDING ? subscription.getStartDate() : now;
+
+ final TimedPhase nextTimedPhase = planAligner.getNextTimedPhase(subscription, planAlignerEffectiveDate, fullCatalog, internalCallContext);
+ final PhaseEvent nextPhaseEvent = (nextTimedPhase != null) ?
+ PhaseEventData.createNextPhaseEvent(subscription.getId(), nextTimedPhase.getPhase().getName(), nextTimedPhase.getStartPhase()) :
+ null;
+ if (nextPhaseEvent != null) {
+ uncancelEvents.add(nextPhaseEvent);
+ }
- dao.uncancelSubscription(subscription, uncancelEvents, internalCallContext);
- try {
- final Catalog fullCatalog = catalogInternalApi.getFullCatalog(true, true, internalCallContext);
+ dao.uncancelSubscription(subscription, uncancelEvents, fullCatalog, internalCallContext);
subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId(), internalCallContext), fullCatalog);
return true;
} catch (final CatalogApiException e) {
@@ -406,9 +416,12 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
final List<PlanPhasePriceOverride> overrides,
final DateTime effectiveDate,
final CallContext context) throws SubscriptionBaseApiException, CatalogApiException {
+
final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
final PlanPhasePriceOverridesWithCallContext overridesWithContext = new DefaultPlanPhasePriceOverridesWithCallContext(overrides, context);
- final Plan newPlan = catalogInternalApi.getFullCatalog(true, true, internalCallContext).createOrFindPlan(spec, overridesWithContext, effectiveDate, subscription.getStartDate());
+
+ final Catalog fullCatalog = catalogInternalApi.getFullCatalog(true, true, internalCallContext);
+ final Plan newPlan = fullCatalog.createOrFindPlan(spec, overridesWithContext, effectiveDate, subscription.getStartDate());
final PhaseType initialPhaseType;
if (overrides != null &&
@@ -423,7 +436,7 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
if (ProductCategory.ADD_ON.toString().equalsIgnoreCase(newPlan.getProduct().getCategory().toString())) {
if (newPlan.getPlansAllowedInBundle() != -1
&& newPlan.getPlansAllowedInBundle() > 0
- && addonUtils.countExistingAddOnsWithSamePlanName(dao.getSubscriptions(subscription.getBundleId(), null, internalCallContext), newPlan.getName())
+ && addonUtils.countExistingAddOnsWithSamePlanName(dao.getSubscriptions(subscription.getBundleId(), null, fullCatalog, internalCallContext), newPlan.getName())
>= newPlan.getPlansAllowedInBundle()) {
// the plan can be changed to the new value, because it has reached its limit by bundle
throw new SubscriptionBaseApiException(ErrorCode.SUB_CHANGE_AO_MAX_PLAN_ALLOWED_BY_BUNDLE, newPlan.getName());
@@ -436,21 +449,21 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
final List<DefaultSubscriptionBase> addOnSubscriptionsToBeCancelled = new ArrayList<DefaultSubscriptionBase>();
final List<SubscriptionBaseEvent> addOnCancelEvents = new ArrayList<SubscriptionBaseEvent>();
- final List<SubscriptionBaseEvent> changeEvents = getEventsOnChangePlan(subscription, newPlan, newPlan.getPriceListName(), effectiveDate, true, addOnSubscriptionsToBeCancelled, addOnCancelEvents, initialPhaseType, internalCallContext);
+ final List<SubscriptionBaseEvent> changeEvents = getEventsOnChangePlan(subscription, newPlan, newPlan.getPriceListName(), effectiveDate, true, addOnSubscriptionsToBeCancelled, addOnCancelEvents, initialPhaseType, fullCatalog, internalCallContext);
- dao.changePlan(subscription, changeEvents, addOnSubscriptionsToBeCancelled, addOnCancelEvents, internalCallContext);
+ dao.changePlan(subscription, changeEvents, addOnSubscriptionsToBeCancelled, addOnCancelEvents, fullCatalog, internalCallContext);
- final Catalog fullCatalog = catalogInternalApi.getFullCatalog(true, true, internalCallContext);
subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId(), internalCallContext), fullCatalog);
}
@Override
- public List<SubscriptionBaseEvent> getEventsOnCreation(final UUID bundleId, final UUID subscriptionId, final DateTime alignStartDate, final DateTime bundleStartDate,
+ public List<SubscriptionBaseEvent> getEventsOnCreation(final UUID subscriptionId, final DateTime alignStartDate, final DateTime bundleStartDate,
final Plan plan, final PhaseType initialPhase,
- final String realPriceList, final DateTime effectiveDate, final DateTime processedDate,
+ final String realPriceList, final DateTime effectiveDate,
+ final Catalog fullCatalog,
final InternalTenantContext internalTenantContext) throws CatalogApiException, SubscriptionBaseApiException {
final TimedPhase[] curAndNextPhases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate, bundleStartDate, plan, initialPhase,
- realPriceList, effectiveDate, internalTenantContext);
+ realPriceList, effectiveDate, fullCatalog, internalTenantContext);
final ApiEventBuilder createBuilder = new ApiEventBuilder()
.setSubscriptionId(subscriptionId)
@@ -475,12 +488,14 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
@Override
public List<SubscriptionBaseEvent> getEventsOnChangePlan(final DefaultSubscriptionBase subscription, final Plan newPlan,
- final String newPriceList, final DateTime effectiveDate, final DateTime processedDate,
- final boolean addCancellationAddOnForEventsIfRequired, final InternalTenantContext internalTenantContext) throws CatalogApiException, SubscriptionBaseApiException {
+ final String newPriceList, final DateTime effectiveDate,
+ final boolean addCancellationAddOnForEventsIfRequired,
+ final Catalog fullCatalog,
+ final InternalTenantContext internalTenantContext) throws CatalogApiException, SubscriptionBaseApiException {
final Collection<DefaultSubscriptionBase> addOnSubscriptionsToBeCancelled = new ArrayList<DefaultSubscriptionBase>();
final Collection<SubscriptionBaseEvent> addOnCancelEvents = new ArrayList<SubscriptionBaseEvent>();
- final List<SubscriptionBaseEvent> changeEvents = getEventsOnChangePlan(subscription, newPlan, newPriceList, effectiveDate, addCancellationAddOnForEventsIfRequired, addOnSubscriptionsToBeCancelled, addOnCancelEvents, null, internalTenantContext);
+ final List<SubscriptionBaseEvent> changeEvents = getEventsOnChangePlan(subscription, newPlan, newPriceList, effectiveDate, addCancellationAddOnForEventsIfRequired, addOnSubscriptionsToBeCancelled, addOnCancelEvents, null, fullCatalog, internalTenantContext);
changeEvents.addAll(addOnCancelEvents);
return changeEvents;
}
@@ -491,9 +506,10 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
final Collection<DefaultSubscriptionBase> addOnSubscriptionsToBeCancelled,
final Collection<SubscriptionBaseEvent> addOnCancelEvents,
final PhaseType initialPhaseType,
+ final Catalog fullCatalog,
final InternalTenantContext internalTenantContext) throws CatalogApiException, SubscriptionBaseApiException {
- final TimedPhase currentTimedPhase = planAligner.getCurrentTimedPhaseOnChange(subscription, newPlan, effectiveDate, initialPhaseType, internalTenantContext);
+ final TimedPhase currentTimedPhase = planAligner.getCurrentTimedPhaseOnChange(subscription, newPlan, effectiveDate, initialPhaseType, fullCatalog, internalTenantContext);
validateSubscriptionState(subscription, effectiveDate);
@@ -505,7 +521,7 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
.setEffectiveDate(effectiveDate)
.setFromDisk(true));
- final TimedPhase nextTimedPhase = planAligner.getNextTimedPhaseOnChange(subscription, newPlan, effectiveDate, initialPhaseType, internalTenantContext);
+ final TimedPhase nextTimedPhase = planAligner.getNextTimedPhaseOnChange(subscription, newPlan, effectiveDate, initialPhaseType, fullCatalog, internalTenantContext);
final PhaseEvent nextPhaseEvent = (nextTimedPhase != null) ?
PhaseEventData.createNextPhaseEvent(subscription.getId(),
nextTimedPhase.getPhase().getName(), nextTimedPhase.getStartPhase()) :
@@ -520,15 +536,17 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
if (subscription.getCategory() == ProductCategory.BASE && addCancellationAddOnForEventsIfRequired) {
final Product currentBaseProduct = changeEvent.getEffectiveDate().compareTo(clock.getUTCNow()) <= 0 ? newPlan.getProduct() : subscription.getCurrentOrPendingPlan().getProduct();
- addOnSubscriptionsToBeCancelled.addAll(addCancellationAddOnForEventsIfRequired(addOnCancelEvents, currentBaseProduct, subscription.getBundleId(), effectiveDate, internalTenantContext));
+ addOnSubscriptionsToBeCancelled.addAll(addCancellationAddOnForEventsIfRequired(addOnCancelEvents, currentBaseProduct, subscription.getBundleId(), effectiveDate, fullCatalog, internalTenantContext));
}
return changeEvents;
}
@Override
public List<SubscriptionBaseEvent> getEventsOnCancelPlan(final DefaultSubscriptionBase subscription,
- final DateTime effectiveDate, final DateTime processedDate,
- final boolean addCancellationAddOnForEventsIfRequired, final InternalTenantContext internalTenantContext) throws CatalogApiException {
+ final DateTime effectiveDate,
+ final boolean addCancellationAddOnForEventsIfRequired,
+ final Catalog fullCatalog,
+ final InternalTenantContext internalTenantContext) throws CatalogApiException {
final List<SubscriptionBaseEvent> cancelEvents = new ArrayList<SubscriptionBaseEvent>();
final SubscriptionBaseEvent cancelEvent = new ApiEventCancel(new ApiEventBuilder()
.setSubscriptionId(subscription.getId())
@@ -537,45 +555,45 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
cancelEvents.add(cancelEvent);
if (subscription.getCategory() == ProductCategory.BASE && addCancellationAddOnForEventsIfRequired) {
final Product currentBaseProduct = cancelEvent.getEffectiveDate().compareTo(clock.getUTCNow()) <= 0 ? null : subscription.getCurrentPlan().getProduct();
- addCancellationAddOnForEventsIfRequired(cancelEvents, currentBaseProduct, subscription.getBundleId(), effectiveDate, internalTenantContext);
+ addCancellationAddOnForEventsIfRequired(cancelEvents, currentBaseProduct, subscription.getBundleId(), effectiveDate, fullCatalog, internalTenantContext);
}
return cancelEvents;
}
@Override
- public int handleBasePlanEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, final CallContext context) throws CatalogApiException {
+ public int handleBasePlanEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, final Catalog catalog, final CallContext context) throws CatalogApiException {
final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context);
if (((ApiEvent) event).getApiEventType() == ApiEventType.CANCEL || ((ApiEvent) event).getApiEventType() == ApiEventType.CHANGE) {
final Product baseProduct = (subscription.getState() == EntitlementState.CANCELLED) ? null : subscription.getCurrentPlan().getProduct();
final List<SubscriptionBaseEvent> cancelEvents = new LinkedList<SubscriptionBaseEvent>();
- final List<DefaultSubscriptionBase> subscriptionsToBeCancelled = computeAddOnsToCancel(cancelEvents, baseProduct, subscription.getBundleId(), event.getEffectiveDate(), internalCallContext);
- dao.cancelSubscriptionsOnBasePlanEvent(subscription, event, subscriptionsToBeCancelled, cancelEvents, internalCallContext);
+ final List<DefaultSubscriptionBase> subscriptionsToBeCancelled = computeAddOnsToCancel(cancelEvents, baseProduct, subscription.getBundleId(), event.getEffectiveDate(), catalog, internalCallContext);
+ dao.cancelSubscriptionsOnBasePlanEvent(subscription, event, subscriptionsToBeCancelled, cancelEvents, catalog, internalCallContext);
return subscriptionsToBeCancelled.size();
} else {
- dao.notifyOnBasePlanEvent(subscription, event, internalCallContext);
+ dao.notifyOnBasePlanEvent(subscription, event, catalog, internalCallContext);
return 0;
}
}
- private List<DefaultSubscriptionBase> computeAddOnsToCancel(final Collection<SubscriptionBaseEvent> cancelEvents, final CatalogEntity baseProduct, final UUID bundleId, final DateTime effectiveDate, final InternalCallContext internalCallContext) throws CatalogApiException {
+ private List<DefaultSubscriptionBase> computeAddOnsToCancel(final Collection<SubscriptionBaseEvent> cancelEvents, final CatalogEntity baseProduct, final UUID bundleId, final DateTime effectiveDate, final Catalog catalog, final InternalCallContext internalCallContext) throws CatalogApiException {
// If cancellation/change occur in the future, there is nothing to do
final DateTime now = clock.getUTCNow();
if (effectiveDate.compareTo(now) > 0) {
return ImmutableList.<DefaultSubscriptionBase>of();
} else {
- return addCancellationAddOnForEventsIfRequired(cancelEvents, baseProduct, bundleId, effectiveDate, internalCallContext);
+ return addCancellationAddOnForEventsIfRequired(cancelEvents, baseProduct, bundleId, effectiveDate, catalog, internalCallContext);
}
}
private List<DefaultSubscriptionBase> addCancellationAddOnForEventsIfRequired(final Collection<SubscriptionBaseEvent> events, final CatalogEntity baseProduct, final UUID bundleId,
- final DateTime effectiveDate, final InternalTenantContext internalTenantContext) throws CatalogApiException {
+ final DateTime effectiveDate, final Catalog catalog, final InternalTenantContext internalTenantContext) throws CatalogApiException {
final List<DefaultSubscriptionBase> subscriptionsToBeCancelled = new ArrayList<DefaultSubscriptionBase>();
- final List<SubscriptionBase> subscriptions = dao.getSubscriptions(bundleId, ImmutableList.<SubscriptionBaseEvent>of(), internalTenantContext);
+ final List<SubscriptionBase> subscriptions = dao.getSubscriptions(bundleId, ImmutableList.<SubscriptionBaseEvent>of(), catalog, internalTenantContext);
for (final SubscriptionBase subscription : subscriptions) {
final DefaultSubscriptionBase cur = (DefaultSubscriptionBase) subscription;
@@ -586,8 +604,8 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
final Plan addonCurrentPlan = cur.getCurrentPlan();
if (baseProduct == null ||
- addonUtils.isAddonIncludedFromProdName(baseProduct.getName(), addonCurrentPlan, effectiveDate, internalTenantContext) ||
- !addonUtils.isAddonAvailableFromProdName(baseProduct.getName(), addonCurrentPlan, effectiveDate, internalTenantContext)) {
+ addonUtils.isAddonIncludedFromProdName(baseProduct.getName(), addonCurrentPlan, effectiveDate, catalog, internalTenantContext) ||
+ !addonUtils.isAddonAvailableFromProdName(baseProduct.getName(), addonCurrentPlan, effectiveDate, catalog, internalTenantContext)) {
//
// Perform AO cancellation using the effectiveDate of the BP
//
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/engine/addon/AddonUtils.java b/subscription/src/main/java/org/killbill/billing/subscription/engine/addon/AddonUtils.java
index e01da44..c8c84b3 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/engine/addon/AddonUtils.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/engine/addon/AddonUtils.java
@@ -22,6 +22,7 @@ import java.util.List;
import org.joda.time.DateTime;
import org.killbill.billing.ErrorCode;
import org.killbill.billing.callcontext.InternalTenantContext;
+import org.killbill.billing.catalog.api.Catalog;
import org.killbill.billing.catalog.api.CatalogApiException;
import org.killbill.billing.catalog.api.CatalogInternalApi;
import org.killbill.billing.catalog.api.Plan;
@@ -37,14 +38,12 @@ import com.google.inject.Inject;
public class AddonUtils {
- private final CatalogInternalApi catalogInternalApi;
@Inject
- public AddonUtils(final CatalogInternalApi catalogInternalApi) {
- this.catalogInternalApi = catalogInternalApi;
+ public AddonUtils() {
}
- public void checkAddonCreationRights(final DefaultSubscriptionBase baseSubscription, final Plan targetAddOnPlan, final DateTime requestedDate, final InternalTenantContext context)
+ public void checkAddonCreationRights(final DefaultSubscriptionBase baseSubscription, final Plan targetAddOnPlan, final DateTime requestedDate, final Catalog catalog, final InternalTenantContext context)
throws SubscriptionBaseApiException, CatalogApiException {
if (baseSubscription.getState() == EntitlementState.CANCELLED ||
@@ -53,7 +52,7 @@ public class AddonUtils {
}
final Plan currentOrPendingPlan = baseSubscription.getCurrentOrPendingPlan();
- final Product baseProduct = catalogInternalApi.getFullCatalog(true, true, context).findProduct(currentOrPendingPlan.getProduct().getName(), requestedDate);
+ final Product baseProduct = catalog.findProduct(currentOrPendingPlan.getProduct().getName(), requestedDate);
if (isAddonIncluded(baseProduct, targetAddOnPlan)) {
throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_AO_ALREADY_INCLUDED,
targetAddOnPlan.getName(), currentOrPendingPlan.getProduct().getName());
@@ -65,18 +64,18 @@ public class AddonUtils {
}
}
- public boolean isAddonAvailableFromProdName(final String baseProductName, final Plan targetAddOnPlan, final DateTime requestedDate, final InternalTenantContext context) {
+ public boolean isAddonAvailableFromProdName(final String baseProductName, final Plan targetAddOnPlan, final DateTime requestedDate, final Catalog catalog, final InternalTenantContext context) {
try {
- final Product product = catalogInternalApi.getFullCatalog(true, true, context).findProduct(baseProductName, requestedDate);
+ final Product product = catalog.findProduct(baseProductName, requestedDate);
return isAddonAvailable(product, targetAddOnPlan);
} catch (CatalogApiException e) {
throw new SubscriptionBaseError(e);
}
}
- public boolean isAddonAvailableFromPlanName(final String basePlanName, final Plan targetAddOnPlan, final DateTime requestedDate, final InternalTenantContext context) {
+ public boolean isAddonAvailableFromPlanName(final String basePlanName, final Plan targetAddOnPlan, final DateTime requestedDate, final Catalog catalog, final InternalTenantContext context) {
try {
- final Plan plan = catalogInternalApi.getFullCatalog(true, true, context).findPlan(basePlanName, requestedDate);
+ final Plan plan = catalog.findPlan(basePlanName, requestedDate);
final Product product = plan.getProduct();
return isAddonAvailable(product, targetAddOnPlan);
} catch (CatalogApiException e) {
@@ -84,9 +83,9 @@ public class AddonUtils {
}
}
- public boolean isAddonIncludedFromProdName(final String baseProductName, final Plan targetAddOnPlan, final DateTime requestedDate, final InternalTenantContext context) {
+ public boolean isAddonIncludedFromProdName(final String baseProductName, final Plan targetAddOnPlan, final DateTime requestedDate, final Catalog catalog, final InternalTenantContext context) {
try {
- final Product product = catalogInternalApi.getFullCatalog(true, true, context).findProduct(baseProductName, requestedDate);
+ final Product product = catalog.findProduct(baseProductName, requestedDate);
return isAddonIncluded(product, targetAddOnPlan);
} catch (CatalogApiException e) {
throw new SubscriptionBaseError(e);
@@ -94,9 +93,9 @@ public class AddonUtils {
}
- public boolean isAddonIncludedFromPlanName(final String basePlanName, final Plan targetAddOnPlan, final DateTime requestedDate, final InternalTenantContext context) {
+ public boolean isAddonIncludedFromPlanName(final String basePlanName, final Plan targetAddOnPlan, final DateTime requestedDate, final Catalog catalog, final InternalTenantContext context) {
try {
- final Plan plan = catalogInternalApi.getFullCatalog(true, true, context).findPlan(basePlanName, requestedDate);
+ final Plan plan = catalog.findPlan(basePlanName, requestedDate);
final Product product = plan.getProduct();
return isAddonIncluded(product, targetAddOnPlan);
} catch (CatalogApiException e) {
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/engine/core/DefaultSubscriptionBaseService.java b/subscription/src/main/java/org/killbill/billing/subscription/engine/core/DefaultSubscriptionBaseService.java
index 183814e..2d80b2e 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/engine/core/DefaultSubscriptionBaseService.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/engine/core/DefaultSubscriptionBaseService.java
@@ -22,7 +22,9 @@ import java.util.UUID;
import org.joda.time.DateTime;
import org.killbill.billing.callcontext.InternalCallContext;
+import org.killbill.billing.catalog.api.Catalog;
import org.killbill.billing.catalog.api.CatalogApiException;
+import org.killbill.billing.catalog.api.CatalogInternalApi;
import org.killbill.billing.catalog.api.ProductCategory;
import org.killbill.billing.platform.api.LifecycleHandlerType;
import org.killbill.billing.platform.api.LifecycleHandlerType.LifecycleLevel;
@@ -72,15 +74,19 @@ public class DefaultSubscriptionBaseService implements EventListener, Subscripti
private final NotificationQueueService notificationQueueService;
private final InternalCallContextFactory internalCallContextFactory;
private final SubscriptionBaseApiService apiService;
+ private final CatalogInternalApi catalogInternalApi;
private NotificationQueue subscriptionEventQueue;
@Inject
- public DefaultSubscriptionBaseService(final Clock clock, final SubscriptionDao dao, final PlanAligner planAligner,
+ public DefaultSubscriptionBaseService(final Clock clock,
+ final SubscriptionDao dao,
+ final PlanAligner planAligner,
final PersistentBus eventBus,
final NotificationQueueService notificationQueueService,
final InternalCallContextFactory internalCallContextFactory,
- final SubscriptionBaseApiService apiService) {
+ final SubscriptionBaseApiService apiService,
+ final CatalogInternalApi catalogInternalApi) {
this.clock = clock;
this.dao = dao;
this.planAligner = planAligner;
@@ -88,6 +94,7 @@ public class DefaultSubscriptionBaseService implements EventListener, Subscripti
this.notificationQueueService = notificationQueueService;
this.internalCallContextFactory = internalCallContextFactory;
this.apiService = apiService;
+ this.catalogInternalApi = catalogInternalApi;
}
@Override
@@ -147,7 +154,8 @@ public class DefaultSubscriptionBaseService implements EventListener, Subscripti
}
try {
- final DefaultSubscriptionBase subscription = (DefaultSubscriptionBase) dao.getSubscriptionFromId(event.getSubscriptionId(), context);
+ final Catalog fullCatalog = catalogInternalApi.getFullCatalog(true, true, context);
+ final DefaultSubscriptionBase subscription = (DefaultSubscriptionBase) dao.getSubscriptionFromId(event.getSubscriptionId(), fullCatalog, context);
if (subscription == null) {
log.warn("Error retrieving subscriptionId='{}'", event.getSubscriptionId());
return;
@@ -161,10 +169,10 @@ public class DefaultSubscriptionBaseService implements EventListener, Subscripti
boolean eventSent = false;
if (event.getType() == EventType.PHASE) {
- eventSent = onPhaseEvent(subscription, event, context);
+ eventSent = onPhaseEvent(subscription, event, fullCatalog, context);
} else if (event.getType() == EventType.API_USER && subscription.getCategory() == ProductCategory.BASE) {
final CallContext callContext = internalCallContextFactory.createCallContext(context);
- eventSent = onBasePlanEvent(subscription, event, callContext);
+ eventSent = onBasePlanEvent(subscription, event, fullCatalog, callContext);
} else if (event.getType() == EventType.BCD_UPDATE) {
eventSent = false;
}
@@ -185,9 +193,9 @@ public class DefaultSubscriptionBaseService implements EventListener, Subscripti
}
}
- private boolean onPhaseEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent readyPhaseEvent, final InternalCallContext context) {
+ private boolean onPhaseEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent readyPhaseEvent, final Catalog fullCatalog, final InternalCallContext context) {
try {
- final TimedPhase nextTimedPhase = planAligner.getNextTimedPhase(subscription, readyPhaseEvent.getEffectiveDate(), context);
+ final TimedPhase nextTimedPhase = planAligner.getNextTimedPhase(subscription, readyPhaseEvent.getEffectiveDate(), fullCatalog, context);
final PhaseEvent nextPhaseEvent = (nextTimedPhase != null) ?
PhaseEventData.createNextPhaseEvent(subscription.getId(),
nextTimedPhase.getPhase().getName(), nextTimedPhase.getStartPhase()) :
@@ -203,8 +211,8 @@ public class DefaultSubscriptionBaseService implements EventListener, Subscripti
return false;
}
- private boolean onBasePlanEvent(final DefaultSubscriptionBase baseSubscription, final SubscriptionBaseEvent event, final CallContext context) throws CatalogApiException {
- apiService.handleBasePlanEvent(baseSubscription, event, context);
+ private boolean onBasePlanEvent(final DefaultSubscriptionBase baseSubscription, final SubscriptionBaseEvent event, final Catalog fullCatalog, final CallContext context) throws CatalogApiException {
+ apiService.handleBasePlanEvent(baseSubscription, event, fullCatalog, context);
return true;
}
}
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java
index 3ee2332..ed363e6 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java
@@ -119,20 +119,17 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
private final NotificationQueueService notificationQueueService;
private final AddonUtils addonUtils;
private final PersistentBus eventBus;
- private final CatalogInternalApi catalogInternalApi;
- private final InternalCallContextFactory internalCallContextFactory;
@Inject
public DefaultSubscriptionDao(final IDBI dbi, final Clock clock, final AddonUtils addonUtils,
- final NotificationQueueService notificationQueueService, final PersistentBus eventBus, final CatalogInternalApi catalogInternalApi,
- final CacheControllerDispatcher cacheControllerDispatcher, final NonEntityDao nonEntityDao, final InternalCallContextFactory internalCallContextFactory) {
+ final NotificationQueueService notificationQueueService, final PersistentBus eventBus,
+ final CacheControllerDispatcher cacheControllerDispatcher, final NonEntityDao nonEntityDao,
+ final InternalCallContextFactory internalCallContextFactory) {
super(new EntitySqlDaoTransactionalJdbiWrapper(dbi, clock, cacheControllerDispatcher, nonEntityDao, internalCallContextFactory), BundleSqlDao.class);
this.clock = clock;
this.notificationQueueService = notificationQueueService;
this.addonUtils = addonUtils;
this.eventBus = eventBus;
- this.catalogInternalApi = catalogInternalApi;
- this.internalCallContextFactory = internalCallContextFactory;
}
@Override
@@ -299,12 +296,12 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
}
@Override
- public SubscriptionBase getBaseSubscription(final UUID bundleId, final InternalTenantContext context) throws CatalogApiException {
- return getBaseSubscription(bundleId, true, context);
+ public SubscriptionBase getBaseSubscription(final UUID bundleId, final Catalog catalog, final InternalTenantContext context) throws CatalogApiException {
+ return getBaseSubscription(bundleId, true, catalog, context);
}
@Override
- public SubscriptionBase getSubscriptionFromId(final UUID subscriptionId, final InternalTenantContext context) throws CatalogApiException {
+ public SubscriptionBase getSubscriptionFromId(final UUID subscriptionId, final Catalog catalog, final InternalTenantContext context) throws CatalogApiException {
final SubscriptionBase shellSubscription = transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<SubscriptionBase>() {
@Override
public SubscriptionBase inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
@@ -313,12 +310,12 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
return SubscriptionModelDao.toSubscription(subscriptionModel, bundleModel.getExternalKey());
}
});
- return buildSubscription(shellSubscription, context);
+ return buildSubscription(shellSubscription, catalog, context);
}
@Override
- public List<SubscriptionBase> getSubscriptions(final UUID bundleId, final List<SubscriptionBaseEvent> dryRunEvents, final InternalTenantContext context) throws CatalogApiException {
- return buildBundleSubscriptions(getSubscriptionFromBundleId(bundleId, context), null, dryRunEvents, context);
+ public List<SubscriptionBase> getSubscriptions(final UUID bundleId, final List<SubscriptionBaseEvent> dryRunEvents, final Catalog catalog, final InternalTenantContext context) throws CatalogApiException {
+ return buildBundleSubscriptions(getSubscriptionFromBundleId(bundleId, context), null, dryRunEvents, catalog, context);
}
private List<SubscriptionBase> getSubscriptionFromBundleId(final UUID bundleId, final InternalTenantContext context) {
@@ -340,7 +337,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
}
@Override
- public Map<UUID, List<SubscriptionBase>> getSubscriptionsForAccount(final InternalTenantContext context) throws CatalogApiException {
+ public Map<UUID, List<SubscriptionBase>> getSubscriptionsForAccount(final Catalog catalog, final InternalTenantContext context) throws CatalogApiException {
final Map<UUID, List<SubscriptionBase>> subscriptionsFromAccountId = getSubscriptionsFromAccountId(context);
final List<SubscriptionBaseEvent> eventsForAccount = getEventsForAccountId(context);
@@ -362,7 +359,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
eventsForSubscriptions.putAll(cur.getId(), ImmutableList.copyOf(events));
}
- result.put(bundleId, buildBundleSubscriptions(subscriptionsForBundle, eventsForSubscriptions, null, context));
+ result.put(bundleId, buildBundleSubscriptions(subscriptionsForBundle, eventsForSubscriptions, null, catalog, context));
}
return result;
}
@@ -501,7 +498,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
}
@Override
- public void createSubscription(final DefaultSubscriptionBase subscription, final List<SubscriptionBaseEvent> initialEvents, final InternalCallContext context) {
+ public void createSubscription(final DefaultSubscriptionBase subscription, final List<SubscriptionBaseEvent> initialEvents, final Catalog catalog, final InternalCallContext context) {
transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
@Override
public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
@@ -513,7 +510,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
createAndRefresh(eventsDaoFromSameTransaction, new SubscriptionEventModelDao(cur), context);
final boolean isBusEvent = cur.getEffectiveDate().compareTo(clock.getUTCNow()) <= 0 && (cur.getType() == EventType.API_USER);
- recordBusOrFutureNotificationFromTransaction(subscription, cur, entitySqlDaoWrapperFactory, isBusEvent, 0, context);
+ recordBusOrFutureNotificationFromTransaction(subscription, cur, entitySqlDaoWrapperFactory, isBusEvent, 0, catalog, context);
}
// Notify the Bus of the latest requested change, if needed
@@ -526,7 +523,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
}
@Override
- public void createSubscriptionsWithAddOns(final List<SubscriptionBaseWithAddOns> subscriptions, final Map<UUID, List<SubscriptionBaseEvent>> initialEventsMap, final InternalCallContext context) {
+ public void createSubscriptionsWithAddOns(final List<SubscriptionBaseWithAddOns> subscriptions, final Map<UUID, List<SubscriptionBaseEvent>> initialEventsMap, final Catalog catalog, final InternalCallContext context) {
transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
@Override
public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
@@ -544,7 +541,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
createAndRefresh(eventsDaoFromSameTransaction, new SubscriptionEventModelDao(cur), context);
final boolean isBusEvent = cur.getEffectiveDate().compareTo(clock.getUTCNow()) <= 0 && (cur.getType() == EventType.API_USER);
- recordBusOrFutureNotificationFromTransaction(defaultSubscriptionBase, cur, entitySqlDaoWrapperFactory, isBusEvent, 0, context);
+ recordBusOrFutureNotificationFromTransaction(defaultSubscriptionBase, cur, entitySqlDaoWrapperFactory, isBusEvent, 0, catalog, context);
}
// Notify the Bus of the latest requested change, if needed
@@ -559,11 +556,11 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
}
@Override
- public void cancelSubscriptionsOnBasePlanEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, final List<DefaultSubscriptionBase> subscriptions, final List<SubscriptionBaseEvent> cancelEvents, final InternalCallContext context) {
+ public void cancelSubscriptionsOnBasePlanEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, final List<DefaultSubscriptionBase> subscriptions, final List<SubscriptionBaseEvent> cancelEvents, final Catalog catalog, final InternalCallContext context) {
transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
@Override
public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
- cancelSubscriptionsFromTransaction(entitySqlDaoWrapperFactory, subscriptions, cancelEvents, context);
+ cancelSubscriptionsFromTransaction(entitySqlDaoWrapperFactory, subscriptions, cancelEvents, catalog, context);
// Make sure to always send the event, even if there were no subscriptions to cancel
notifyBusOfEffectiveImmediateChange(entitySqlDaoWrapperFactory, subscription, event, subscriptions.size(), context);
return null;
@@ -572,7 +569,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
}
@Override
- public void notifyOnBasePlanEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, final InternalCallContext context) {
+ public void notifyOnBasePlanEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, final Catalog catalog, final InternalCallContext context) {
transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
@Override
public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
@@ -584,26 +581,26 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
}
@Override
- public void cancelSubscriptions(final List<DefaultSubscriptionBase> subscriptions, final List<SubscriptionBaseEvent> cancelEvents, final InternalCallContext context) {
+ public void cancelSubscriptions(final List<DefaultSubscriptionBase> subscriptions, final List<SubscriptionBaseEvent> cancelEvents, final Catalog catalog, final InternalCallContext context) {
transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
@Override
public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
- cancelSubscriptionsFromTransaction(entitySqlDaoWrapperFactory, subscriptions, cancelEvents, context);
+ cancelSubscriptionsFromTransaction(entitySqlDaoWrapperFactory, subscriptions, cancelEvents, catalog, context);
return null;
}
});
}
- private void cancelSubscriptionsFromTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory, final List<DefaultSubscriptionBase> subscriptions, final List<SubscriptionBaseEvent> cancelEvents, final InternalCallContext context) throws EntityPersistenceException {
+ private void cancelSubscriptionsFromTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory, final List<DefaultSubscriptionBase> subscriptions, final List<SubscriptionBaseEvent> cancelEvents, final Catalog catalog, final InternalCallContext context) throws EntityPersistenceException {
for (int i = 0; i < subscriptions.size(); i++) {
final DefaultSubscriptionBase subscription = subscriptions.get(i);
final SubscriptionBaseEvent cancelEvent = cancelEvents.get(i);
- cancelSubscriptionFromTransaction(subscription, cancelEvent, entitySqlDaoWrapperFactory, context, subscriptions.size() - i - 1);
+ cancelSubscriptionFromTransaction(subscription, cancelEvent, entitySqlDaoWrapperFactory, catalog, context, subscriptions.size() - i - 1);
}
}
@Override
- public void uncancelSubscription(final DefaultSubscriptionBase subscription, final List<SubscriptionBaseEvent> uncancelEvents, final InternalCallContext context) {
+ public void uncancelSubscription(final DefaultSubscriptionBase subscription, final List<SubscriptionBaseEvent> uncancelEvents, final Catalog catalog, final InternalCallContext context) {
final InternalCallContext contextWithUpdatedDate = contextWithUpdatedDate(context);
transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
@@ -646,7 +643,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
}
@Override
- public void changePlan(final DefaultSubscriptionBase subscription, final List<SubscriptionBaseEvent> originalInputChangeEvents, final List<DefaultSubscriptionBase> subscriptionsToBeCancelled, final List<SubscriptionBaseEvent> cancelEvents, final InternalCallContext context) {
+ public void changePlan(final DefaultSubscriptionBase subscription, final List<SubscriptionBaseEvent> originalInputChangeEvents, final List<DefaultSubscriptionBase> subscriptionsToBeCancelled, final List<SubscriptionBaseEvent> cancelEvents, final Catalog catalog, final InternalCallContext context) {
// First event is expected to be the subscription CHANGE event
final SubscriptionBaseEvent inputChangeEvent = originalInputChangeEvents.get(0);
@@ -700,7 +697,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
createAndRefresh(transactional, new SubscriptionEventModelDao(cur), context);
final boolean isBusEvent = cur.getEffectiveDate().compareTo(clock.getUTCNow()) <= 0 && (cur.getType() == EventType.API_USER);
- recordBusOrFutureNotificationFromTransaction(subscription, cur, entitySqlDaoWrapperFactory, isBusEvent, 0, context);
+ recordBusOrFutureNotificationFromTransaction(subscription, cur, entitySqlDaoWrapperFactory, isBusEvent, 0, catalog, context);
}
// Notify the Bus of the latest requested change
@@ -708,7 +705,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
notifyBusOfRequestedChange(entitySqlDaoWrapperFactory, subscription, finalEvent, SubscriptionBaseTransitionType.CHANGE, context);
// Cancel associated add-ons
- cancelSubscriptionsFromTransaction(entitySqlDaoWrapperFactory, subscriptionsToBeCancelled, cancelEvents, context);
+ cancelSubscriptionsFromTransaction(entitySqlDaoWrapperFactory, subscriptionsToBeCancelled, cancelEvents, catalog, context);
return null;
}
@@ -740,7 +737,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
});
}
- private void cancelSubscriptionFromTransaction(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent cancelEvent, final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory, final InternalCallContext context, final int seqId)
+ private void cancelSubscriptionFromTransaction(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent cancelEvent, final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory, final Catalog catalog, final InternalCallContext context, final int seqId)
throws EntityPersistenceException {
final UUID subscriptionId = subscription.getId();
cancelFutureEventsFromTransaction(subscriptionId, cancelEvent.getEffectiveDate(), entitySqlDaoWrapperFactory, true, context);
@@ -748,7 +745,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
createAndRefresh(subscriptionEventSqlDao, new SubscriptionEventModelDao(cancelEvent), context);
final boolean isBusEvent = cancelEvent.getEffectiveDate().compareTo(clock.getUTCNow()) <= 0;
- recordBusOrFutureNotificationFromTransaction(subscription, cancelEvent, entitySqlDaoWrapperFactory, isBusEvent, seqId, context);
+ recordBusOrFutureNotificationFromTransaction(subscription, cancelEvent, entitySqlDaoWrapperFactory, isBusEvent, seqId, catalog, context);
// Notify the Bus of the requested change
notifyBusOfRequestedChange(entitySqlDaoWrapperFactory, subscription, cancelEvent, SubscriptionBaseTransitionType.CANCEL, context);
@@ -811,14 +808,14 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
}
}
- private SubscriptionBase buildSubscription(final SubscriptionBase input, final InternalTenantContext context) throws CatalogApiException {
+ private SubscriptionBase buildSubscription(final SubscriptionBase input, final Catalog catalog, final InternalTenantContext context) throws CatalogApiException {
if (input == null) {
return null;
}
final List<SubscriptionBase> bundleInput = new ArrayList<SubscriptionBase>();
if (input.getCategory() == ProductCategory.ADD_ON) {
- final SubscriptionBase baseSubscription = getBaseSubscription(input.getBundleId(), false, context);
+ final SubscriptionBase baseSubscription = getBaseSubscription(input.getBundleId(), false, catalog, context);
if (baseSubscription == null) {
return null;
}
@@ -829,7 +826,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
bundleInput.add(input);
}
- final List<SubscriptionBase> reloadedSubscriptions = buildBundleSubscriptions(bundleInput, null, null, context);
+ final List<SubscriptionBase> reloadedSubscriptions = buildBundleSubscriptions(bundleInput, null, null, catalog, context);
for (final SubscriptionBase cur : reloadedSubscriptions) {
if (cur.getId().equals(input.getId())) {
return cur;
@@ -840,7 +837,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
}
private List<SubscriptionBase> buildBundleSubscriptions(final List<SubscriptionBase> input, @Nullable final Multimap<UUID, SubscriptionBaseEvent> eventsForSubscription,
- @Nullable final Collection<SubscriptionBaseEvent> dryRunEvents, final InternalTenantContext context) throws CatalogApiException {
+ @Nullable final Collection<SubscriptionBaseEvent> dryRunEvents, final Catalog catalog, final InternalTenantContext context) throws CatalogApiException {
if (input == null || input.isEmpty()) {
return Collections.emptyList();
}
@@ -857,7 +854,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
getEventsForSubscription(cur.getId(), context);
mergeDryRunEvents(cur.getId(), events, dryRunEvents);
- SubscriptionBase reloaded = createSubscriptionForInternalUse(cur, events, context);
+ SubscriptionBase reloaded = createSubscriptionForInternalUse(cur, events, catalog, context);
switch (cur.getCategory()) {
case BASE:
@@ -885,8 +882,8 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
for (final ApiEventChange baseChangeEvent : baseChangeEvents) {
final String baseProductName = baseChangeEvent.getEventPlan();
- if ((!addonUtils.isAddonAvailableFromPlanName(baseProductName, targetAddOnPlan, baseChangeEvent.getEffectiveDate(), context)) ||
- (addonUtils.isAddonIncludedFromPlanName(baseProductName, targetAddOnPlan, baseChangeEvent.getEffectiveDate(), context))) {
+ if ((!addonUtils.isAddonAvailableFromPlanName(baseProductName, targetAddOnPlan, baseChangeEvent.getEffectiveDate(), catalog, context)) ||
+ (addonUtils.isAddonIncludedFromPlanName(baseProductName, targetAddOnPlan, baseChangeEvent.getEffectiveDate(), catalog, context))) {
if (baseTriggerEventForAddOnCancellation != null) {
if (baseTriggerEventForAddOnCancellation.getEffectiveDate().isAfter(baseChangeEvent.getEffectiveDate())) {
baseTriggerEventForAddOnCancellation = baseChangeEvent;
@@ -909,7 +906,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
events.add(addOnCancelEvent);
// Finally reload subscription with full set of events
- reloaded = createSubscriptionForInternalUse(cur, events, context);
+ reloaded = createSubscriptionForInternalUse(cur, events, catalog, context);
}
break;
default:
@@ -973,7 +970,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
@Override
public void transfer(final UUID srcAccountId, final UUID destAccountId, final BundleTransferData bundleTransferData,
- final List<TransferCancelData> transferCancelData, final InternalCallContext fromContext, final InternalCallContext toContext) {
+ final List<TransferCancelData> transferCancelData, final Catalog catalog, final InternalCallContext fromContext, final InternalCallContext toContext) {
transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
@Override
@@ -982,7 +979,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
// Cancel the subscriptions for the old bundle
for (final TransferCancelData cancel : transferCancelData) {
- cancelSubscriptionFromTransaction(cancel.getSubscription(), cancel.getCancelEvent(), entitySqlDaoWrapperFactory, fromContext, 0);
+ cancelSubscriptionFromTransaction(cancel.getSubscription(), cancel.getCancelEvent(), entitySqlDaoWrapperFactory, catalog, fromContext, 0);
}
transferBundleDataFromTransaction(bundleTransferData, transactional, entitySqlDaoWrapperFactory, toContext);
@@ -1005,7 +1002,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
}
@Override
- public void createBCDChangeEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent bcdEvent, final InternalCallContext context) {
+ public void createBCDChangeEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent bcdEvent, final Catalog catalog, final InternalCallContext context) {
transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
@Override
public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
@@ -1015,7 +1012,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
// Notify the Bus
notifyBusOfRequestedChange(entitySqlDaoWrapperFactory, subscription, bcdEvent, SubscriptionBaseTransitionType.BCD_CHANGE, context);
final boolean isBusEvent = bcdEvent.getEffectiveDate().compareTo(clock.getUTCNow()) <= 0;
- recordBusOrFutureNotificationFromTransaction(subscription, bcdEvent, entitySqlDaoWrapperFactory, isBusEvent, 0, context);
+ recordBusOrFutureNotificationFromTransaction(subscription, bcdEvent, entitySqlDaoWrapperFactory, isBusEvent, 0, catalog, context);
return null;
}
@@ -1023,21 +1020,20 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
}
- private SubscriptionBase createSubscriptionForInternalUse(final SubscriptionBase shellSubscription, final List<SubscriptionBaseEvent> events, final InternalTenantContext context) throws CatalogApiException {
+ private SubscriptionBase createSubscriptionForInternalUse(final SubscriptionBase shellSubscription, final List<SubscriptionBaseEvent> events, final Catalog catalog, final InternalTenantContext context) throws CatalogApiException {
final DefaultSubscriptionBase result = new DefaultSubscriptionBase(new SubscriptionBuilder(((DefaultSubscriptionBase) shellSubscription)), null, clock);
if (!events.isEmpty()) {
- final Catalog fullCatalog = getFullCatalog(result.getId(), ObjectType.SUBSCRIPTION, context);
- result.rebuildTransitions(events, fullCatalog);
+ result.rebuildTransitions(events, catalog);
}
return result;
}
- private SubscriptionBase getBaseSubscription(final UUID bundleId, final boolean rebuildSubscription, final InternalTenantContext context) throws CatalogApiException {
+ private SubscriptionBase getBaseSubscription(final UUID bundleId, final boolean rebuildSubscription, final Catalog catalog, final InternalTenantContext context) throws CatalogApiException {
final List<SubscriptionBase> subscriptions = getSubscriptionFromBundleId(bundleId, context);
for (final SubscriptionBase cur : subscriptions) {
if (cur.getCategory() == ProductCategory.BASE) {
- return rebuildSubscription ? buildSubscription(cur, context) : cur;
+ return rebuildSubscription ? buildSubscription(cur, catalog, context) : cur;
}
}
return null;
@@ -1047,9 +1043,9 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
// Either records a notification or sends a bus event if operation is immediate
//
private void recordBusOrFutureNotificationFromTransaction(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory, final boolean busEvent,
- final int seqId, final InternalCallContext context) {
+ final int seqId, final Catalog catalog, final InternalCallContext context) {
if (busEvent) {
- rebuildSubscriptionAndNotifyBusOfEffectiveImmediateChange(entitySqlDaoWrapperFactory, subscription, event, seqId, context);
+ rebuildSubscriptionAndNotifyBusOfEffectiveImmediateChange(entitySqlDaoWrapperFactory, subscription, event, seqId, catalog, context);
} else {
recordFutureNotificationFromTransaction(entitySqlDaoWrapperFactory,
event.getEffectiveDate(),
@@ -1060,9 +1056,9 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
// Sends bus notification for event on effective date -- only used for operation that happen immediately
private void rebuildSubscriptionAndNotifyBusOfEffectiveImmediateChange(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory, final DefaultSubscriptionBase subscription,
- final SubscriptionBaseEvent immediateEvent, final int seqId, final InternalCallContext context) {
+ final SubscriptionBaseEvent immediateEvent, final int seqId, final Catalog catalog, final InternalCallContext context) {
try {
- final DefaultSubscriptionBase upToDateSubscription = createSubscriptionWithNewEvent(subscription, immediateEvent, context);
+ final DefaultSubscriptionBase upToDateSubscription = createSubscriptionWithNewEvent(subscription, immediateEvent, catalog, context);
notifyBusOfEffectiveImmediateChange(entitySqlDaoWrapperFactory, upToDateSubscription, immediateEvent, seqId, context);
} catch (final CatalogApiException e) {
log.warn("Failed to post effective event for subscriptionId='{}'", subscription.getId(), e);
@@ -1145,7 +1141,7 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
//
// Creates a copy of the existing subscriptions whose 'transitions' will reflect the new event
//
- private DefaultSubscriptionBase createSubscriptionWithNewEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent newEvent, final InternalTenantContext context) throws CatalogApiException {
+ private DefaultSubscriptionBase createSubscriptionWithNewEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent newEvent, final Catalog catalog, final InternalTenantContext context) throws CatalogApiException {
final DefaultSubscriptionBase subscriptionWithNewEvent = new DefaultSubscriptionBase(subscription, null, clock);
final List<SubscriptionBaseEvent> allEvents = new LinkedList<SubscriptionBaseEvent>();
@@ -1153,17 +1149,10 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
allEvents.addAll(subscriptionWithNewEvent.getEvents());
}
allEvents.add(newEvent);
- subscriptionWithNewEvent.rebuildTransitions(allEvents, getFullCatalog(subscription.getId(), ObjectType.SUBSCRIPTION, context));
+ subscriptionWithNewEvent.rebuildTransitions(allEvents, catalog);
return subscriptionWithNewEvent;
}
- private Catalog getFullCatalog(final UUID objectId, final ObjectType objectType, final InternalTenantContext contextWithOrWithoutAccountId) throws CatalogApiException {
-
- final InternalTenantContext context = contextWithOrWithoutAccountId.getAccountRecordId() == null ?
- internalCallContextFactory.recreateInternalTenantContextWithAccountRecordId(objectId, objectType, contextWithOrWithoutAccountId) :
- contextWithOrWithoutAccountId;
- return catalogInternalApi.getFullCatalog(true, true, context);
- }
private InternalCallContext contextWithUpdatedDate(final InternalCallContext input) {
return new InternalCallContext(input, clock.getUTCNow());
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java
index 516d80c..be85bb2 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/SubscriptionDao.java
@@ -22,6 +22,7 @@ import java.util.UUID;
import org.killbill.billing.callcontext.InternalCallContext;
import org.killbill.billing.callcontext.InternalTenantContext;
+import org.killbill.billing.catalog.api.Catalog;
import org.killbill.billing.catalog.api.CatalogApiException;
import org.killbill.billing.entitlement.api.SubscriptionApiException;
import org.killbill.billing.subscription.api.SubscriptionBase;
@@ -54,17 +55,17 @@ public interface SubscriptionDao extends EntityDao<SubscriptionBundleModelDao, S
public SubscriptionBaseBundle createSubscriptionBundle(DefaultSubscriptionBaseBundle bundle, InternalCallContext context);
- public SubscriptionBase getSubscriptionFromId(UUID subscriptionId, InternalTenantContext context) throws CatalogApiException;
+ public SubscriptionBase getSubscriptionFromId(UUID subscriptionId, final Catalog catalog, InternalTenantContext context) throws CatalogApiException;
// ACCOUNT retrieval
public UUID getAccountIdFromSubscriptionId(UUID subscriptionId, InternalTenantContext context);
// SubscriptionBase retrieval
- public SubscriptionBase getBaseSubscription(UUID bundleId, InternalTenantContext context) throws CatalogApiException;
+ public SubscriptionBase getBaseSubscription(UUID bundleId, final Catalog catalog, InternalTenantContext context) throws CatalogApiException;
- public List<SubscriptionBase> getSubscriptions(UUID bundleId, List<SubscriptionBaseEvent> dryRunEvents, InternalTenantContext context) throws CatalogApiException;
+ public List<SubscriptionBase> getSubscriptions(UUID bundleId, List<SubscriptionBaseEvent> dryRunEvents, final Catalog catalog, InternalTenantContext context) throws CatalogApiException;
- public Map<UUID, List<SubscriptionBase>> getSubscriptionsForAccount(InternalTenantContext context) throws CatalogApiException;
+ public Map<UUID, List<SubscriptionBase>> getSubscriptionsForAccount(final Catalog catalog, InternalTenantContext context) throws CatalogApiException;
// Update
public void updateChargedThroughDate(DefaultSubscriptionBase subscription, InternalCallContext context);
@@ -81,24 +82,24 @@ public interface SubscriptionDao extends EntityDao<SubscriptionBundleModelDao, S
public List<SubscriptionBaseEvent> getPendingEventsForSubscription(UUID subscriptionId, InternalTenantContext context);
// SubscriptionBase creation, cancellation, changePlanWithRequestedDate apis
- public void createSubscription(DefaultSubscriptionBase subscription, List<SubscriptionBaseEvent> initialEvents, InternalCallContext context);
+ public void createSubscription(DefaultSubscriptionBase subscription, List<SubscriptionBaseEvent> initialEvents, final Catalog catalog, InternalCallContext context);
- public void createSubscriptionsWithAddOns(List<SubscriptionBaseWithAddOns> subscriptions, Map<UUID, List<SubscriptionBaseEvent>> initialEventsMap, InternalCallContext context);
+ public void createSubscriptionsWithAddOns(List<SubscriptionBaseWithAddOns> subscriptions, Map<UUID, List<SubscriptionBaseEvent>> initialEventsMap, final Catalog catalog, InternalCallContext context);
- public void cancelSubscriptionsOnBasePlanEvent(DefaultSubscriptionBase subscription, SubscriptionBaseEvent event, List<DefaultSubscriptionBase> subscriptions, List<SubscriptionBaseEvent> cancelEvents, InternalCallContext context);
+ public void cancelSubscriptionsOnBasePlanEvent(DefaultSubscriptionBase subscription, SubscriptionBaseEvent event, List<DefaultSubscriptionBase> subscriptions, List<SubscriptionBaseEvent> cancelEvents, final Catalog catalog, InternalCallContext context);
- public void notifyOnBasePlanEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, final InternalCallContext context);
+ public void notifyOnBasePlanEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, final Catalog catalog, final InternalCallContext context);
- public void cancelSubscriptions(List<DefaultSubscriptionBase> subscriptions, List<SubscriptionBaseEvent> cancelEvents, InternalCallContext context);
+ public void cancelSubscriptions(List<DefaultSubscriptionBase> subscriptions, List<SubscriptionBaseEvent> cancelEvents, final Catalog catalog, InternalCallContext context);
- public void uncancelSubscription(DefaultSubscriptionBase subscription, List<SubscriptionBaseEvent> uncancelEvents, InternalCallContext context);
+ public void uncancelSubscription(DefaultSubscriptionBase subscription, List<SubscriptionBaseEvent> uncancelEvents, final Catalog catalog, InternalCallContext context);
- public void changePlan(DefaultSubscriptionBase subscription, List<SubscriptionBaseEvent> changeEvents, List<DefaultSubscriptionBase> subscriptionsToBeCancelled, List<SubscriptionBaseEvent> cancelEvents, InternalCallContext context);
+ public void changePlan(DefaultSubscriptionBase subscription, List<SubscriptionBaseEvent> changeEvents, List<DefaultSubscriptionBase> subscriptionsToBeCancelled, List<SubscriptionBaseEvent> cancelEvents, final Catalog catalog, InternalCallContext context);
- public void transfer(UUID srcAccountId, UUID destAccountId, BundleTransferData data, List<TransferCancelData> transferCancelData, InternalCallContext fromContext, InternalCallContext toContext);
+ public void transfer(UUID srcAccountId, UUID destAccountId, BundleTransferData data, List<TransferCancelData> transferCancelData, final Catalog catalog, InternalCallContext fromContext, InternalCallContext toContext);
public void updateBundleExternalKey(UUID bundleId, String externalKey, InternalCallContext context);
- public void createBCDChangeEvent(DefaultSubscriptionBase subscription, SubscriptionBaseEvent bcdEvent, InternalCallContext context);
+ public void createBCDChangeEvent(DefaultSubscriptionBase subscription, SubscriptionBaseEvent bcdEvent, final Catalog catalog, InternalCallContext context);
}
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/alignment/TestPlanAligner.java b/subscription/src/test/java/org/killbill/billing/subscription/alignment/TestPlanAligner.java
index 21a112f..7b2ec78 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/alignment/TestPlanAligner.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/alignment/TestPlanAligner.java
@@ -51,7 +51,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
@BeforeClass(groups = "fast")
public void beforeClass() throws Exception {
super.beforeClass();
- planAligner = new PlanAligner(catalogInternalApi);
+ planAligner = new PlanAligner();
}
@@ -75,7 +75,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
Assert.assertEquals(phases[1].getStartPhase(), defaultSubscriptionBase.getBundleStartDate().plusDays(30));
// Verify the next phase via the other API
- final TimedPhase nextTimePhase = planAligner.getNextTimedPhase(defaultSubscriptionBase, effectiveDate, internalCallContext);
+ final TimedPhase nextTimePhase = planAligner.getNextTimedPhase(defaultSubscriptionBase, effectiveDate, catalog, internalCallContext);
Assert.assertEquals(nextTimePhase.getStartPhase(), defaultSubscriptionBase.getBundleStartDate().plusDays(30));
// Now look at the past, before the bundle started
@@ -117,7 +117,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
Assert.assertEquals(phases[1].getStartPhase(), defaultSubscriptionBase.getStartDate().plusMonths(1));
// Verify the next phase via the other API
- final TimedPhase nextTimePhase = planAligner.getNextTimedPhase(defaultSubscriptionBase, effectiveDate, internalCallContext);
+ final TimedPhase nextTimePhase = planAligner.getNextTimedPhase(defaultSubscriptionBase, effectiveDate, catalog, internalCallContext);
Assert.assertEquals(nextTimePhase.getStartPhase(), defaultSubscriptionBase.getStartDate().plusMonths(1));
// Now look at the past, before the subscription started
@@ -152,7 +152,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
final DateTime alignStartDate = bundleStartDate;
final Plan plan = catalogService.getFullCatalog(true, true, internalCallContext).findPlan(productName, clock.getUTCNow());
- final TimedPhase [] phases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate, bundleStartDate, plan, PhaseType.EVERGREEN, PriceListSet.DEFAULT_PRICELIST_NAME, now, internalCallContext);
+ final TimedPhase [] phases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate, bundleStartDate, plan, PhaseType.EVERGREEN, PriceListSet.DEFAULT_PRICELIST_NAME, now, catalog, internalCallContext);
Assert.assertEquals(phases.length, 2);
Assert.assertEquals(phases[0].getPhase().getPhaseType(), PhaseType.EVERGREEN);
Assert.assertEquals(phases[0].getStartPhase(), now);
@@ -164,7 +164,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
final Plan newPlan = catalogService.getFullCatalog(true, true, internalCallContext).findPlan(newProductName, clock.getUTCNow());
final DateTime effectiveChangeDate = defaultSubscriptionBase.getStartDate().plusMonths(15);
- final TimedPhase currentPhase = planAligner.getCurrentTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, null, internalCallContext);
+ final TimedPhase currentPhase = planAligner.getCurrentTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, null, catalog, internalCallContext);
Assert.assertEquals(currentPhase.getStartPhase(), alignStartDate);
Assert.assertEquals(currentPhase.getPhase().getPhaseType(), PhaseType.EVERGREEN);
}
@@ -182,7 +182,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
final DateTime alignStartDate = bundleStartDate;
final Plan plan = catalogService.getFullCatalog(true, true, internalCallContext).findPlan(productName, clock.getUTCNow());
- final TimedPhase [] phases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate, bundleStartDate, plan, PhaseType.EVERGREEN, PriceListSet.DEFAULT_PRICELIST_NAME, now, internalCallContext);
+ final TimedPhase [] phases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate, bundleStartDate, plan, PhaseType.EVERGREEN, PriceListSet.DEFAULT_PRICELIST_NAME, now, catalog, internalCallContext);
Assert.assertEquals(phases.length, 2);
Assert.assertEquals(phases[0].getPhase().getPhaseType(), PhaseType.EVERGREEN);
Assert.assertEquals(phases[0].getStartPhase(), now);
@@ -194,7 +194,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
final Plan newPlan = catalogService.getFullCatalog(true, true, internalCallContext).findPlan(newProductName, clock.getUTCNow());
final DateTime effectiveChangeDate = defaultSubscriptionBase.getStartDate().plusMonths(15);
- final TimedPhase currentPhase = planAligner.getCurrentTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, null, internalCallContext);
+ final TimedPhase currentPhase = planAligner.getCurrentTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, null, catalog, internalCallContext);
Assert.assertEquals(currentPhase.getStartPhase(), alignStartDate);
Assert.assertEquals(currentPhase.getPhase().getPhaseType(), PhaseType.EVERGREEN);
}
@@ -212,7 +212,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
final DateTime alignStartDate = bundleStartDate;
final Plan plan = catalogService.getFullCatalog(true, true, internalCallContext).findPlan(productName, clock.getUTCNow());
- final TimedPhase [] phases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate, bundleStartDate, plan, PhaseType.EVERGREEN, PriceListSet.DEFAULT_PRICELIST_NAME, now, internalCallContext);
+ final TimedPhase [] phases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate, bundleStartDate, plan, PhaseType.EVERGREEN, PriceListSet.DEFAULT_PRICELIST_NAME, now, catalog, internalCallContext);
Assert.assertEquals(phases.length, 2);
Assert.assertEquals(phases[0].getPhase().getPhaseType(), PhaseType.EVERGREEN);
Assert.assertEquals(phases[0].getStartPhase(), now);
@@ -225,7 +225,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
final DateTime effectiveChangeDate = defaultSubscriptionBase.getStartDate().plusMonths(15);
// Because new Plan has an EVERGREEN PhaseType we end up directly on that PhaseType
- final TimedPhase currentPhase = planAligner.getCurrentTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, null, internalCallContext);
+ final TimedPhase currentPhase = planAligner.getCurrentTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, null, catalog, internalCallContext);
Assert.assertEquals(currentPhase.getStartPhase(), alignStartDate);
Assert.assertEquals(currentPhase.getPhase().getPhaseType(), PhaseType.EVERGREEN);
@@ -243,7 +243,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
final DateTime alignStartDate = bundleStartDate;
final Plan plan = catalogService.getFullCatalog(true, true, internalCallContext).findPlan(productName, clock.getUTCNow());
- final TimedPhase [] phases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate, bundleStartDate, plan, PhaseType.EVERGREEN, PriceListSet.DEFAULT_PRICELIST_NAME, now, internalCallContext);
+ final TimedPhase [] phases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate, bundleStartDate, plan, PhaseType.EVERGREEN, PriceListSet.DEFAULT_PRICELIST_NAME, now, catalog, internalCallContext);
Assert.assertEquals(phases.length, 2);
Assert.assertEquals(phases[0].getPhase().getPhaseType(), PhaseType.EVERGREEN);
Assert.assertEquals(phases[0].getStartPhase(), now);
@@ -256,7 +256,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
final DateTime effectiveChangeDate = defaultSubscriptionBase.getStartDate().plusMonths(15);
// Because new Plan has an EVERGREEN PhaseType we end up directly on that PhaseType
- final TimedPhase currentPhase = planAligner.getCurrentTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, null, internalCallContext);
+ final TimedPhase currentPhase = planAligner.getCurrentTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, null, catalog, internalCallContext);
Assert.assertEquals(currentPhase.getStartPhase(), alignStartDate);
Assert.assertEquals(currentPhase.getPhase().getPhaseType(), PhaseType.EVERGREEN);
}
@@ -273,7 +273,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
final DateTime alignStartDate = bundleStartDate;
final Plan plan = catalogService.getFullCatalog(true, true, internalCallContext).findPlan(productName, clock.getUTCNow());
- final TimedPhase [] phases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate, bundleStartDate, plan, PhaseType.EVERGREEN, PriceListSet.DEFAULT_PRICELIST_NAME, now, internalCallContext);
+ final TimedPhase [] phases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate, bundleStartDate, plan, PhaseType.EVERGREEN, PriceListSet.DEFAULT_PRICELIST_NAME, now, catalog, internalCallContext);
Assert.assertEquals(phases.length, 2);
Assert.assertEquals(phases[0].getPhase().getPhaseType(), PhaseType.EVERGREEN);
Assert.assertEquals(phases[0].getStartPhase(), now);
@@ -285,13 +285,13 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
final Plan newPlan = catalogService.getFullCatalog(true, true, internalCallContext).findPlan(newProductName, clock.getUTCNow());
final DateTime effectiveChangeDate = defaultSubscriptionBase.getStartDate().plusDays(5);
- final TimedPhase currentPhase = planAligner.getCurrentTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, null, internalCallContext);
+ final TimedPhase currentPhase = planAligner.getCurrentTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, null, catalog, internalCallContext);
// Initial phase EVERGREEN does not exist in the new Plan so we ignore the original skipped Phase and proceed with default alignment (we only move the clock 5 days so we are still in TRIAL)
Assert.assertEquals(currentPhase.getStartPhase(), alignStartDate);
Assert.assertEquals(currentPhase.getPhase().getPhaseType(), PhaseType.TRIAL);
- final TimedPhase nextPhase = planAligner.getNextTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, null, internalCallContext);
+ final TimedPhase nextPhase = planAligner.getNextTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, null, catalog, internalCallContext);
Assert.assertEquals(nextPhase.getStartPhase(), alignStartDate.plusDays(30));
Assert.assertEquals(nextPhase.getPhase().getPhaseType(), PhaseType.FIXEDTERM);
}
@@ -309,7 +309,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
final DateTime alignStartDate = bundleStartDate;
final Plan plan = catalogService.getFullCatalog(true, true, internalCallContext).findPlan(productName, clock.getUTCNow());
- final TimedPhase [] phases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate, bundleStartDate, plan, null, PriceListSet.DEFAULT_PRICELIST_NAME, now, internalCallContext);
+ final TimedPhase [] phases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate, bundleStartDate, plan, null, PriceListSet.DEFAULT_PRICELIST_NAME, now, catalog, internalCallContext);
Assert.assertEquals(phases.length, 2);
Assert.assertEquals(phases[0].getPhase().getPhaseType(), PhaseType.TRIAL);
Assert.assertEquals(phases[0].getStartPhase(), now);
@@ -322,13 +322,13 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
final Plan newPlan = catalogService.getFullCatalog(true, true, internalCallContext).findPlan(newProductName, clock.getUTCNow());
final DateTime effectiveChangeDate = defaultSubscriptionBase.getStartDate().plusDays(5);
- final TimedPhase currentPhase = planAligner.getCurrentTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, PhaseType.DISCOUNT, internalCallContext);
+ final TimedPhase currentPhase = planAligner.getCurrentTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, PhaseType.DISCOUNT, catalog, internalCallContext);
// We end up straight on DISCOUNT but because we are using START_OF_SUBSCRIPTION alignment, such Phase starts with beginning of subscription
Assert.assertEquals(currentPhase.getStartPhase(), alignStartDate);
Assert.assertEquals(currentPhase.getPhase().getPhaseType(), PhaseType.DISCOUNT);
- final TimedPhase nextPhase = planAligner.getNextTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, PhaseType.DISCOUNT, internalCallContext);
+ final TimedPhase nextPhase = planAligner.getNextTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, PhaseType.DISCOUNT, catalog, internalCallContext);
Assert.assertEquals(nextPhase.getStartPhase(), alignStartDate.plusMonths(6));
Assert.assertEquals(nextPhase.getPhase().getPhaseType(), PhaseType.EVERGREEN);
}
@@ -345,7 +345,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
final DateTime alignStartDate = bundleStartDate;
final Plan plan = catalogService.getFullCatalog(true, true, internalCallContext).findPlan(productName, clock.getUTCNow());
- final TimedPhase [] phases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate, bundleStartDate, plan, null, PriceListSet.DEFAULT_PRICELIST_NAME, now, internalCallContext);
+ final TimedPhase [] phases = planAligner.getCurrentAndNextTimedPhaseOnCreate(alignStartDate, bundleStartDate, plan, null, PriceListSet.DEFAULT_PRICELIST_NAME, now, catalog, internalCallContext);
Assert.assertEquals(phases.length, 2);
Assert.assertEquals(phases[0].getPhase().getPhaseType(), PhaseType.TRIAL);
Assert.assertEquals(phases[0].getStartPhase(), now);
@@ -358,13 +358,13 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
final Plan newPlan = catalogService.getFullCatalog(true, true, internalCallContext).findPlan(newProductName, clock.getUTCNow());
final DateTime effectiveChangeDate = defaultSubscriptionBase.getStartDate().plusDays(5);
- final TimedPhase currentPhase = planAligner.getCurrentTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, PhaseType.EVERGREEN, internalCallContext);
+ final TimedPhase currentPhase = planAligner.getCurrentTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, PhaseType.EVERGREEN, catalog, internalCallContext);
// We end up straight on EVERGREEN Phase and because we are CHANGE_OF_PLAN aligned the start is at the effective date of the change
Assert.assertEquals(currentPhase.getStartPhase(), alignStartDate.plusDays(5));
Assert.assertEquals(currentPhase.getPhase().getPhaseType(), PhaseType.EVERGREEN);
- final TimedPhase nextPhase = planAligner.getNextTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, PhaseType.EVERGREEN, internalCallContext);
+ final TimedPhase nextPhase = planAligner.getNextTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, PhaseType.EVERGREEN, catalog, internalCallContext);
Assert.assertNull(nextPhase);
}
@@ -444,7 +444,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
// The date is used for different catalog versions - we don't care here
final Plan newPlan = catalogService.getFullCatalog(true, true, internalCallContext).findPlan(newProductName, clock.getUTCNow());
- return planAligner.getNextTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, null, internalCallContext);
+ return planAligner.getNextTimedPhaseOnChange(defaultSubscriptionBase, newPlan, effectiveChangeDate, null, catalog, internalCallContext);
}
private TimedPhase[] getTimedPhasesOnCreate(final String productName,
@@ -456,7 +456,7 @@ public class TestPlanAligner extends SubscriptionTestSuiteNoDB {
// Same here for the requested date
final TimedPhase[] phases = planAligner.getCurrentAndNextTimedPhaseOnCreate(defaultSubscriptionBase.getAlignStartDate(), defaultSubscriptionBase.getBundleStartDate(),
- plan, initialPhase, priceList, effectiveDate, internalCallContext);
+ plan, initialPhase, priceList, effectiveDate, catalog, internalCallContext);
Assert.assertEquals(phases.length, 2);
return phases;
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/api/transfer/TestDefaultSubscriptionTransferApi.java b/subscription/src/test/java/org/killbill/billing/subscription/api/transfer/TestDefaultSubscriptionTransferApi.java
index 1f034e4..95ce7e2 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/api/transfer/TestDefaultSubscriptionTransferApi.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/api/transfer/TestDefaultSubscriptionTransferApi.java
@@ -74,6 +74,8 @@ public class TestDefaultSubscriptionTransferApi extends SubscriptionTestSuiteNoD
final SubscriptionBaseApiService apiService = Mockito.mock(SubscriptionBaseApiService.class);
final SubscriptionBaseTimelineApi timelineApi = Mockito.mock(SubscriptionBaseTimelineApi.class);
transferApi = new DefaultSubscriptionBaseTransferApi(clock, dao, timelineApi, catalogInternalApiWithMockCatalogService, apiService, internalCallContextFactory);
+ // Overrride catalog with our Mock CatalogService
+ this.catalog = catalogInternalApiWithMockCatalogService.getFullCatalog(true, true, internalCallContext);
}
@Test(groups = "fast")
@@ -86,7 +88,7 @@ public class TestDefaultSubscriptionTransferApi extends SubscriptionTestSuiteNoD
final DefaultSubscriptionBase subscription = new DefaultSubscriptionBase(subscriptionBuilder);
final DateTime transferDate = subscriptionStartTime.plusDays(10);
- final List<SubscriptionBaseEvent> events = transferApi.toEvents(existingEvents, subscription, transferDate, internalCallContext);
+ final List<SubscriptionBaseEvent> events = transferApi.toEvents(existingEvents, subscription, transferDate, catalog, internalCallContext);
Assert.assertEquals(events.size(), 0);
}
@@ -102,7 +104,7 @@ public class TestDefaultSubscriptionTransferApi extends SubscriptionTestSuiteNoD
final DefaultSubscriptionBase subscription = new DefaultSubscriptionBase(subscriptionBuilder);
final DateTime transferDate = subscriptionStartTime.plusHours(1);
- final List<SubscriptionBaseEvent> events = transferApi.toEvents(existingEvents, subscription, transferDate, internalCallContext);
+ final List<SubscriptionBaseEvent> events = transferApi.toEvents(existingEvents, subscription, transferDate, catalog, internalCallContext);
Assert.assertEquals(events.size(), 1);
Assert.assertEquals(events.get(0).getType(), EventType.API_USER);
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java b/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
index a4ae105..1c2af52 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
@@ -31,6 +31,7 @@ import java.util.UUID;
import org.joda.time.DateTime;
import org.killbill.billing.callcontext.InternalCallContext;
import org.killbill.billing.callcontext.InternalTenantContext;
+import org.killbill.billing.catalog.api.Catalog;
import org.killbill.billing.catalog.api.CatalogApiException;
import org.killbill.billing.catalog.api.CatalogService;
import org.killbill.billing.catalog.api.ProductCategory;
@@ -180,7 +181,7 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
}
@Override
- public SubscriptionBase getSubscriptionFromId(final UUID subscriptionId, final InternalTenantContext context) {
+ public SubscriptionBase getSubscriptionFromId(final UUID subscriptionId, final Catalog catalog, final InternalTenantContext context) {
for (final SubscriptionBase cur : subscriptions) {
if (cur.getId().equals(subscriptionId)) {
return buildSubscription((DefaultSubscriptionBase) cur, context);
@@ -209,7 +210,7 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
@Override
public void createSubscription(final DefaultSubscriptionBase subscription, final List<SubscriptionBaseEvent> initialEvents,
- final InternalCallContext context) {
+ final Catalog catalog, final InternalCallContext context) {
synchronized (events) {
events.addAll(initialEvents);
for (final SubscriptionBaseEvent cur : initialEvents) {
@@ -224,6 +225,7 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
@Override
public void createSubscriptionsWithAddOns(final List<SubscriptionBaseWithAddOns> subscriptions,
final Map<UUID, List<SubscriptionBaseEvent>> initialEventsMap,
+ final Catalog catalog,
final InternalCallContext context) {
synchronized (events) {
for (final SubscriptionBaseWithAddOns subscription : subscriptions) {
@@ -242,7 +244,7 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
}
@Override
- public List<SubscriptionBase> getSubscriptions(final UUID bundleId, final List<SubscriptionBaseEvent> dryRunEvents, final InternalTenantContext context) {
+ public List<SubscriptionBase> getSubscriptions(final UUID bundleId, final List<SubscriptionBaseEvent> dryRunEvents, final Catalog catalog, final InternalTenantContext context) {
final List<SubscriptionBase> results = new ArrayList<SubscriptionBase>();
for (final SubscriptionBase cur : subscriptions) {
if (cur.getBundleId().equals(bundleId)) {
@@ -253,7 +255,7 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
}
@Override
- public Map<UUID, List<SubscriptionBase>> getSubscriptionsForAccount(final InternalTenantContext context) {
+ public Map<UUID, List<SubscriptionBase>> getSubscriptionsForAccount(final Catalog catalog, final InternalTenantContext context) {
final Map<UUID, List<SubscriptionBase>> results = new HashMap<UUID, List<SubscriptionBase>>();
for (final SubscriptionBase cur : subscriptions) {
if (results.get(cur.getBundleId()) == null) {
@@ -293,7 +295,7 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
}
@Override
- public SubscriptionBase getBaseSubscription(final UUID bundleId, final InternalTenantContext context) {
+ public SubscriptionBase getBaseSubscription(final UUID bundleId, final Catalog catalog, final InternalTenantContext context) {
for (final SubscriptionBase cur : subscriptions) {
if (cur.getBundleId().equals(bundleId) &&
cur.getCurrentPlan().getProduct().getCategory() == ProductCategory.BASE) {
@@ -305,7 +307,7 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
@Override
public void createNextPhaseEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent readyPhaseEvent, final SubscriptionBaseEvent nextPhase, final InternalCallContext context) {
- cancelNextPhaseEvent(subscription.getId(), context);
+ cancelNextPhaseEvent(subscription.getId(), null, context);
insertEvent(nextPhase, context);
notifyBusOfEffectiveImmediateChange(subscription, readyPhaseEvent, 0, context);
}
@@ -341,38 +343,38 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
}
@Override
- public void cancelSubscriptionsOnBasePlanEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, final List<DefaultSubscriptionBase> subscriptions, final List<SubscriptionBaseEvent> cancelEvents, final InternalCallContext context) {
- cancelSubscriptions(subscriptions, cancelEvents, context);
+ public void cancelSubscriptionsOnBasePlanEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, final List<DefaultSubscriptionBase> subscriptions, final List<SubscriptionBaseEvent> cancelEvents, final Catalog catalog, final InternalCallContext context) {
+ cancelSubscriptions(subscriptions, cancelEvents, catalog, context);
notifyBusOfEffectiveImmediateChange(subscription, event, subscriptions.size(), context);
}
@Override
- public void notifyOnBasePlanEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, final InternalCallContext context) {
+ public void notifyOnBasePlanEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, final Catalog catalog, final InternalCallContext context) {
notifyBusOfEffectiveImmediateChange(subscription, event, subscriptions.size(), context);
}
@Override
- public void cancelSubscriptions(final List<DefaultSubscriptionBase> subscriptions, final List<SubscriptionBaseEvent> cancelEvents, final InternalCallContext context) {
+ public void cancelSubscriptions(final List<DefaultSubscriptionBase> subscriptions, final List<SubscriptionBaseEvent> cancelEvents, final Catalog catalog, final InternalCallContext context) {
synchronized (events) {
for (int i = 0; i < subscriptions.size(); i++) {
- cancelNextPhaseEvent(subscriptions.get(i).getId(), context);
+ cancelNextPhaseEvent(subscriptions.get(i).getId(), catalog, context);
insertEvent(cancelEvents.get(i), context);
}
}
}
@Override
- public void changePlan(final DefaultSubscriptionBase subscription, final List<SubscriptionBaseEvent> changeEvents, final List<DefaultSubscriptionBase> subscriptionsToBeCancelled, final List<SubscriptionBaseEvent> cancelEvents, final InternalCallContext context) {
+ public void changePlan(final DefaultSubscriptionBase subscription, final List<SubscriptionBaseEvent> changeEvents, final List<DefaultSubscriptionBase> subscriptionsToBeCancelled, final List<SubscriptionBaseEvent> cancelEvents, final Catalog catalog, final InternalCallContext context) {
synchronized (events) {
cancelNextChangeEvent(subscription.getId());
- cancelNextPhaseEvent(subscription.getId(), context);
+ cancelNextPhaseEvent(subscription.getId(), catalog, context);
events.addAll(changeEvents);
for (final SubscriptionBaseEvent cur : changeEvents) {
recordFutureNotificationFromTransaction(null, cur.getEffectiveDate(), new SubscriptionNotificationKey(cur.getId()), context);
}
}
- cancelSubscriptions(subscriptionsToBeCancelled, cancelEvents, context);
+ cancelSubscriptions(subscriptionsToBeCancelled, cancelEvents, catalog, context);
}
private void insertEvent(final SubscriptionBaseEvent event, final InternalCallContext context) {
@@ -383,8 +385,8 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
}
}
- private void cancelNextPhaseEvent(final UUID subscriptionId, final InternalTenantContext context) {
- final SubscriptionBase curSubscription = getSubscriptionFromId(subscriptionId, context);
+ private void cancelNextPhaseEvent(final UUID subscriptionId, final Catalog catalog, final InternalTenantContext context) {
+ final SubscriptionBase curSubscription = getSubscriptionFromId(subscriptionId, catalog, context);
if (curSubscription.getCurrentPhase() == null ||
curSubscription.getCurrentPhase().getDuration().getUnit() == TimeUnit.UNLIMITED) {
return;
@@ -430,7 +432,7 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
@Override
public void uncancelSubscription(final DefaultSubscriptionBase subscription, final List<SubscriptionBaseEvent> uncancelEvents,
- final InternalCallContext context) {
+ final Catalog catalog, final InternalCallContext context) {
synchronized (events) {
boolean foundCancel = false;
@@ -502,7 +504,7 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
@Override
public void transfer(final UUID srcAccountId, final UUID destAccountId, final BundleTransferData data,
- final List<TransferCancelData> transferCancelData, final InternalCallContext fromContext,
+ final List<TransferCancelData> transferCancelData, final Catalog catalog, final InternalCallContext fromContext,
final InternalCallContext toContext) {
}
@@ -511,7 +513,7 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
}
@Override
- public void createBCDChangeEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent bcdEvent, final InternalCallContext context) {
+ public void createBCDChangeEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent bcdEvent, final Catalog catalog, final InternalCallContext context) {
}
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoSql.java b/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoSql.java
index a5b2251..790ef04 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoSql.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoSql.java
@@ -36,8 +36,8 @@ public class MockSubscriptionDaoSql extends DefaultSubscriptionDao {
@Inject
public MockSubscriptionDaoSql(final IDBI dbi, final Clock clock, final AddonUtils addonUtils, final NotificationQueueService notificationQueueService,
- final PersistentBus eventBus, final CatalogInternalApi catalogService, final CacheControllerDispatcher cacheControllerDispatcher,
+ final PersistentBus eventBus, final CacheControllerDispatcher cacheControllerDispatcher,
final NonEntityDao nonEntityDao, final InternalCallContextFactory internalCallContextFactory) {
- super(dbi, clock, addonUtils, notificationQueueService, eventBus, catalogService, cacheControllerDispatcher, nonEntityDao, internalCallContextFactory);
+ super(dbi, clock, addonUtils, notificationQueueService, eventBus, cacheControllerDispatcher, nonEntityDao, internalCallContextFactory);
}
}