killbill-uncached
Changes
entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java 281(+181 -100)
entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java 232(+91 -141)
entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementContext.java 13(+11 -2)
entitlement/src/main/java/org/killbill/billing/entitlement/api/EntitlementPluginExecution.java 113(+113 -0)
entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementInternalApi.java 8(+6 -2)
entitlement/src/main/java/org/killbill/billing/entitlement/glue/DefaultEntitlementModule.java 2(+2 -0)
entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultEntitlement.java 35(+19 -16)
entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultEntitlementApi.java 55(+29 -26)
entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultSubscriptionApi.java 23(+13 -10)
entitlement/src/test/java/org/killbill/billing/entitlement/dao/TestDefaultBlockingStateDao.java 5(+4 -1)
entitlement/src/test/java/org/killbill/billing/entitlement/engine/core/TestEntitlementUtils.java 33(+17 -16)
Details
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java
index 004a24f..97583ac 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java
@@ -35,6 +35,10 @@ import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
import org.killbill.billing.catalog.api.PriceList;
import org.killbill.billing.catalog.api.Product;
import org.killbill.billing.catalog.api.ProductCategory;
+import org.killbill.billing.entitlement.api.EntitlementPluginExecution.WithEntitlementPlugin;
+import org.killbill.billing.entitlement.plugin.api.EntitlementContext;
+import org.killbill.billing.entitlement.plugin.api.OperationType;
+import org.killbill.billing.payment.api.PluginProperty;
import org.killbill.clock.Clock;
import org.killbill.billing.entitlement.DefaultEntitlementService;
import org.killbill.billing.entitlement.EntitlementService;
@@ -66,6 +70,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
protected final Clock clock;
protected final BlockingChecker checker;
protected final EntitlementApi entitlementApi;
+ protected final EntitlementPluginExecution pluginExecution;
protected final SubscriptionBaseInternalApi subscriptionInternalApi;
protected final BlockingStateDao blockingStateDao;
protected final NotificationQueueService notificationQueueService;
@@ -74,19 +79,20 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
// Refresh-able
protected EventsStream eventsStream;
+
public DefaultEntitlement(final UUID entitlementId, final EventsStreamBuilder eventsStreamBuilder,
- final EntitlementApi entitlementApi, final BlockingStateDao blockingStateDao,
+ final EntitlementApi entitlementApi, final EntitlementPluginExecution pluginExecution, final BlockingStateDao blockingStateDao,
final SubscriptionBaseInternalApi subscriptionInternalApi, final BlockingChecker checker,
final NotificationQueueService notificationQueueService, final EntitlementUtils entitlementUtils,
final EntitlementDateHelper dateHelper, final Clock clock,
final InternalCallContextFactory internalCallContextFactory, final TenantContext tenantContext) throws EntitlementApiException {
this(eventsStreamBuilder.buildForEntitlement(entitlementId, tenantContext), eventsStreamBuilder,
- entitlementApi, blockingStateDao, subscriptionInternalApi, checker, notificationQueueService,
+ entitlementApi, pluginExecution, blockingStateDao, subscriptionInternalApi, checker, notificationQueueService,
entitlementUtils, dateHelper, clock, internalCallContextFactory);
}
public DefaultEntitlement(final EventsStream eventsStream, final EventsStreamBuilder eventsStreamBuilder,
- final EntitlementApi entitlementApi, final BlockingStateDao blockingStateDao,
+ final EntitlementApi entitlementApi, final EntitlementPluginExecution pluginExecution, final BlockingStateDao blockingStateDao,
final SubscriptionBaseInternalApi subscriptionInternalApi, final BlockingChecker checker,
final NotificationQueueService notificationQueueService, final EntitlementUtils entitlementUtils,
final EntitlementDateHelper dateHelper, final Clock clock, final InternalCallContextFactory internalCallContextFactory) {
@@ -95,6 +101,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
this.eventsStream = eventsStream;
this.dateHelper = dateHelper;
this.entitlementApi = entitlementApi;
+ this.pluginExecution = pluginExecution;
this.subscriptionInternalApi = subscriptionInternalApi;
this.internalCallContextFactory = internalCallContextFactory;
this.clock = clock;
@@ -108,6 +115,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
this(in.getEventsStream(),
in.getEventsStreamBuilder(),
in.getEntitlementApi(),
+ in.getPluginExecution(),
in.getBlockingStateDao(),
in.getSubscriptionInternalApi(),
in.getChecker(),
@@ -152,6 +160,10 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
return entitlementApi;
}
+ public EntitlementPluginExecution getPluginExecution() {
+ return pluginExecution;
+ }
+
public SubscriptionBaseInternalApi getSubscriptionInternalApi() {
return subscriptionInternalApi;
}
@@ -242,16 +254,16 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
}
@Override
- public Entitlement cancelEntitlementWithPolicy(final EntitlementActionPolicy entitlementPolicy, final CallContext callContext) throws EntitlementApiException {
+ public Entitlement cancelEntitlementWithPolicy(final EntitlementActionPolicy entitlementPolicy, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
// Get the latest state from disk - required to have the latest CTD
refresh(callContext);
final LocalDate cancellationDate = getLocalDateFromEntitlementPolicy(entitlementPolicy);
- return cancelEntitlementWithDate(cancellationDate, false, callContext);
+ return cancelEntitlementWithDate(cancellationDate, false, properties, callContext);
}
@Override
- public Entitlement cancelEntitlementWithDate(final LocalDate localCancelDate, final boolean overrideBillingEffectiveDate, final CallContext callContext) throws EntitlementApiException {
+ public Entitlement cancelEntitlementWithDate(final LocalDate localCancelDate, final boolean overrideBillingEffectiveDate, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
// Get the latest state from disk
refresh(callContext);
@@ -280,16 +292,16 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
}
@Override
- public Entitlement cancelEntitlementWithPolicyOverrideBillingPolicy(final EntitlementActionPolicy entitlementPolicy, final BillingActionPolicy billingPolicy, final CallContext callContext) throws EntitlementApiException {
+ public Entitlement cancelEntitlementWithPolicyOverrideBillingPolicy(final EntitlementActionPolicy entitlementPolicy, final BillingActionPolicy billingPolicy, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
// Get the latest state from disk - required to have the latest CTD
refresh(callContext);
final LocalDate cancellationDate = getLocalDateFromEntitlementPolicy(entitlementPolicy);
- return cancelEntitlementWithDateOverrideBillingPolicy(cancellationDate, billingPolicy, callContext);
+ return cancelEntitlementWithDateOverrideBillingPolicy(cancellationDate, billingPolicy, properties, callContext);
}
@Override
- public void uncancelEntitlement(final CallContext callContext) throws EntitlementApiException {
+ public void uncancelEntitlement(final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
// Get the latest state from disk
refresh(callContext);
@@ -328,34 +340,52 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
}
@Override
- public Entitlement cancelEntitlementWithDateOverrideBillingPolicy(final LocalDate localCancelDate, final BillingActionPolicy billingPolicy, final CallContext callContext) throws EntitlementApiException {
+ public Entitlement cancelEntitlementWithDateOverrideBillingPolicy(final LocalDate localCancelDate, final BillingActionPolicy billingPolicy, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
+
// Get the latest state from disk
refresh(callContext);
- if (eventsStream.isEntitlementCancelled()) {
- throw new EntitlementApiException(ErrorCode.SUB_CANCEL_BAD_STATE, getId(), EntitlementState.CANCELLED);
- }
-
- // Make sure to compute the entitlement effective date first to avoid timing issues for IMM cancellations
- // (we don't want an entitlement cancel date one second or so after the subscription cancel date or add-ons cancellations
- // computations won't work).
- final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
- final LocalDate effectiveLocalDate = new LocalDate(localCancelDate, eventsStream.getAccountTimeZone());
- final DateTime effectiveDate = dateHelper.fromLocalDateAndReferenceTime(effectiveLocalDate, getSubscriptionBase().getStartDate(), contextWithValidAccountRecordId);
-
- try {
- // Cancel subscription base first, to correctly compute the add-ons entitlements we need to cancel (see below)
- getSubscriptionBase().cancelWithPolicy(billingPolicy, callContext);
- } catch (SubscriptionBaseApiException e) {
- throw new EntitlementApiException(e);
- }
-
- final BlockingState newBlockingState = new DefaultBlockingState(getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_CANCELLED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, false, effectiveDate);
- entitlementUtils.setBlockingStateAndPostBlockingTransitionEvent(newBlockingState, contextWithValidAccountRecordId);
-
- blockAddOnsIfRequired(effectiveDate, callContext, contextWithValidAccountRecordId);
-
- return entitlementApi.getEntitlementForId(getId(), callContext);
+ final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CANCEL_SUBSCRIPTION,
+ getAccountId(),
+ null,
+ getBundleId(),
+ null,
+ getExternalKey(),
+ null,
+ localCancelDate,
+ properties,
+ callContext);
+
+ final WithEntitlementPlugin<Entitlement> cancelEntitlementWithPlugin = new WithEntitlementPlugin<Entitlement>() {
+ @Override
+ public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ if (eventsStream.isEntitlementCancelled()) {
+ throw new EntitlementApiException(ErrorCode.SUB_CANCEL_BAD_STATE, getId(), EntitlementState.CANCELLED);
+ }
+
+ // Make sure to compute the entitlement effective date first to avoid timing issues for IMM cancellations
+ // (we don't want an entitlement cancel date one second or so after the subscription cancel date or add-ons cancellations
+ // computations won't work).
+ final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
+ final LocalDate effectiveLocalDate = new LocalDate(updatedPluginContext.getEffectiveDate(), eventsStream.getAccountTimeZone());
+ final DateTime effectiveDate = dateHelper.fromLocalDateAndReferenceTime(effectiveLocalDate, getSubscriptionBase().getStartDate(), contextWithValidAccountRecordId);
+
+ try {
+ // Cancel subscription base first, to correctly compute the add-ons entitlements we need to cancel (see below)
+ getSubscriptionBase().cancelWithPolicy(billingPolicy, callContext);
+ } catch (SubscriptionBaseApiException e) {
+ throw new EntitlementApiException(e);
+ }
+
+ final BlockingState newBlockingState = new DefaultBlockingState(getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_CANCELLED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, false, effectiveDate);
+ entitlementUtils.setBlockingStateAndPostBlockingTransitionEvent(newBlockingState, contextWithValidAccountRecordId);
+
+ blockAddOnsIfRequired(effectiveDate, callContext, contextWithValidAccountRecordId);
+
+ return entitlementApi.getEntitlementForId(getId(), callContext);
+ }
+ };
+ return pluginExecution.executeWithPlugin(cancelEntitlementWithPlugin, pluginContext);
}
private LocalDate getLocalDateFromEntitlementPolicy(final EntitlementActionPolicy entitlementPolicy) {
@@ -374,87 +404,138 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
}
@Override
- public Entitlement changePlan(final String productName, final BillingPeriod billingPeriod, final String priceList, final List<PlanPhasePriceOverride> overrides, final CallContext callContext) throws EntitlementApiException {
+ public Entitlement changePlan(final String productName, final BillingPeriod billingPeriod, final String priceList, final List<PlanPhasePriceOverride> overrides, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
// Get the latest state from disk
refresh(callContext);
- if (!eventsStream.isEntitlementActive()) {
- throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), getState());
- }
-
- final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
- try {
- checker.checkBlockedChange(getSubscriptionBase(), context);
- } catch (BlockingApiException e) {
- throw new EntitlementApiException(e, e.getCode(), e.getMessage());
- }
-
- final DateTime effectiveChangeDate;
- try {
- effectiveChangeDate = getSubscriptionBase().changePlan(productName, billingPeriod, priceList, overrides, callContext);
- } catch (SubscriptionBaseApiException e) {
- throw new EntitlementApiException(e);
- }
-
- blockAddOnsIfRequired(effectiveChangeDate, callContext, context);
-
- return entitlementApi.getEntitlementForId(getId(), callContext);
+ final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CHANGE_PLAN,
+ getAccountId(),
+ null,
+ getBundleId(),
+ null,
+ getExternalKey(),
+ null,
+ null,
+ properties,
+ callContext);
+
+ final WithEntitlementPlugin<Entitlement> changePlanWithPlugin = new WithEntitlementPlugin<Entitlement>() {
+ @Override
+ public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ if (!eventsStream.isEntitlementActive()) {
+ throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), getState());
+ }
+
+ final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
+ try {
+ checker.checkBlockedChange(getSubscriptionBase(), context);
+ } catch (BlockingApiException e) {
+ throw new EntitlementApiException(e, e.getCode(), e.getMessage());
+ }
+
+ final DateTime effectiveChangeDate;
+ try {
+ effectiveChangeDate = getSubscriptionBase().changePlan(productName, billingPeriod, priceList, overrides, callContext);
+ } catch (SubscriptionBaseApiException e) {
+ throw new EntitlementApiException(e);
+ }
+
+ blockAddOnsIfRequired(effectiveChangeDate, callContext, context);
+
+ return entitlementApi.getEntitlementForId(getId(), callContext);
+ }
+ };
+ return pluginExecution.executeWithPlugin(changePlanWithPlugin, pluginContext);
}
@Override
- public Entitlement changePlanWithDate(final String productName, final BillingPeriod billingPeriod, final String priceList, final List<PlanPhasePriceOverride> overrides, final LocalDate localDate, final CallContext callContext) throws EntitlementApiException {
+ public Entitlement changePlanWithDate(final String productName, final BillingPeriod billingPeriod, final String priceList, final List<PlanPhasePriceOverride> overrides, final LocalDate localDate, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
// Get the latest state from disk
refresh(callContext);
- if (!eventsStream.isEntitlementActive()) {
- throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), getState());
- }
-
- final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
- try {
- checker.checkBlockedChange(getSubscriptionBase(), context);
- } catch (BlockingApiException e) {
- throw new EntitlementApiException(e, e.getCode(), e.getMessage());
- }
-
- final DateTime effectiveChangeDate = dateHelper.fromLocalDateAndReferenceTime(localDate, getSubscriptionBase().getStartDate(), context);
- try {
- getSubscriptionBase().changePlanWithDate(productName, billingPeriod, priceList, overrides, effectiveChangeDate, callContext);
- } catch (SubscriptionBaseApiException e) {
- throw new EntitlementApiException(e);
- }
-
- blockAddOnsIfRequired(effectiveChangeDate, callContext, context);
-
- return entitlementApi.getEntitlementForId(getId(), callContext);
+ final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CHANGE_PLAN,
+ getAccountId(),
+ null,
+ getBundleId(),
+ null,
+ getExternalKey(),
+ null,
+ localDate,
+ properties,
+ callContext);
+
+ final WithEntitlementPlugin<Entitlement> changePlanWithPlugin = new WithEntitlementPlugin<Entitlement>() {
+ @Override
+ public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ if (!eventsStream.isEntitlementActive()) {
+ throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), getState());
+ }
+
+ final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
+ try {
+ checker.checkBlockedChange(getSubscriptionBase(), context);
+ } catch (BlockingApiException e) {
+ throw new EntitlementApiException(e, e.getCode(), e.getMessage());
+ }
+
+ final DateTime effectiveChangeDate = dateHelper.fromLocalDateAndReferenceTime(updatedPluginContext.getEffectiveDate(), getSubscriptionBase().getStartDate(), context);
+ try {
+ getSubscriptionBase().changePlanWithDate(productName, billingPeriod, priceList, overrides, effectiveChangeDate, callContext);
+ } catch (SubscriptionBaseApiException e) {
+ throw new EntitlementApiException(e);
+ }
+
+ blockAddOnsIfRequired(effectiveChangeDate, callContext, context);
+
+ return entitlementApi.getEntitlementForId(getId(), callContext);
+ }
+ };
+ return pluginExecution.executeWithPlugin(changePlanWithPlugin, pluginContext);
}
@Override
- public Entitlement changePlanOverrideBillingPolicy(final String productName, final BillingPeriod billingPeriod, final String priceList, final List<PlanPhasePriceOverride> overrides, final LocalDate localDate, final BillingActionPolicy actionPolicy, final CallContext callContext) throws EntitlementApiException {
+ public Entitlement changePlanOverrideBillingPolicy(final String productName, final BillingPeriod billingPeriod, final String priceList, final List<PlanPhasePriceOverride> overrides, final LocalDate localDate, final BillingActionPolicy actionPolicy, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
// Get the latest state from disk
refresh(callContext);
- if (!eventsStream.isEntitlementActive()) {
- throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), getState());
- }
-
- final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
- try {
- checker.checkBlockedChange(getSubscriptionBase(), context);
- } catch (BlockingApiException e) {
- throw new EntitlementApiException(e, e.getCode(), e.getMessage());
- }
-
- final DateTime effectiveChangeDate;
- try {
- effectiveChangeDate = getSubscriptionBase().changePlanWithPolicy(productName, billingPeriod, priceList, overrides, actionPolicy, callContext);
- } catch (SubscriptionBaseApiException e) {
- throw new EntitlementApiException(e);
- }
-
- blockAddOnsIfRequired(effectiveChangeDate, callContext, context);
-
- return entitlementApi.getEntitlementForId(getId(), callContext);
+ final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CHANGE_PLAN,
+ getAccountId(),
+ null,
+ getBundleId(),
+ null,
+ getExternalKey(),
+ null,
+ localDate,
+ properties,
+ callContext);
+
+ final WithEntitlementPlugin<Entitlement> changePlanWithPlugin = new WithEntitlementPlugin<Entitlement>() {
+ @Override
+ public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ if (!eventsStream.isEntitlementActive()) {
+ throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), getState());
+ }
+
+ final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
+ try {
+ checker.checkBlockedChange(getSubscriptionBase(), context);
+ } catch (BlockingApiException e) {
+ throw new EntitlementApiException(e, e.getCode(), e.getMessage());
+ }
+
+ final DateTime effectiveChangeDate;
+ try {
+ effectiveChangeDate = getSubscriptionBase().changePlanWithPolicy(productName, billingPeriod, priceList, overrides, actionPolicy, callContext);
+ } catch (SubscriptionBaseApiException e) {
+ throw new EntitlementApiException(e);
+ }
+
+ blockAddOnsIfRequired(effectiveChangeDate, callContext, context);
+
+ return entitlementApi.getEntitlementForId(getId(), callContext);
+ }
+ };
+ return pluginExecution.executeWithPlugin(changePlanWithPlugin, pluginContext);
}
private void refresh(final TenantContext context) throws EntitlementApiException {
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java
index 6736e28..7f2ecc6 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java
@@ -39,6 +39,7 @@ import org.killbill.billing.entitlement.DefaultEntitlementService;
import org.killbill.billing.entitlement.EntitlementService;
import org.killbill.billing.entitlement.EntitlementTransitionType;
import org.killbill.billing.entitlement.EventsStream;
+import org.killbill.billing.entitlement.api.EntitlementPluginExecution.WithEntitlementPlugin;
import org.killbill.billing.entitlement.block.BlockingChecker;
import org.killbill.billing.entitlement.dao.BlockingStateDao;
import org.killbill.billing.entitlement.engine.core.EntitlementNotificationKey;
@@ -46,14 +47,9 @@ import org.killbill.billing.entitlement.engine.core.EntitlementNotificationKeyAc
import org.killbill.billing.entitlement.engine.core.EntitlementUtils;
import org.killbill.billing.entitlement.engine.core.EventsStreamBuilder;
import org.killbill.billing.entitlement.plugin.api.EntitlementContext;
-import org.killbill.billing.entitlement.plugin.api.EntitlementPluginApi;
-import org.killbill.billing.entitlement.plugin.api.EntitlementPluginApiException;
-import org.killbill.billing.entitlement.plugin.api.OnFailureEntitlementResult;
-import org.killbill.billing.entitlement.plugin.api.OnSuccessEntitlementResult;
import org.killbill.billing.entitlement.plugin.api.OperationType;
-import org.killbill.billing.entitlement.plugin.api.PriorEntitlementResult;
import org.killbill.billing.junction.DefaultBlockingState;
-import org.killbill.billing.osgi.api.OSGIServiceRegistration;
+import org.killbill.billing.payment.api.PluginProperty;
import org.killbill.billing.subscription.api.SubscriptionBase;
import org.killbill.billing.subscription.api.SubscriptionBaseInternalApi;
import org.killbill.billing.subscription.api.transfer.SubscriptionBaseTransferApi;
@@ -99,7 +95,7 @@ public class DefaultEntitlementApi implements EntitlementApi {
private final EventsStreamBuilder eventsStreamBuilder;
private final EntitlementUtils entitlementUtils;
private final NotificationQueueService notificationQueueService;
- private final OSGIServiceRegistration<EntitlementPluginApi> pluginRegistry;
+ private final EntitlementPluginExecution pluginExecution;
@Inject
public DefaultEntitlementApi(final PersistentBus eventBus, final InternalCallContextFactory internalCallContextFactory,
@@ -107,7 +103,7 @@ public class DefaultEntitlementApi implements EntitlementApi {
final AccountInternalApi accountApi, final BlockingStateDao blockingStateDao, final Clock clock,
final BlockingChecker checker, final NotificationQueueService notificationQueueService,
final EventsStreamBuilder eventsStreamBuilder, final EntitlementUtils entitlementUtils,
- final OSGIServiceRegistration<EntitlementPluginApi> pluginRegistry) {
+ final EntitlementPluginExecution pluginExecution) {
this.eventBus = eventBus;
this.internalCallContextFactory = internalCallContextFactory;
this.subscriptionBaseInternalApi = subscriptionInternalApi;
@@ -119,51 +115,27 @@ public class DefaultEntitlementApi implements EntitlementApi {
this.notificationQueueService = notificationQueueService;
this.eventsStreamBuilder = eventsStreamBuilder;
this.entitlementUtils = entitlementUtils;
- this.pluginRegistry = pluginRegistry;
+ this.pluginExecution = pluginExecution;
this.dateHelper = new EntitlementDateHelper(accountApi, clock);
}
- public interface WithEntitlementPlugin<T> {
- T doCall(final EntitlementApi entitlementApi) throws EntitlementApiException;
- }
-
- private <T> T executeWithPlugin(final WithEntitlementPlugin<T> callback, final EntitlementApi entitlementApi, final EntitlementContext pluginContext) throws EntitlementApiException {
-
- try {
- final PriorEntitlementResult priorEntitlementResult = executePluginPriorCalls(pluginContext);
- if (priorEntitlementResult != null && priorEntitlementResult.isAborted()) {
- throw new EntitlementApiException(ErrorCode.ENT_PLUGIN_API_ABORTED);
- }
- final EntitlementContext updatedPluginContext = new DefaultEntitlementContext(pluginContext, priorEntitlementResult);
- try {
- T result = callback.doCall(entitlementApi);
- executePluginOnSuccessCalls(updatedPluginContext);
- return result;
- } catch (final EntitlementApiException e) {
- executePluginOnFailureCalls(updatedPluginContext);
- throw e;
- }
- } catch (final EntitlementPluginApiException e) {
- throw new EntitlementApiException(ErrorCode.ENT_PLUGIN_API_ABORTED, e.getMessage());
- }
- }
-
@Override
- public Entitlement createBaseEntitlement(final UUID accountId, final PlanPhaseSpecifier planPhaseSpecifier, final String externalKey, final List<PlanPhasePriceOverride> overrides, final LocalDate effectiveDate, final CallContext callContext) throws EntitlementApiException {
+ public Entitlement createBaseEntitlement(final UUID accountId, final PlanPhaseSpecifier planPhaseSpecifier, final String externalKey, final List<PlanPhasePriceOverride> overrides, final LocalDate effectiveDate, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CREATE_SUBSCRIPTION,
accountId,
null,
+ null,
planPhaseSpecifier,
externalKey,
overrides,
effectiveDate,
- null,
+ properties,
callContext);
final WithEntitlementPlugin<Entitlement> createBaseEntitlementWithPlugin = new WithEntitlementPlugin<Entitlement>() {
@Override
- public Entitlement doCall(final EntitlementApi entitlementApi) throws EntitlementApiException {
+ public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(accountId, callContext);
try {
@@ -171,14 +143,13 @@ public class DefaultEntitlementApi implements EntitlementApi {
throw new EntitlementApiException(new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_ACTIVE_BUNDLE_KEY_EXISTS, externalKey));
}
-
final SubscriptionBaseBundle bundle = subscriptionBaseInternalApi.createBundleForAccount(accountId, externalKey, contextWithValidAccountRecordId);
final DateTime referenceTime = clock.getUTCNow();
- final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(effectiveDate, referenceTime, contextWithValidAccountRecordId);
- final SubscriptionBase subscription = subscriptionBaseInternalApi.createSubscription(bundle.getId(), planPhaseSpecifier, overrides, requestedDate, contextWithValidAccountRecordId);
+ final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(updatedPluginContext.getEffectiveDate(), referenceTime, contextWithValidAccountRecordId);
+ final SubscriptionBase subscription = subscriptionBaseInternalApi.createSubscription(bundle.getId(), updatedPluginContext.getPlanPhaseSpecifier(), updatedPluginContext.getPlanPhasePriceOverride(), requestedDate, contextWithValidAccountRecordId);
- return new DefaultEntitlement(subscription.getId(), eventsStreamBuilder, entitlementApi,
+ return new DefaultEntitlement(subscription.getId(), eventsStreamBuilder, entitlementApi, pluginExecution,
blockingStateDao, subscriptionBaseInternalApi, checker, notificationQueueService,
entitlementUtils, dateHelper, clock, internalCallContextFactory, callContext);
} catch (SubscriptionBaseApiException e) {
@@ -186,25 +157,26 @@ public class DefaultEntitlementApi implements EntitlementApi {
}
}
};
- return executeWithPlugin(createBaseEntitlementWithPlugin, this, pluginContext);
+ return pluginExecution.executeWithPlugin(createBaseEntitlementWithPlugin, pluginContext);
}
@Override
- public Entitlement addEntitlement(final UUID bundleId, final PlanPhaseSpecifier planPhaseSpecifier, final List<PlanPhasePriceOverride> overrides, final LocalDate effectiveDate, final CallContext callContext) throws EntitlementApiException {
+ public Entitlement addEntitlement(final UUID bundleId, final PlanPhaseSpecifier planPhaseSpecifier, final List<PlanPhasePriceOverride> overrides, final LocalDate effectiveDate, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CREATE_SUBSCRIPTION,
null,
+ null,
bundleId,
planPhaseSpecifier,
null,
overrides,
effectiveDate,
- null,
+ properties,
callContext);
final WithEntitlementPlugin<Entitlement> addEntitlementWithPlugin = new WithEntitlementPlugin<Entitlement>() {
@Override
- public Entitlement doCall(final EntitlementApi entitlementApi) throws EntitlementApiException {
+ public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
final EventsStream eventsStreamForBaseSubscription = eventsStreamBuilder.buildForBaseSubscription(bundleId, callContext);
// Check the base entitlement state is active
@@ -217,13 +189,13 @@ public class DefaultEntitlementApi implements EntitlementApi {
throw new EntitlementApiException(new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, BlockingChecker.ACTION_CHANGE, BlockingChecker.TYPE_SUBSCRIPTION, eventsStreamForBaseSubscription.getEntitlementId().toString()));
}
- final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(effectiveDate, eventsStreamForBaseSubscription.getSubscriptionBase().getStartDate(), eventsStreamForBaseSubscription.getInternalTenantContext());
+ final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(updatedPluginContext.getEffectiveDate(), eventsStreamForBaseSubscription.getSubscriptionBase().getStartDate(), eventsStreamForBaseSubscription.getInternalTenantContext());
try {
final InternalCallContext context = internalCallContextFactory.createInternalCallContext(callContext);
- final SubscriptionBase subscription = subscriptionBaseInternalApi.createSubscription(bundleId, planPhaseSpecifier, overrides, requestedDate, context);
+ final SubscriptionBase subscription = subscriptionBaseInternalApi.createSubscription(bundleId, updatedPluginContext.getPlanPhaseSpecifier(), updatedPluginContext.getPlanPhasePriceOverride(), requestedDate, context);
- return new DefaultEntitlement(subscription.getId(), eventsStreamBuilder, entitlementApi,
+ return new DefaultEntitlement(subscription.getId(), eventsStreamBuilder, entitlementApi, pluginExecution,
blockingStateDao, subscriptionBaseInternalApi, checker, notificationQueueService,
entitlementUtils, dateHelper, clock, internalCallContextFactory, callContext);
} catch (SubscriptionBaseApiException e) {
@@ -231,7 +203,7 @@ public class DefaultEntitlementApi implements EntitlementApi {
}
}
};
- return executeWithPlugin(addEntitlementWithPlugin, this, pluginContext);
+ return pluginExecution.executeWithPlugin(addEntitlementWithPlugin, pluginContext);
}
@Override
@@ -252,7 +224,7 @@ public class DefaultEntitlementApi implements EntitlementApi {
@Override
public Entitlement getEntitlementForId(final UUID uuid, final TenantContext tenantContext) throws EntitlementApiException {
final EventsStream eventsStream = eventsStreamBuilder.buildForEntitlement(uuid, tenantContext);
- return new DefaultEntitlement(eventsStream, eventsStreamBuilder, this,
+ return new DefaultEntitlement(eventsStream, eventsStreamBuilder, this, pluginExecution,
blockingStateDao, subscriptionBaseInternalApi, checker, notificationQueueService,
entitlementUtils, dateHelper, clock, internalCallContextFactory);
}
@@ -299,7 +271,7 @@ public class DefaultEntitlementApi implements EntitlementApi {
new Function<EventsStream, Entitlement>() {
@Override
public Entitlement apply(final EventsStream eventsStream) {
- return new DefaultEntitlement(eventsStream, eventsStreamBuilder, entitlementApi,
+ return new DefaultEntitlement(eventsStream, eventsStreamBuilder, entitlementApi, pluginExecution,
blockingStateDao, subscriptionBaseInternalApi, checker, notificationQueueService,
entitlementUtils, dateHelper, clock, internalCallContextFactory);
}
@@ -307,21 +279,22 @@ public class DefaultEntitlementApi implements EntitlementApi {
}
@Override
- public void pause(final UUID bundleId, final LocalDate localEffectiveDate, final CallContext context) throws EntitlementApiException {
+ public void pause(final UUID bundleId, final LocalDate localEffectiveDate, final Iterable<PluginProperty> properties, final CallContext context) throws EntitlementApiException {
final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.PAUSE_SUBSCRIPTION,
null,
+ null,
bundleId,
null,
null,
null,
localEffectiveDate,
- null,
+ properties,
context);
final WithEntitlementPlugin<Void> pauseWithPlugin = new WithEntitlementPlugin<Void>() {
@Override
- public Void doCall(final EntitlementApi entitlementApi) throws EntitlementApiException {
+ public Void doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
try {
final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(bundleId, ObjectType.BUNDLE, context);
final BlockingState currentState = blockingStateDao.getBlockingStateForService(bundleId, BlockingStateType.SUBSCRIPTION_BUNDLE, EntitlementService.ENTITLEMENT_SERVICE_NAME, contextWithValidAccountRecordId);
@@ -332,7 +305,7 @@ public class DefaultEntitlementApi implements EntitlementApi {
final SubscriptionBaseBundle bundle = subscriptionBaseInternalApi.getBundleFromId(bundleId, contextWithValidAccountRecordId);
final Account account = accountApi.getAccountById(bundle.getAccountId(), contextWithValidAccountRecordId);
final SubscriptionBase baseSubscription = subscriptionBaseInternalApi.getBaseSubscription(bundleId, contextWithValidAccountRecordId);
- final DateTime effectiveDate = dateHelper.fromLocalDateAndReferenceTime(localEffectiveDate, baseSubscription.getStartDate(), contextWithValidAccountRecordId);
+ final DateTime effectiveDate = dateHelper.fromLocalDateAndReferenceTime(updatedPluginContext.getEffectiveDate(), baseSubscription.getStartDate(), contextWithValidAccountRecordId);
if (!dateHelper.isBeforeOrEqualsToday(effectiveDate, account.getTimeZone())) {
recordPauseResumeNotificationEntry(baseSubscription.getId(), bundleId, effectiveDate, true, contextWithValidAccountRecordId);
@@ -363,31 +336,32 @@ public class DefaultEntitlementApi implements EntitlementApi {
return null;
}
};
- executeWithPlugin(pauseWithPlugin, this, pluginContext);
+ pluginExecution.executeWithPlugin(pauseWithPlugin, pluginContext);
}
@Override
- public void resume(final UUID bundleId, final LocalDate localEffectiveDate, final CallContext context) throws EntitlementApiException {
+ public void resume(final UUID bundleId, final LocalDate localEffectiveDate, final Iterable<PluginProperty> properties, final CallContext context) throws EntitlementApiException {
final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.RESUME_SUBSCRIPTION,
null,
+ null,
bundleId,
null,
null,
null,
localEffectiveDate,
- null,
+ properties,
context);
final WithEntitlementPlugin<Void> resumeWithPlugin = new WithEntitlementPlugin<Void>() {
@Override
- public Void doCall(final EntitlementApi entitlementApi) throws EntitlementApiException {
+ public Void doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
try {
final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(bundleId, ObjectType.BUNDLE, context);
final SubscriptionBaseBundle bundle = subscriptionBaseInternalApi.getBundleFromId(bundleId, contextWithValidAccountRecordId);
final Account account = accountApi.getAccountById(bundle.getAccountId(), contextWithValidAccountRecordId);
final SubscriptionBase baseSubscription = subscriptionBaseInternalApi.getBaseSubscription(bundleId, contextWithValidAccountRecordId);
- final DateTime effectiveDate = dateHelper.fromLocalDateAndReferenceTime(localEffectiveDate, baseSubscription.getStartDate(), contextWithValidAccountRecordId);
+ final DateTime effectiveDate = dateHelper.fromLocalDateAndReferenceTime(updatedPluginContext.getEffectiveDate(), baseSubscription.getStartDate(), contextWithValidAccountRecordId);
if (!dateHelper.isBeforeOrEqualsToday(effectiveDate, account.getTimeZone())) {
recordPauseResumeNotificationEntry(baseSubscription.getId(), bundleId, effectiveDate, false, contextWithValidAccountRecordId);
@@ -425,57 +399,75 @@ public class DefaultEntitlementApi implements EntitlementApi {
return null;
}
};
- executeWithPlugin(resumeWithPlugin, this, pluginContext);
+ pluginExecution.executeWithPlugin(resumeWithPlugin, pluginContext);
}
@Override
- public UUID transferEntitlements(final UUID sourceAccountId, final UUID destAccountId, final String externalKey, final LocalDate effectiveDate, final CallContext context) throws EntitlementApiException {
- return transferEntitlementsOverrideBillingPolicy(sourceAccountId, destAccountId, externalKey, effectiveDate, BillingActionPolicy.IMMEDIATE, context);
+ public UUID transferEntitlements(final UUID sourceAccountId, final UUID destAccountId, final String externalKey, final LocalDate effectiveDate, final Iterable<PluginProperty> properties, final CallContext context) throws EntitlementApiException {
+ return transferEntitlementsOverrideBillingPolicy(sourceAccountId, destAccountId, externalKey, effectiveDate, BillingActionPolicy.IMMEDIATE, properties, context);
}
@Override
- public UUID transferEntitlementsOverrideBillingPolicy(final UUID sourceAccountId, final UUID destAccountId, final String externalKey, final LocalDate effectiveDate, final BillingActionPolicy billingPolicy, final CallContext context) throws EntitlementApiException {
- final boolean cancelImm;
- switch (billingPolicy) {
- case IMMEDIATE:
- cancelImm = true;
- break;
- case END_OF_TERM:
- cancelImm = false;
- break;
- default:
- throw new RuntimeException("Unexpected billing policy " + billingPolicy);
- }
+ public UUID transferEntitlementsOverrideBillingPolicy(final UUID sourceAccountId, final UUID destAccountId, final String externalKey, final LocalDate effectiveDate, final BillingActionPolicy billingPolicy, final Iterable<PluginProperty> properties, final CallContext context) throws EntitlementApiException {
- final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(sourceAccountId, context);
- try {
+ final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.TRANSFER_BUNDLE,
+ sourceAccountId,
+ destAccountId,
+ null,
+ null,
+ externalKey,
+ null,
+ effectiveDate,
+ properties,
+ context);
- final UUID activeSubscriptionIdForKey = entitlementUtils.getFirstActiveSubscriptionIdForKeyOrNull(externalKey, contextWithValidAccountRecordId);
- final SubscriptionBase baseSubscription = activeSubscriptionIdForKey != null ?
- subscriptionBaseInternalApi.getSubscriptionFromId(activeSubscriptionIdForKey, contextWithValidAccountRecordId) : null;
- final SubscriptionBaseBundle baseBundle = baseSubscription != null ?
- subscriptionBaseInternalApi.getBundleFromId(baseSubscription.getBundleId(), contextWithValidAccountRecordId) : null;
+ final WithEntitlementPlugin<UUID> transferWithPlugin = new WithEntitlementPlugin<UUID>() {
+ @Override
+ public UUID doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
+ final boolean cancelImm;
+ switch (billingPolicy) {
+ case IMMEDIATE:
+ cancelImm = true;
+ break;
+ case END_OF_TERM:
+ cancelImm = false;
+ break;
+ default:
+ throw new RuntimeException("Unexpected billing policy " + billingPolicy);
+ }
- if (baseBundle == null || !baseBundle.getAccountId().equals(sourceAccountId)) {
- throw new EntitlementApiException(new SubscriptionBaseApiException(ErrorCode.SUB_GET_INVALID_BUNDLE_KEY, externalKey));
- }
+ final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(sourceAccountId, context);
+ try {
- final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(effectiveDate, baseSubscription.getStartDate(), contextWithValidAccountRecordId);
- final SubscriptionBaseBundle newBundle = subscriptionBaseTransferApi.transferBundle(sourceAccountId, destAccountId, externalKey, requestedDate, true, cancelImm, context);
+ final UUID activeSubscriptionIdForKey = entitlementUtils.getFirstActiveSubscriptionIdForKeyOrNull(externalKey, contextWithValidAccountRecordId);
+ final SubscriptionBase baseSubscription = activeSubscriptionIdForKey != null ?
+ subscriptionBaseInternalApi.getSubscriptionFromId(activeSubscriptionIdForKey, contextWithValidAccountRecordId) : null;
+ final SubscriptionBaseBundle baseBundle = baseSubscription != null ?
+ subscriptionBaseInternalApi.getBundleFromId(baseSubscription.getBundleId(), contextWithValidAccountRecordId) : null;
- // Block all associated subscriptions - TODO Do we want to block the bundle as well (this will add an extra STOP_ENTITLEMENT event in the bundle timeline stream)?
- // Note that there is no un-transfer at the moment, so we effectively add a blocking state on disk for all subscriptions
- for (final SubscriptionBase subscriptionBase : subscriptionBaseInternalApi.getSubscriptionsForBundle(baseBundle.getId(), null, contextWithValidAccountRecordId)) {
- final BlockingState blockingState = new DefaultBlockingState(subscriptionBase.getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_CANCELLED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, false, requestedDate);
- entitlementUtils.setBlockingStateAndPostBlockingTransitionEvent(blockingState, contextWithValidAccountRecordId);
- }
+ if (baseBundle == null || !baseBundle.getAccountId().equals(sourceAccountId)) {
+ throw new EntitlementApiException(new SubscriptionBaseApiException(ErrorCode.SUB_GET_INVALID_BUNDLE_KEY, externalKey));
+ }
- return newBundle.getId();
- } catch (SubscriptionBaseTransferApiException e) {
- throw new EntitlementApiException(e);
- } catch (SubscriptionBaseApiException e) {
- throw new EntitlementApiException(e);
- }
+ final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(updatedPluginContext.getEffectiveDate(), baseSubscription.getStartDate(), contextWithValidAccountRecordId);
+ final SubscriptionBaseBundle newBundle = subscriptionBaseTransferApi.transferBundle(sourceAccountId, destAccountId, externalKey, requestedDate, true, cancelImm, context);
+
+ // Block all associated subscriptions - TODO Do we want to block the bundle as well (this will add an extra STOP_ENTITLEMENT event in the bundle timeline stream)?
+ // Note that there is no un-transfer at the moment, so we effectively add a blocking state on disk for all subscriptions
+ for (final SubscriptionBase subscriptionBase : subscriptionBaseInternalApi.getSubscriptionsForBundle(baseBundle.getId(), null, contextWithValidAccountRecordId)) {
+ final BlockingState blockingState = new DefaultBlockingState(subscriptionBase.getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_CANCELLED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, false, requestedDate);
+ entitlementUtils.setBlockingStateAndPostBlockingTransitionEvent(blockingState, contextWithValidAccountRecordId);
+ }
+
+ return newBundle.getId();
+ } catch (SubscriptionBaseTransferApiException e) {
+ throw new EntitlementApiException(e);
+ } catch (SubscriptionBaseApiException e) {
+ throw new EntitlementApiException(e);
+ }
+ }
+ };
+ return pluginExecution.executeWithPlugin(transferWithPlugin, pluginContext);
}
private void recordPauseResumeNotificationEntry(final UUID entitlementId, final UUID bundleId, final DateTime effectiveDate, final boolean isPause, final InternalCallContext contextWithValidAccountRecordId) throws EntitlementApiException {
@@ -494,46 +486,4 @@ public class DefaultEntitlementApi implements EntitlementApi {
throw new EntitlementApiException(e, ErrorCode.__UNKNOWN_ERROR_CODE);
}
}
-
- private PriorEntitlementResult executePluginPriorCalls(final EntitlementContext entitlementContextArg) throws EntitlementPluginApiException {
-
- // Return as soon as the first plugin aborts, or the last result for the last plugin
- PriorEntitlementResult prevResult = null;
-
- EntitlementContext currentContext = entitlementContextArg;
- for (final String pluginName : pluginRegistry.getAllServices()) {
- final EntitlementPluginApi plugin = pluginRegistry.getServiceForName(pluginName);
- if (plugin == null) {
- // First call to plugin, we log warn, if plugin is not registered
- log.warn("Skipping unknown entitlement control plugin {} when fetching results", pluginName);
- continue;
- }
- prevResult = plugin.priorCall(currentContext, currentContext.getPluginProperties());
- if (prevResult.isAborted()) {
- break;
- }
- currentContext = new DefaultEntitlementContext(currentContext, prevResult);
- }
- return prevResult;
- }
-
- private OnSuccessEntitlementResult executePluginOnSuccessCalls(final EntitlementContext context) throws EntitlementPluginApiException {
- for (final String pluginName : pluginRegistry.getAllServices()) {
- final EntitlementPluginApi plugin = pluginRegistry.getServiceForName(pluginName);
- if (plugin != null) {
- plugin.onSuccessCall(context, context.getPluginProperties());
- }
- }
- return null;
- }
-
- private OnFailureEntitlementResult executePluginOnFailureCalls(final EntitlementContext context) throws EntitlementPluginApiException {
- for (final String pluginName : pluginRegistry.getAllServices()) {
- final EntitlementPluginApi plugin = pluginRegistry.getServiceForName(pluginName);
- if (plugin != null) {
- plugin.onFailureCall(context, context.getPluginProperties());
- }
- }
- return null;
- }
}
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementContext.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementContext.java
index eb7c293..47ada7b 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementContext.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementContext.java
@@ -34,12 +34,12 @@ import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.CallOrigin;
import org.killbill.billing.util.callcontext.UserType;
-import com.google.common.base.MoreObjects;
public class DefaultEntitlementContext implements EntitlementContext {
private final OperationType operationType;
private final UUID accountId;
+ private final UUID destinationAccountId;
private final UUID bundleId;
private final PlanPhaseSpecifier spec;
private final String externalKey;
@@ -61,6 +61,7 @@ public class DefaultEntitlementContext implements EntitlementContext {
@Nullable final PriorEntitlementResult pluginResult) {
this(prev.getOperationType(),
prev.getAccountId(),
+ prev.getDestinationAccountId(),
prev.getBundleId(),
pluginResult != null && pluginResult.getAdjustedPlanPhaseSpecifier() != null ? pluginResult.getAdjustedPlanPhaseSpecifier() : prev.getPlanPhaseSpecifier(),
prev.getExternalKey(),
@@ -72,6 +73,7 @@ public class DefaultEntitlementContext implements EntitlementContext {
public DefaultEntitlementContext(final OperationType operationType,
final UUID accountId,
+ final UUID destinationAccountId,
final UUID bundleId,
final PlanPhaseSpecifier spec,
final String externalKey,
@@ -79,7 +81,7 @@ public class DefaultEntitlementContext implements EntitlementContext {
final LocalDate effectiveDate,
final Iterable<PluginProperty> pluginProperties,
final CallContext callContext) {
- this(operationType, accountId, bundleId, spec, externalKey, planPhasePriceOverrides, effectiveDate, pluginProperties,
+ this(operationType, accountId, destinationAccountId, bundleId, spec, externalKey, planPhasePriceOverrides, effectiveDate, pluginProperties,
callContext.getUserToken(), callContext.getUserName(), callContext.getCallOrigin(), callContext.getUserType(), callContext.getReasonCode(),
callContext.getComments(), callContext.getCreatedDate(), callContext.getUpdatedDate(), callContext.getTenantId());
}
@@ -87,6 +89,7 @@ public class DefaultEntitlementContext implements EntitlementContext {
public DefaultEntitlementContext(final OperationType operationType,
final UUID accountId,
+ final UUID destinationAccountId,
final UUID bundleId,
final PlanPhaseSpecifier spec,
final String externalKey,
@@ -104,6 +107,7 @@ public class DefaultEntitlementContext implements EntitlementContext {
final UUID tenantId) {
this.operationType = operationType;
this.accountId = accountId;
+ this.destinationAccountId = destinationAccountId;
this.bundleId = bundleId;
this.spec = spec;
this.externalKey = externalKey;
@@ -132,6 +136,11 @@ public class DefaultEntitlementContext implements EntitlementContext {
}
@Override
+ public UUID getDestinationAccountId() {
+ return destinationAccountId;
+ }
+
+ @Override
public UUID getBundleId() {
return bundleId;
}
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/EntitlementPluginExecution.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/EntitlementPluginExecution.java
new file mode 100644
index 0000000..61f6307
--- /dev/null
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/EntitlementPluginExecution.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.entitlement.api;
+
+import javax.inject.Inject;
+
+import org.killbill.billing.ErrorCode;
+import org.killbill.billing.entitlement.plugin.api.EntitlementContext;
+import org.killbill.billing.entitlement.plugin.api.EntitlementPluginApi;
+import org.killbill.billing.entitlement.plugin.api.EntitlementPluginApiException;
+import org.killbill.billing.entitlement.plugin.api.OnFailureEntitlementResult;
+import org.killbill.billing.entitlement.plugin.api.OnSuccessEntitlementResult;
+import org.killbill.billing.entitlement.plugin.api.PriorEntitlementResult;
+import org.killbill.billing.osgi.api.OSGIServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EntitlementPluginExecution {
+
+ private static final Logger log = LoggerFactory.getLogger(EntitlementPluginExecution.class);
+
+ private final EntitlementApi entitlementApi;
+ private final OSGIServiceRegistration<EntitlementPluginApi> pluginRegistry;
+
+ public interface WithEntitlementPlugin<T> {
+ T doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException;
+ }
+
+
+ @Inject
+ public EntitlementPluginExecution(final EntitlementApi entitlementApi, final OSGIServiceRegistration<EntitlementPluginApi> pluginRegistry) {
+ this.entitlementApi = entitlementApi;
+ this.pluginRegistry = pluginRegistry;
+ }
+
+ public <T> T executeWithPlugin(final WithEntitlementPlugin<T> callback, final EntitlementContext pluginContext) throws EntitlementApiException {
+
+ try {
+ final PriorEntitlementResult priorEntitlementResult = executePluginPriorCalls(pluginContext);
+ if (priorEntitlementResult != null && priorEntitlementResult.isAborted()) {
+ throw new EntitlementApiException(ErrorCode.ENT_PLUGIN_API_ABORTED);
+ }
+ final EntitlementContext updatedPluginContext = new DefaultEntitlementContext(pluginContext, priorEntitlementResult);
+ try {
+ T result = callback.doCall(entitlementApi, updatedPluginContext);
+ executePluginOnSuccessCalls(updatedPluginContext);
+ return result;
+ } catch (final EntitlementApiException e) {
+ executePluginOnFailureCalls(updatedPluginContext);
+ throw e;
+ }
+ } catch (final EntitlementPluginApiException e) {
+ throw new EntitlementApiException(ErrorCode.ENT_PLUGIN_API_ABORTED, e.getMessage());
+ }
+ }
+
+ private PriorEntitlementResult executePluginPriorCalls(final EntitlementContext entitlementContextArg) throws EntitlementPluginApiException {
+
+ // Return as soon as the first plugin aborts, or the last result for the last plugin
+ PriorEntitlementResult prevResult = null;
+
+ EntitlementContext currentContext = entitlementContextArg;
+ for (final String pluginName : pluginRegistry.getAllServices()) {
+ final EntitlementPluginApi plugin = pluginRegistry.getServiceForName(pluginName);
+ if (plugin == null) {
+ // First call to plugin, we log warn, if plugin is not registered
+ log.warn("Skipping unknown entitlement control plugin {} when fetching results", pluginName);
+ continue;
+ }
+ prevResult = plugin.priorCall(currentContext, currentContext.getPluginProperties());
+ if (prevResult.isAborted()) {
+ break;
+ }
+ currentContext = new DefaultEntitlementContext(currentContext, prevResult);
+ }
+ return prevResult;
+ }
+
+ private OnSuccessEntitlementResult executePluginOnSuccessCalls(final EntitlementContext context) throws EntitlementPluginApiException {
+ for (final String pluginName : pluginRegistry.getAllServices()) {
+ final EntitlementPluginApi plugin = pluginRegistry.getServiceForName(pluginName);
+ if (plugin != null) {
+ plugin.onSuccessCall(context, context.getPluginProperties());
+ }
+ }
+ return null;
+ }
+
+ private OnFailureEntitlementResult executePluginOnFailureCalls(final EntitlementContext context) throws EntitlementPluginApiException {
+ for (final String pluginName : pluginRegistry.getAllServices()) {
+ final EntitlementPluginApi plugin = pluginRegistry.getServiceForName(pluginName);
+ if (plugin != null) {
+ plugin.onFailureCall(context, context.getPluginProperties());
+ }
+ }
+ return null;
+ }
+}
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementInternalApi.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementInternalApi.java
index a0247ca..b4c8459 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementInternalApi.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementInternalApi.java
@@ -26,6 +26,7 @@ import javax.inject.Inject;
import org.killbill.billing.account.api.AccountInternalApi;
import org.killbill.billing.callcontext.InternalTenantContext;
+import org.killbill.billing.entitlement.api.EntitlementPluginExecution;
import org.killbill.clock.Clock;
import org.killbill.billing.entitlement.AccountEntitlements;
import org.killbill.billing.entitlement.AccountEventsStreams;
@@ -57,14 +58,17 @@ public class DefaultEntitlementInternalApi implements EntitlementInternalApi {
private final EventsStreamBuilder eventsStreamBuilder;
private final EntitlementUtils entitlementUtils;
private final NotificationQueueService notificationQueueService;
+ private final EntitlementPluginExecution pluginExecution;
@Inject
- public DefaultEntitlementInternalApi(final EntitlementApi entitlementApi, final InternalCallContextFactory internalCallContextFactory,
+ public DefaultEntitlementInternalApi(final EntitlementApi entitlementApi, final EntitlementPluginExecution pluginExecution,
+ final InternalCallContextFactory internalCallContextFactory,
final SubscriptionBaseInternalApi subscriptionInternalApi,
final AccountInternalApi accountApi, final BlockingStateDao blockingStateDao, final Clock clock,
final BlockingChecker checker, final NotificationQueueService notificationQueueService,
final EventsStreamBuilder eventsStreamBuilder, final EntitlementUtils entitlementUtils) {
this.entitlementApi = entitlementApi;
+ this.pluginExecution= pluginExecution;
this.internalCallContextFactory = internalCallContextFactory;
this.subscriptionInternalApi = subscriptionInternalApi;
this.clock = clock;
@@ -89,7 +93,7 @@ public class DefaultEntitlementInternalApi implements EntitlementInternalApi {
}
for (final EventsStream eventsStream : accountEventsStreams.getEventsStreams().get(bundleId)) {
- final Entitlement entitlement = new DefaultEntitlement(eventsStream, eventsStreamBuilder, entitlementApi,
+ final Entitlement entitlement = new DefaultEntitlement(eventsStream, eventsStreamBuilder, entitlementApi, pluginExecution,
blockingStateDao, subscriptionInternalApi, checker, notificationQueueService,
entitlementUtils, dateHelper, clock, internalCallContextFactory);
entitlementsPerBundle.get(bundleId).add(entitlement);
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/DefaultEntitlementService.java b/entitlement/src/main/java/org/killbill/billing/entitlement/DefaultEntitlementService.java
index cd4e917..d93e058 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/DefaultEntitlementService.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/DefaultEntitlementService.java
@@ -31,6 +31,7 @@ import org.killbill.billing.entitlement.dao.BlockingStateDao;
import org.killbill.billing.entitlement.engine.core.BlockingTransitionNotificationKey;
import org.killbill.billing.entitlement.engine.core.EntitlementNotificationKey;
import org.killbill.billing.entitlement.engine.core.EntitlementNotificationKeyAction;
+import org.killbill.billing.payment.api.PluginProperty;
import org.killbill.billing.platform.api.LifecycleHandlerType;
import org.killbill.billing.platform.api.LifecycleHandlerType.LifecycleLevel;
import org.killbill.billing.util.callcontext.CallContext;
@@ -49,6 +50,7 @@ import org.killbill.notificationq.api.NotificationQueueService.NotificationQueue
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.collect.ImmutableList;
import com.google.inject.Inject;
public class DefaultEntitlementService implements EntitlementService {
@@ -132,9 +134,9 @@ public class DefaultEntitlementService implements EntitlementService {
EntitlementNotificationKeyAction.CANCEL.equals(entitlementNotificationKeyAction)) {
((DefaultEntitlement) entitlement).blockAddOnsIfRequired(key.getEffectiveDate(), callContext, internalCallContext);
} else if (EntitlementNotificationKeyAction.PAUSE.equals(entitlementNotificationKeyAction)) {
- entitlementApi.pause(key.getBundleId(), key.getEffectiveDate().toLocalDate(), callContext);
+ entitlementApi.pause(key.getBundleId(), key.getEffectiveDate().toLocalDate(), ImmutableList.<PluginProperty>of(), callContext);
} else if (EntitlementNotificationKeyAction.RESUME.equals(entitlementNotificationKeyAction)) {
- entitlementApi.resume(key.getBundleId(), key.getEffectiveDate().toLocalDate(), callContext);
+ entitlementApi.resume(key.getBundleId(), key.getEffectiveDate().toLocalDate(), ImmutableList.<PluginProperty>of(), callContext);
}
} catch (final EntitlementApiException e) {
log.error("Error processing event for entitlement {}" + entitlement.getId(), e);
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/glue/DefaultEntitlementModule.java b/entitlement/src/main/java/org/killbill/billing/entitlement/glue/DefaultEntitlementModule.java
index 852dbd6..abb79ff 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/glue/DefaultEntitlementModule.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/glue/DefaultEntitlementModule.java
@@ -24,6 +24,7 @@ import org.killbill.billing.entitlement.EntitlementService;
import org.killbill.billing.entitlement.api.DefaultEntitlementApi;
import org.killbill.billing.entitlement.api.DefaultSubscriptionApi;
import org.killbill.billing.entitlement.api.EntitlementApi;
+import org.killbill.billing.entitlement.api.EntitlementPluginExecution;
import org.killbill.billing.entitlement.api.SubscriptionApi;
import org.killbill.billing.entitlement.api.svcs.DefaultEntitlementInternalApi;
import org.killbill.billing.entitlement.api.svcs.DefaultInternalBlockingApi;
@@ -50,6 +51,7 @@ public class DefaultEntitlementModule extends KillBillModule implements Entitlem
protected void installEntitlementPluginApi() {
bind(new TypeLiteral<OSGIServiceRegistration<EntitlementPluginApi>>() {}).toProvider(DefaultEntitlementProviderPluginRegistryProvider.class).asEagerSingleton();
+ bind(EntitlementPluginExecution.class).asEagerSingleton();
}
@Override
diff --git a/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultEntitlement.java b/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultEntitlement.java
index 7fa6a31..f7e4372 100644
--- a/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultEntitlement.java
+++ b/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultEntitlement.java
@@ -18,6 +18,7 @@ package org.killbill.billing.entitlement.api;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
+import org.killbill.billing.payment.api.PluginProperty;
import org.killbill.billing.subscription.api.user.SubscriptionBaseApiException;
import org.testng.annotations.Test;
@@ -32,6 +33,8 @@ import org.killbill.billing.entitlement.EntitlementTestSuiteWithEmbeddedDB;
import org.killbill.billing.entitlement.api.Entitlement.EntitlementActionPolicy;
import org.killbill.billing.entitlement.api.Entitlement.EntitlementState;
+import com.google.common.collect.ImmutableList;
+
import static org.testng.Assert.assertEquals;
public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
@@ -47,7 +50,7 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
// Create entitlement and check each field
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, callContext);
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
assertEquals(entitlement.getState(), EntitlementState.ACTIVE);
@@ -55,7 +58,7 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
testListener.pushExpectedEvents(NextEvent.CANCEL, NextEvent.BLOCK);
final LocalDate cancelDate = new LocalDate(clock.getUTCNow());
- entitlement.cancelEntitlementWithDate(cancelDate, true, callContext);
+ entitlement.cancelEntitlementWithDate(cancelDate, true, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
final Entitlement entitlement2 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
@@ -74,14 +77,14 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
// Create entitlement and check each field
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, callContext);
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
assertEquals(entitlement.getState(), EntitlementState.ACTIVE);
clock.addDays(5);
final LocalDate cancelDate = new LocalDate(clock.getUTCToday().plusDays(1));
- entitlement.cancelEntitlementWithDate(cancelDate, true, callContext);
+ entitlement.cancelEntitlementWithDate(cancelDate, true, ImmutableList.<PluginProperty>of(), callContext);
final Entitlement entitlement2 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
assertEquals(entitlement2.getState(), EntitlementState.ACTIVE);
@@ -108,21 +111,21 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
// Create entitlement and check each field
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, callContext);
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
assertEquals(entitlement.getState(), EntitlementState.ACTIVE);
clock.addDays(5);
final LocalDate cancelDate = new LocalDate(clock.getUTCToday().plusDays(1));
- entitlement.cancelEntitlementWithDate(cancelDate, true, callContext);
+ entitlement.cancelEntitlementWithDate(cancelDate, true, ImmutableList.<PluginProperty>of(), callContext);
final Entitlement entitlement2 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
assertEquals(entitlement2.getState(), EntitlementState.ACTIVE);
assertEquals(entitlement2.getEffectiveEndDate(), cancelDate);
testListener.pushExpectedEvents(NextEvent.UNCANCEL);
- entitlement2.uncancelEntitlement(callContext);
+ entitlement2.uncancelEntitlement(ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
clock.addDays(1);
@@ -141,11 +144,11 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
// Create entitlement and check each field
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, callContext);
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
testListener.pushExpectedEvents(NextEvent.CANCEL, NextEvent.BLOCK);
- final Entitlement cancelledEntitlement = entitlement.cancelEntitlementWithPolicy(EntitlementActionPolicy.END_OF_TERM, callContext);
+ final Entitlement cancelledEntitlement = entitlement.cancelEntitlementWithPolicy(EntitlementActionPolicy.END_OF_TERM, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
assertEquals(cancelledEntitlement.getState(), EntitlementState.CANCELLED);
assertEquals(cancelledEntitlement.getEffectiveEndDate(), initialDate);
@@ -166,7 +169,7 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
// Create entitlement and check each field
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, callContext);
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
final DateTime ctd = clock.getUTCNow().plusDays(30).plusMonths(1);
@@ -180,7 +183,7 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
final Entitlement entitlement2 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
testListener.pushExpectedEvent(NextEvent.BLOCK);
- final Entitlement entitlement3 = entitlement2.cancelEntitlementWithPolicy(EntitlementActionPolicy.IMMEDIATE, callContext);
+ final Entitlement entitlement3 = entitlement2.cancelEntitlementWithPolicy(EntitlementActionPolicy.IMMEDIATE, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
assertEquals(entitlement3.getState(), EntitlementState.CANCELLED);
assertEquals(entitlement3.getEffectiveEndDate(), new LocalDate(2013, 9, 8));
@@ -209,7 +212,7 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
// Create entitlement and check each field
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, callContext);
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
final DateTime ctd = clock.getUTCNow().plusDays(30).plusMonths(1);
@@ -221,7 +224,7 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
final Entitlement entitlement2 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
- final Entitlement entitlement3 = entitlement2.cancelEntitlementWithPolicy(EntitlementActionPolicy.END_OF_TERM, callContext);
+ final Entitlement entitlement3 = entitlement2.cancelEntitlementWithPolicy(EntitlementActionPolicy.END_OF_TERM, ImmutableList.<PluginProperty>of(), callContext);
assertEquals(entitlement3.getState(), EntitlementState.ACTIVE);
assertEquals(entitlement3.getEffectiveEndDate(), new LocalDate(ctd));
@@ -249,12 +252,12 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
// Create entitlement and check each field
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, callContext);
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// Immediate change during trial
testListener.pushExpectedEvent(NextEvent.CHANGE);
- entitlement.changePlan("Assault-Rifle", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null, callContext);
+ entitlement.changePlan("Assault-Rifle", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// Verify the change is immediate
@@ -262,7 +265,7 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
assertEquals(entitlement2.getLastActivePlan().getProduct().getName(), "Assault-Rifle");
testListener.pushExpectedEvents(NextEvent.CANCEL, NextEvent.BLOCK);
- final Entitlement cancelledEntitlement = entitlement.cancelEntitlementWithPolicy(EntitlementActionPolicy.END_OF_TERM, callContext);
+ final Entitlement cancelledEntitlement = entitlement.cancelEntitlementWithPolicy(EntitlementActionPolicy.END_OF_TERM, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
assertEquals(cancelledEntitlement.getState(), EntitlementState.CANCELLED);
assertEquals(cancelledEntitlement.getEffectiveEndDate(), initialDate);
diff --git a/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultEntitlementApi.java b/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultEntitlementApi.java
index 044bf37..45851eb 100644
--- a/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultEntitlementApi.java
+++ b/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultEntitlementApi.java
@@ -21,6 +21,7 @@ import java.util.UUID;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
+import org.killbill.billing.payment.api.PluginProperty;
import org.killbill.billing.subscription.api.user.SubscriptionBaseApiException;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -38,6 +39,8 @@ import org.killbill.billing.entitlement.EntitlementTestSuiteWithEmbeddedDB;
import org.killbill.billing.entitlement.api.Entitlement.EntitlementSourceType;
import org.killbill.billing.entitlement.api.Entitlement.EntitlementState;
+import com.google.common.collect.ImmutableList;
+
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
@@ -54,17 +57,17 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
// Keep the same object for the whole test, to make sure we refresh its state before r/w calls
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, callContext);
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// Add ADD_ON
// Keep the same object for the whole test, to make sure we refresh its state before r/w calls
final PlanPhaseSpecifier addOnSpec = new PlanPhaseSpecifier("Telescopic-Scope", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement addOnEntitlement = entitlementApi.addEntitlement(entitlement.getBundleId(), addOnSpec, null, initialDate, callContext);
+ final Entitlement addOnEntitlement = entitlementApi.addEntitlement(entitlement.getBundleId(), addOnSpec, null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
try {
- entitlement.uncancelEntitlement(callContext);
+ entitlement.uncancelEntitlement(ImmutableList.<PluginProperty>of(), callContext);
Assert.fail("Entitlement hasn't been cancelled yet");
} catch (final EntitlementApiException e) {
Assert.assertEquals(e.getCode(), ErrorCode.SUB_CANCEL_BAD_STATE.getCode());
@@ -74,32 +77,32 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
// Cancelling the base entitlement will cancel the add-on
testListener.pushExpectedEvents(NextEvent.CANCEL, NextEvent.BLOCK, NextEvent.CANCEL, NextEvent.BLOCK);
- entitlement.cancelEntitlementWithDateOverrideBillingPolicy(clock.getUTCToday(), BillingActionPolicy.IMMEDIATE, callContext);
+ entitlement.cancelEntitlementWithDateOverrideBillingPolicy(clock.getUTCToday(), BillingActionPolicy.IMMEDIATE, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
try {
- entitlement.cancelEntitlementWithDateOverrideBillingPolicy(clock.getUTCToday(), BillingActionPolicy.IMMEDIATE, callContext);
+ entitlement.cancelEntitlementWithDateOverrideBillingPolicy(clock.getUTCToday(), BillingActionPolicy.IMMEDIATE, ImmutableList.<PluginProperty>of(), callContext);
Assert.fail("Entitlement is already cancelled");
} catch (final EntitlementApiException e) {
Assert.assertEquals(e.getCode(), ErrorCode.SUB_CANCEL_BAD_STATE.getCode());
}
try {
- addOnEntitlement.cancelEntitlementWithDateOverrideBillingPolicy(clock.getUTCToday(), BillingActionPolicy.IMMEDIATE, callContext);
+ addOnEntitlement.cancelEntitlementWithDateOverrideBillingPolicy(clock.getUTCToday(), BillingActionPolicy.IMMEDIATE, ImmutableList.<PluginProperty>of(), callContext);
Assert.fail("Add-On Entitlement is already cancelled");
} catch (final EntitlementApiException e) {
Assert.assertEquals(e.getCode(), ErrorCode.SUB_CANCEL_BAD_STATE.getCode());
}
try {
- entitlement.uncancelEntitlement(callContext);
+ entitlement.uncancelEntitlement(ImmutableList.<PluginProperty>of(), callContext);
Assert.fail("Entitlement is already cancelled");
} catch (final EntitlementApiException e) {
Assert.assertEquals(e.getCode(), ErrorCode.SUB_CANCEL_BAD_STATE.getCode());
}
try {
- addOnEntitlement.uncancelEntitlement(callContext);
+ addOnEntitlement.uncancelEntitlement(ImmutableList.<PluginProperty>of(), callContext);
Assert.fail("Add-On Entitlement is already cancelled");
} catch (final EntitlementApiException e) {
Assert.assertEquals(e.getCode(), ErrorCode.SUB_CANCEL_BAD_STATE.getCode());
@@ -118,7 +121,7 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
// Keep the same object for the whole test, to make sure we refresh its state before r/w calls
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, callContext);
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
testListener.pushExpectedEvent(NextEvent.PHASE);
@@ -128,12 +131,12 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
final LocalDate entitlementCancelledDate = clock.getToday(account.getTimeZone());
testListener.pushExpectedEvent(NextEvent.BLOCK);
- final Entitlement cancelledEntitlement = entitlement.cancelEntitlementWithDateOverrideBillingPolicy(clock.getToday(account.getTimeZone()), BillingActionPolicy.END_OF_TERM, callContext);
+ final Entitlement cancelledEntitlement = entitlement.cancelEntitlementWithDateOverrideBillingPolicy(clock.getToday(account.getTimeZone()), BillingActionPolicy.END_OF_TERM, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
Assert.assertEquals(cancelledEntitlement.getEffectiveEndDate(), entitlementCancelledDate);
testListener.pushExpectedEvent(NextEvent.UNCANCEL);
- cancelledEntitlement.uncancelEntitlement(callContext);
+ cancelledEntitlement.uncancelEntitlement(ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
final Entitlement reactivatedEntitlement = entitlementApi.getEntitlementForId(cancelledEntitlement.getId(), callContext);
@@ -151,7 +154,7 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
// Create entitlement and check each field
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, callContext);
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
assertEquals(entitlement.getAccountId(), account.getId());
assertEquals(entitlement.getExternalKey(), account.getExternalKey());
@@ -243,13 +246,13 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
// Create entitlement and check each field
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement baseEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, callContext);
+ final Entitlement baseEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// Add ADD_ON
final PlanPhaseSpecifier spec1 = new PlanPhaseSpecifier("Telescopic-Scope", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement telescopicEntitlement = entitlementApi.addEntitlement(baseEntitlement.getBundleId(), spec1, null, initialDate, callContext);
+ final Entitlement telescopicEntitlement = entitlementApi.addEntitlement(baseEntitlement.getBundleId(), spec1, null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
assertEquals(telescopicEntitlement.getAccountId(), account.getId());
@@ -282,21 +285,21 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
// Create entitlement and check each field
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement baseEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, callContext);
+ final Entitlement baseEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
clock.addDays(1);
final LocalDate effectiveDateSpec1 = new LocalDate(clock.getUTCNow(), account.getTimeZone());
final PlanPhaseSpecifier spec1 = new PlanPhaseSpecifier("Telescopic-Scope", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement telescopicEntitlement = entitlementApi.addEntitlement(baseEntitlement.getBundleId(), spec1, null, effectiveDateSpec1, callContext);
+ final Entitlement telescopicEntitlement = entitlementApi.addEntitlement(baseEntitlement.getBundleId(), spec1, null, effectiveDateSpec1, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// Block all entitlement in the bundle
clock.addDays(5);
testListener.pushExpectedEvents(NextEvent.PAUSE, NextEvent.BLOCK);
- entitlementApi.pause(baseEntitlement.getBundleId(), new LocalDate(clock.getUTCNow()), callContext);
+ entitlementApi.pause(baseEntitlement.getBundleId(), new LocalDate(clock.getUTCNow()), ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// Verify blocking state
@@ -308,7 +311,7 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
// Check we can't block in a blocked state
try {
- entitlementApi.pause(baseEntitlement.getBundleId(), new LocalDate(clock.getUTCNow()), callContext);
+ entitlementApi.pause(baseEntitlement.getBundleId(), new LocalDate(clock.getUTCNow()), ImmutableList.<PluginProperty>of(), callContext);
Assert.fail("Should not have succeeded to block in a blocked state");
} catch (EntitlementApiException e) {
assertEquals(e.getCode(), ErrorCode.ENT_ALREADY_BLOCKED.getCode());
@@ -323,7 +326,7 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
// Try to add an ADD_ON, it should fail
try {
final PlanPhaseSpecifier spec3 = new PlanPhaseSpecifier("Telescopic-Scope", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
- final Entitlement telescopicEntitlement3 = entitlementApi.addEntitlement(baseEntitlement.getBundleId(), spec1, null, effectiveDateSpec1, callContext);
+ final Entitlement telescopicEntitlement3 = entitlementApi.addEntitlement(baseEntitlement.getBundleId(), spec1, null, effectiveDateSpec1, ImmutableList.<PluginProperty>of(), callContext);
} catch (EntitlementApiException e) {
assertEquals(e.getCode(), ErrorCode.SUB_GET_NO_SUCH_BASE_SUBSCRIPTION.getCode());
}
@@ -331,11 +334,11 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
clock.addDays(3);
testListener.pushExpectedEvents(NextEvent.RESUME, NextEvent.BLOCK);
- entitlementApi.resume(baseEntitlement.getBundleId(), new LocalDate(clock.getUTCNow()), callContext);
+ entitlementApi.resume(baseEntitlement.getBundleId(), new LocalDate(clock.getUTCNow()), ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// Verify call is idempotent
- entitlementApi.resume(baseEntitlement.getBundleId(), new LocalDate(clock.getUTCNow()), callContext);
+ entitlementApi.resume(baseEntitlement.getBundleId(), new LocalDate(clock.getUTCNow()), ImmutableList.<PluginProperty>of(), callContext);
// Verify blocking state
final Entitlement baseEntitlement3 = entitlementApi.getEntitlementForId(baseEntitlement.getId(), callContext);
@@ -361,7 +364,7 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
// Create entitlement
testListener.pushExpectedEvent(NextEvent.CREATE);
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, null);
- final Entitlement baseEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, callContext);
+ final Entitlement baseEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// Get the phase event out of the way
@@ -370,12 +373,12 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
assertListenerStatus();
final LocalDate pauseDate = new LocalDate(2013, 9, 17);
- entitlementApi.pause(baseEntitlement.getBundleId(), pauseDate, callContext);
+ entitlementApi.pause(baseEntitlement.getBundleId(), pauseDate, ImmutableList.<PluginProperty>of(), callContext);
// No event yet
assertListenerStatus();
final LocalDate resumeDate = new LocalDate(2013, 12, 24);
- entitlementApi.resume(baseEntitlement.getBundleId(), resumeDate, callContext);
+ entitlementApi.resume(baseEntitlement.getBundleId(), resumeDate, ImmutableList.<PluginProperty>of(), callContext);
// No event yet
assertListenerStatus();
@@ -408,7 +411,7 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
// Create entitlement
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement baseEntitlement = entitlementApi.createBaseEntitlement(accountSrc.getId(), spec, accountSrc.getExternalKey(), null, initialDate, callContext);
+ final Entitlement baseEntitlement = entitlementApi.createBaseEntitlement(accountSrc.getId(), spec, accountSrc.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
final DateTime ctd = clock.getUTCNow().plusDays(30).plusMonths(1);
@@ -421,7 +424,7 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
// Transfer bundle to dest account
final LocalDate effectiveDate = new LocalDate(clock.getUTCNow(), accountSrc.getTimeZone());
testListener.pushExpectedEvents(NextEvent.TRANSFER, NextEvent.BLOCK);
- final UUID newBundleId = entitlementApi.transferEntitlementsOverrideBillingPolicy(accountSrc.getId(), accountDesc.getId(), baseEntitlement.getExternalKey(), effectiveDate, BillingActionPolicy.END_OF_TERM, callContext);
+ final UUID newBundleId = entitlementApi.transferEntitlementsOverrideBillingPolicy(accountSrc.getId(), accountDesc.getId(), baseEntitlement.getExternalKey(), effectiveDate, BillingActionPolicy.END_OF_TERM, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
final Entitlement oldBaseEntitlement = entitlementApi.getAllEntitlementsForAccountIdAndExternalKey(accountSrc.getId(), accountSrc.getExternalKey(), callContext).get(0);
diff --git a/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultSubscriptionApi.java b/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultSubscriptionApi.java
index 92ba55d..9adb178 100644
--- a/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultSubscriptionApi.java
+++ b/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultSubscriptionApi.java
@@ -20,6 +20,7 @@ import java.util.List;
import java.util.UUID;
import org.joda.time.LocalDate;
+import org.killbill.billing.payment.api.PluginProperty;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -37,6 +38,8 @@ import org.killbill.billing.util.api.AuditLevel;
import org.killbill.billing.util.audit.AuditLog;
import org.killbill.billing.util.audit.ChangeType;
+import com.google.common.collect.ImmutableList;
+
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
@@ -52,10 +55,10 @@ public class TestDefaultSubscriptionApi extends EntitlementTestSuiteWithEmbedded
final Account account = accountApi.createAccount(getAccountData(7), callContext);
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
testListener.pushExpectedEvents(NextEvent.CREATE, NextEvent.CREATE, NextEvent.BLOCK);
- final Entitlement entitlement1 = entitlementApi.createBaseEntitlement(account.getId(), spec, UUID.randomUUID().toString(), null, initialDate, callContext);
+ final Entitlement entitlement1 = entitlementApi.createBaseEntitlement(account.getId(), spec, UUID.randomUUID().toString(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
// Sleep 1 sec so created date are apparts from each other and ordering in the bundle does not default on the UUID which is random.
try {Thread.sleep(1000); } catch (InterruptedException ignore) {};
- final Entitlement entitlement2 = entitlementApi.createBaseEntitlement(account.getId(), spec, UUID.randomUUID().toString(), null, initialDate, callContext);
+ final Entitlement entitlement2 = entitlementApi.createBaseEntitlement(account.getId(), spec, UUID.randomUUID().toString(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
entitlementUtils.setBlockingStateAndPostBlockingTransitionEvent(new DefaultBlockingState(account.getId(), BlockingStateType.ACCOUNT, "stateName", "service", false, false, false, clock.getUTCNow()),
internalCallContextFactory.createInternalCallContext(account.getId(), callContext));
assertListenerStatus();
@@ -98,7 +101,7 @@ public class TestDefaultSubscriptionApi extends EntitlementTestSuiteWithEmbedded
// Create entitlement and check each field
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, externalKey, null, initialDate, callContext);
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, externalKey, null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
assertEquals(entitlement.getAccountId(), account.getId());
assertEquals(entitlement.getExternalKey(), externalKey);
@@ -115,7 +118,7 @@ public class TestDefaultSubscriptionApi extends EntitlementTestSuiteWithEmbedded
// Cancel entitlement
clock.addDays(3);
testListener.pushExpectedEvents(NextEvent.CANCEL, NextEvent.BLOCK);
- entitlement.cancelEntitlementWithDate(new LocalDate(clock.getUTCNow(), account.getTimeZone()), true, callContext);
+ entitlement.cancelEntitlementWithDate(new LocalDate(clock.getUTCNow(), account.getTimeZone()), true, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
try {
@@ -132,7 +135,7 @@ public class TestDefaultSubscriptionApi extends EntitlementTestSuiteWithEmbedded
// Create entitlement and check each field
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement entitlement2 = entitlementApi.createBaseEntitlement(account.getId(), spec2, externalKey, null, new LocalDate(clock.getUTCNow(), account.getTimeZone()), callContext);
+ final Entitlement entitlement2 = entitlementApi.createBaseEntitlement(account.getId(), spec2, externalKey, null, new LocalDate(clock.getUTCNow(), account.getTimeZone()), ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
assertEquals(entitlement2.getAccountId(), account.getId());
assertEquals(entitlement2.getExternalKey(), externalKey);
@@ -163,7 +166,7 @@ public class TestDefaultSubscriptionApi extends EntitlementTestSuiteWithEmbedded
final Account account2 = accountApi.createAccount(getAccountData(7), callContext);
testListener.pushExpectedEvents(NextEvent.TRANSFER, NextEvent.CANCEL, NextEvent.BLOCK);
- entitlementApi.transferEntitlements(account.getId(), account2.getId(), externalKey, new LocalDate(clock.getUTCNow(), account.getTimeZone()), callContext);
+ entitlementApi.transferEntitlements(account.getId(), account2.getId(), externalKey, new LocalDate(clock.getUTCNow(), account.getTimeZone()), ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
final List<SubscriptionBundle> bundles3 = subscriptionApi.getSubscriptionBundlesForExternalKey(externalKey, callContext);
@@ -203,7 +206,7 @@ public class TestDefaultSubscriptionApi extends EntitlementTestSuiteWithEmbedded
// Create entitlement
testListener.pushExpectedEvent(NextEvent.CREATE);
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, null);
- final Entitlement baseEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, callContext);
+ final Entitlement baseEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// Get the phase event out of the way
@@ -212,13 +215,13 @@ public class TestDefaultSubscriptionApi extends EntitlementTestSuiteWithEmbedded
assertListenerStatus();
final LocalDate pauseDate = new LocalDate(2013, 9, 17);
- entitlementApi.pause(baseEntitlement.getBundleId(), pauseDate, callContext);
+ entitlementApi.pause(baseEntitlement.getBundleId(), pauseDate, ImmutableList.<PluginProperty>of(), callContext);
final LocalDate resumeDate = new LocalDate(2013, 12, 24);
- entitlementApi.resume(baseEntitlement.getBundleId(), resumeDate, callContext);
+ entitlementApi.resume(baseEntitlement.getBundleId(), resumeDate, ImmutableList.<PluginProperty>of(), callContext);
final LocalDate cancelDate = new LocalDate(2013, 12, 27);
- baseEntitlement.cancelEntitlementWithDate(cancelDate, true, callContext);
+ baseEntitlement.cancelEntitlementWithDate(cancelDate, true, ImmutableList.<PluginProperty>of(), callContext);
testListener.pushExpectedEvents(NextEvent.PAUSE, NextEvent.BLOCK, NextEvent.RESUME, NextEvent.BLOCK, NextEvent.CANCEL, NextEvent.BLOCK);
clock.setDay(cancelDate.plusDays(1));
diff --git a/entitlement/src/test/java/org/killbill/billing/entitlement/dao/TestDefaultBlockingStateDao.java b/entitlement/src/test/java/org/killbill/billing/entitlement/dao/TestDefaultBlockingStateDao.java
index 92cb81c..32f84a7 100644
--- a/entitlement/src/test/java/org/killbill/billing/entitlement/dao/TestDefaultBlockingStateDao.java
+++ b/entitlement/src/test/java/org/killbill/billing/entitlement/dao/TestDefaultBlockingStateDao.java
@@ -21,6 +21,7 @@ import java.util.UUID;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
+import org.killbill.billing.payment.api.PluginProperty;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -37,6 +38,8 @@ import org.killbill.billing.entitlement.api.BlockingStateType;
import org.killbill.billing.entitlement.api.Entitlement;
import org.killbill.billing.junction.DefaultBlockingState;
+import com.google.common.collect.ImmutableList;
+
public class TestDefaultBlockingStateDao extends EntitlementTestSuiteWithEmbeddedDB {
private Account account;
@@ -56,7 +59,7 @@ public class TestDefaultBlockingStateDao extends EntitlementTestSuiteWithEmbedde
// See TestEntitlementUtils for a more comprehensive test
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
testListener.pushExpectedEvent(NextEvent.CREATE);
- final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, clock.getUTCToday(), callContext);
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, clock.getUTCToday(), ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
final BlockingStateType type = BlockingStateType.SUBSCRIPTION;
diff --git a/entitlement/src/test/java/org/killbill/billing/entitlement/engine/core/TestEntitlementUtils.java b/entitlement/src/test/java/org/killbill/billing/entitlement/engine/core/TestEntitlementUtils.java
index 3f32c16..e32a1ef 100644
--- a/entitlement/src/test/java/org/killbill/billing/entitlement/engine/core/TestEntitlementUtils.java
+++ b/entitlement/src/test/java/org/killbill/billing/entitlement/engine/core/TestEntitlementUtils.java
@@ -24,6 +24,7 @@ import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
+import org.killbill.billing.payment.api.PluginProperty;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -79,11 +80,11 @@ public class TestEntitlementUtils extends EntitlementTestSuiteWithEmbeddedDB {
// Create base entitlement
final PlanPhaseSpecifier baseSpec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
- baseEntitlement = (DefaultEntitlement) entitlementApi.createBaseEntitlement(account.getId(), baseSpec, account.getExternalKey(), null, initialDate, callContext);
+ baseEntitlement = (DefaultEntitlement) entitlementApi.createBaseEntitlement(account.getId(), baseSpec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
// Add ADD_ON
final PlanPhaseSpecifier addOnSpec = new PlanPhaseSpecifier("Telescopic-Scope", ProductCategory.ADD_ON, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
- addOnEntitlement = (DefaultEntitlement) entitlementApi.addEntitlement(baseEntitlement.getBundleId(), addOnSpec, null, initialDate, callContext);
+ addOnEntitlement = (DefaultEntitlement) entitlementApi.addEntitlement(baseEntitlement.getBundleId(), addOnSpec, null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
// Verify the initial state
checkFutureBlockingStatesToCancel(baseEntitlement, null, null);
@@ -106,7 +107,7 @@ public class TestEntitlementUtils extends EntitlementTestSuiteWithEmbeddedDB {
@Test(groups = "slow", description = "Verify add-ons blocking states are added for EOT cancellations")
public void testCancellationEOT() throws Exception {
// Cancel the base plan
- final DefaultEntitlement cancelledBaseEntitlement = (DefaultEntitlement) baseEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.END_OF_TERM, BillingActionPolicy.END_OF_TERM, callContext);
+ final DefaultEntitlement cancelledBaseEntitlement = (DefaultEntitlement) baseEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.END_OF_TERM, BillingActionPolicy.END_OF_TERM, ImmutableList.<PluginProperty>of(), callContext);
// No blocking event (EOT)
assertListenerStatus();
@@ -139,13 +140,13 @@ public class TestEntitlementUtils extends EntitlementTestSuiteWithEmbeddedDB {
@Test(groups = "slow", description = "Verify add-ons blocking states are not impacted for add-on IMM cancellations")
public void testCancellationBaseEOTAddOnIMM() throws Exception {
// Cancel the base plan
- final DefaultEntitlement cancelledBaseEntitlement = (DefaultEntitlement) baseEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.END_OF_TERM, BillingActionPolicy.END_OF_TERM, callContext);
+ final DefaultEntitlement cancelledBaseEntitlement = (DefaultEntitlement) baseEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.END_OF_TERM, BillingActionPolicy.END_OF_TERM, ImmutableList.<PluginProperty>of(), callContext);
// No blocking event (EOT)
assertListenerStatus();
// Cancel the add-on
testListener.pushExpectedEvents(NextEvent.CANCEL, NextEvent.BLOCK);
- final DefaultEntitlement cancelledAddOnEntitlement = (DefaultEntitlement) addOnEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.IMMEDIATE, BillingActionPolicy.IMMEDIATE, callContext);
+ final DefaultEntitlement cancelledAddOnEntitlement = (DefaultEntitlement) addOnEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.IMMEDIATE, BillingActionPolicy.IMMEDIATE, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// Verify the blocking states API doesn't mix the dates (all blocking states are on disk)
@@ -156,7 +157,7 @@ public class TestEntitlementUtils extends EntitlementTestSuiteWithEmbeddedDB {
public void testCancellationBillingIMMEntitlementEOT() throws Exception {
// Cancel the base plan
testListener.pushExpectedEvents(NextEvent.CANCEL, NextEvent.CANCEL);
- final DefaultEntitlement cancelledBaseEntitlement = (DefaultEntitlement) baseEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.END_OF_TERM, BillingActionPolicy.IMMEDIATE, callContext);
+ final DefaultEntitlement cancelledBaseEntitlement = (DefaultEntitlement) baseEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.END_OF_TERM, BillingActionPolicy.IMMEDIATE, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// Verify the blocking states API sees the EOT cancellation (add-on blocking state not on disk)
@@ -171,7 +172,7 @@ public class TestEntitlementUtils extends EntitlementTestSuiteWithEmbeddedDB {
// Cancel the base plan
testListener.pushExpectedEvents(NextEvent.CANCEL, NextEvent.BLOCK, NextEvent.CANCEL, NextEvent.BLOCK);
- final DefaultEntitlement cancelledBaseEntitlement = (DefaultEntitlement) baseEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.IMMEDIATE, BillingActionPolicy.IMMEDIATE, callContext);
+ final DefaultEntitlement cancelledBaseEntitlement = (DefaultEntitlement) baseEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.IMMEDIATE, BillingActionPolicy.IMMEDIATE, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// Refresh the add-on state
@@ -206,7 +207,7 @@ public class TestEntitlementUtils extends EntitlementTestSuiteWithEmbeddedDB {
// Cancel the base plan
testListener.pushExpectedEvents(NextEvent.BLOCK, NextEvent.BLOCK);
- final DefaultEntitlement cancelledBaseEntitlement = (DefaultEntitlement) baseEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.IMMEDIATE, BillingActionPolicy.END_OF_TERM, callContext);
+ final DefaultEntitlement cancelledBaseEntitlement = (DefaultEntitlement) baseEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.IMMEDIATE, BillingActionPolicy.END_OF_TERM, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// Refresh the add-on state
@@ -235,7 +236,7 @@ public class TestEntitlementUtils extends EntitlementTestSuiteWithEmbeddedDB {
@Test(groups = "slow", description = "Verify add-ons blocking states are added for EOT change plans")
public void testChangePlanEOT() throws Exception {
// Change plan EOT to Assault-Rifle (Telescopic-Scope is included)
- final DefaultEntitlement changedBaseEntitlement = (DefaultEntitlement) baseEntitlement.changePlanWithDate("Assault-Rifle", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null, new LocalDate(2013, 10, 7), callContext);
+ final DefaultEntitlement changedBaseEntitlement = (DefaultEntitlement) baseEntitlement.changePlanWithDate("Assault-Rifle", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null, new LocalDate(2013, 10, 7), ImmutableList.<PluginProperty>of(), callContext);
// No blocking event (EOT)
assertListenerStatus();
@@ -270,11 +271,11 @@ public class TestEntitlementUtils extends EntitlementTestSuiteWithEmbeddedDB {
// Add a second ADD_ON (Laser-Scope is available, not included)
testListener.pushExpectedEvents(NextEvent.CREATE);
final PlanPhaseSpecifier secondAddOnSpec = new PlanPhaseSpecifier("Laser-Scope", ProductCategory.ADD_ON, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
- final DefaultEntitlement secondAddOnEntitlement = (DefaultEntitlement) entitlementApi.addEntitlement(baseEntitlement.getBundleId(), secondAddOnSpec, null, clock.getUTCToday(), callContext);
+ final DefaultEntitlement secondAddOnEntitlement = (DefaultEntitlement) entitlementApi.addEntitlement(baseEntitlement.getBundleId(), secondAddOnSpec, null, clock.getUTCToday(), ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// Change plan EOT to Assault-Rifle (Telescopic-Scope is included)
- final DefaultEntitlement changedBaseEntitlement = (DefaultEntitlement) baseEntitlement.changePlanWithDate("Assault-Rifle", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null, new LocalDate(2013, 10, 7), callContext);
+ final DefaultEntitlement changedBaseEntitlement = (DefaultEntitlement) baseEntitlement.changePlanWithDate("Assault-Rifle", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null, new LocalDate(2013, 10, 7), ImmutableList.<PluginProperty>of(), callContext);
// No blocking event (EOT)
assertListenerStatus();
@@ -293,7 +294,7 @@ public class TestEntitlementUtils extends EntitlementTestSuiteWithEmbeddedDB {
// Change plan IMM (upgrade) to Assault-Rifle (Telescopic-Scope is included)
testListener.pushExpectedEvents(NextEvent.CHANGE, NextEvent.CANCEL, NextEvent.BLOCK);
- final DefaultEntitlement changedBaseEntitlement = (DefaultEntitlement) baseEntitlement.changePlan("Assault-Rifle", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null, callContext);
+ final DefaultEntitlement changedBaseEntitlement = (DefaultEntitlement) baseEntitlement.changePlan("Assault-Rifle", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// Refresh the add-on state
@@ -324,21 +325,21 @@ public class TestEntitlementUtils extends EntitlementTestSuiteWithEmbeddedDB {
// Add a second ADD_ON
testListener.pushExpectedEvents(NextEvent.CREATE, NextEvent.PHASE);
final PlanPhaseSpecifier addOn2Spec = new PlanPhaseSpecifier("Telescopic-Scope", ProductCategory.ADD_ON, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
- final Entitlement addOn2Entitlement = entitlementApi.addEntitlement(baseEntitlement.getBundleId(), addOn2Spec, null, initialDate, callContext);
+ final Entitlement addOn2Entitlement = entitlementApi.addEntitlement(baseEntitlement.getBundleId(), addOn2Spec, null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
// Date prior to the base cancellation date to verify it is not impacted by the base cancellation (in contrary to the second add-on)
final LocalDate addOn1CancellationDate = new LocalDate(2013, 9, 9);
- addOnEntitlement.cancelEntitlementWithDate(addOn1CancellationDate, true, callContext);
+ addOnEntitlement.cancelEntitlementWithDate(addOn1CancellationDate, true, ImmutableList.<PluginProperty>of(), callContext);
final LocalDate addOn2CancellationDate = new LocalDate(2013, 11, 11);
- addOn2Entitlement.cancelEntitlementWithDate(addOn2CancellationDate, true, callContext);
+ addOn2Entitlement.cancelEntitlementWithDate(addOn2CancellationDate, true, ImmutableList.<PluginProperty>of(), callContext);
// Before the base entitlement is cancelled, respect the specified cancellation date
Assert.assertEquals(entitlementApi.getEntitlementForId(addOn2Entitlement.getId(), callContext).getEffectiveEndDate(), addOn2CancellationDate);
final LocalDate baseCancellationDate = new LocalDate(2013, 10, 10);
- baseEntitlement.cancelEntitlementWithDate(baseCancellationDate, true, callContext);
+ baseEntitlement.cancelEntitlementWithDate(baseCancellationDate, true, ImmutableList.<PluginProperty>of(), callContext);
// After the base entitlement is cancelled, verify the date is overridden
Assert.assertEquals(entitlementApi.getEntitlementForId(addOn2Entitlement.getId(), callContext).getEffectiveEndDate(), baseCancellationDate);
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/BundleResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/BundleResource.java
index 1b291d4..96c4678 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/BundleResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/BundleResource.java
@@ -55,6 +55,7 @@ import org.killbill.billing.jaxrs.json.TagJson;
import org.killbill.billing.jaxrs.util.Context;
import org.killbill.billing.jaxrs.util.JaxrsUriBuilder;
import org.killbill.billing.payment.api.PaymentApi;
+import org.killbill.billing.payment.api.PluginProperty;
import org.killbill.billing.util.api.AuditUserApi;
import org.killbill.billing.util.api.CustomFieldApiException;
import org.killbill.billing.util.api.CustomFieldUserApi;
@@ -198,16 +199,18 @@ public class BundleResource extends JaxRsResourceBase {
@ApiResponse(code = 404, message = "Bundle not found")})
public Response pauseBundle(@PathParam(ID_PARAM_NAME) final String id,
@QueryParam(QUERY_REQUESTED_DT) final String requestedDate,
+ @QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
@HeaderParam(HDR_CREATED_BY) final String createdBy,
@HeaderParam(HDR_REASON) final String reason,
@HeaderParam(HDR_COMMENT) final String comment,
@javax.ws.rs.core.Context final HttpServletRequest request) throws SubscriptionApiException, EntitlementApiException, AccountApiException {
+ final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final CallContext callContext = context.createContext(createdBy, reason, comment, request);
final UUID bundleId = UUID.fromString(id);
final SubscriptionBundle bundle = subscriptionApi.getSubscriptionBundle(bundleId, callContext);
final LocalDate inputLocalDate = toLocalDate(bundle.getAccountId(), requestedDate, callContext);
- entitlementApi.pause(bundleId, inputLocalDate, callContext);
+ entitlementApi.pause(bundleId, inputLocalDate, pluginProperties, callContext);
return Response.status(Status.OK).build();
}
@@ -221,16 +224,18 @@ public class BundleResource extends JaxRsResourceBase {
@ApiResponse(code = 404, message = "Bundle not found")})
public Response resumeBundle(@PathParam(ID_PARAM_NAME) final String id,
@QueryParam(QUERY_REQUESTED_DT) final String requestedDate,
+ @QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
@HeaderParam(HDR_CREATED_BY) final String createdBy,
@HeaderParam(HDR_REASON) final String reason,
@HeaderParam(HDR_COMMENT) final String comment,
@javax.ws.rs.core.Context final HttpServletRequest request) throws SubscriptionApiException, EntitlementApiException, AccountApiException {
+ final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final CallContext callContext = context.createContext(createdBy, reason, comment, request);
final UUID bundleId = UUID.fromString(id);
final SubscriptionBundle bundle = subscriptionApi.getSubscriptionBundle(bundleId, callContext);
final LocalDate inputLocalDate = toLocalDate(bundle.getAccountId(), requestedDate, callContext);
- entitlementApi.resume(bundleId, inputLocalDate, callContext);
+ entitlementApi.resume(bundleId, inputLocalDate, pluginProperties, callContext);
return Response.status(Status.OK).build();
}
@@ -310,6 +315,7 @@ public class BundleResource extends JaxRsResourceBase {
@PathParam(ID_PARAM_NAME) final String id,
@QueryParam(QUERY_REQUESTED_DT) final String requestedDate,
@QueryParam(QUERY_BILLING_POLICY) @DefaultValue("END_OF_TERM") final String policyString,
+ @QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
@HeaderParam(HDR_CREATED_BY) final String createdBy,
@HeaderParam(HDR_REASON) final String reason,
@HeaderParam(HDR_COMMENT) final String comment,
@@ -318,6 +324,7 @@ public class BundleResource extends JaxRsResourceBase {
verifyNonNullOrEmpty(json, "BundleJson body should be specified");
verifyNonNullOrEmpty(json.getAccountId(), "BundleJson accountId needs to be set");
+ final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final BillingActionPolicy policy = BillingActionPolicy.valueOf(policyString.toUpperCase());
final CallContext callContext = context.createContext(createdBy, reason, comment, request);
@@ -326,7 +333,7 @@ public class BundleResource extends JaxRsResourceBase {
final SubscriptionBundle bundle = subscriptionApi.getSubscriptionBundle(bundleId, callContext);
final LocalDate inputLocalDate = toLocalDate(bundle.getAccountId(), requestedDate, callContext);
- final UUID newBundleId = entitlementApi.transferEntitlementsOverrideBillingPolicy(bundle.getAccountId(), UUID.fromString(json.getAccountId()), bundle.getExternalKey(), inputLocalDate, policy, callContext);
+ final UUID newBundleId = entitlementApi.transferEntitlementsOverrideBillingPolicy(bundle.getAccountId(), UUID.fromString(json.getAccountId()), bundle.getExternalKey(), inputLocalDate, policy, pluginProperties, callContext);
return uriBuilder.buildResponse(BundleResource.class, "getBundle", newBundleId, uriInfo.getBaseUri().toString());
}
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SubscriptionResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SubscriptionResource.java
index a713b8c..7e4dc8d 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SubscriptionResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/SubscriptionResource.java
@@ -72,6 +72,7 @@ import org.killbill.billing.jaxrs.util.Context;
import org.killbill.billing.jaxrs.util.JaxrsUriBuilder;
import org.killbill.billing.jaxrs.util.KillbillEventHandler;
import org.killbill.billing.payment.api.PaymentApi;
+import org.killbill.billing.payment.api.PluginProperty;
import org.killbill.billing.util.api.AuditUserApi;
import org.killbill.billing.util.api.CustomFieldApiException;
import org.killbill.billing.util.api.CustomFieldUserApi;
@@ -149,6 +150,7 @@ public class SubscriptionResource extends JaxRsResourceBase {
@QueryParam(QUERY_REQUESTED_DT) final String requestedDate,
@QueryParam(QUERY_CALL_COMPLETION) @DefaultValue("false") final Boolean callCompletion,
@QueryParam(QUERY_CALL_TIMEOUT) @DefaultValue("3") final long timeoutSec,
+ @QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
@HeaderParam(HDR_CREATED_BY) final String createdBy,
@HeaderParam(HDR_REASON) final String reason,
@HeaderParam(HDR_COMMENT) final String comment,
@@ -160,6 +162,7 @@ public class SubscriptionResource extends JaxRsResourceBase {
entitlement.getBillingPeriod(), "SubscriptionJson billingPeriod needs to be set",
entitlement.getPriceList(), "SubscriptionJson priceList needs to be set");
+ final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final boolean createAddOnEntitlement = ProductCategory.ADD_ON.toString().equals(entitlement.getProductCategory());
if (createAddOnEntitlement) {
verifyNonNullOrEmpty(entitlement.getBundleId(), "SubscriptionJson bundleId should be specified for ADD_ON");
@@ -186,8 +189,8 @@ public class SubscriptionResource extends JaxRsResourceBase {
final List<PlanPhasePriceOverride> overrides = PhasePriceOverrideJson.toPlanPhasePriceOverrides(entitlement.getPriceOverrides(), planSpec, account.getCurrency());
return createAddOnEntitlement ?
- entitlementApi.addEntitlement(bundleId, spec, overrides, inputLocalDate, callContext) :
- entitlementApi.createBaseEntitlement(account.getId(), spec, entitlement.getExternalKey(), overrides, inputLocalDate, callContext);
+ entitlementApi.addEntitlement(bundleId, spec, overrides, inputLocalDate, pluginProperties, callContext) :
+ entitlementApi.createBaseEntitlement(account.getId(), spec, entitlement.getExternalKey(), overrides, inputLocalDate, pluginProperties, callContext);
}
@Override
@@ -215,13 +218,15 @@ public class SubscriptionResource extends JaxRsResourceBase {
@ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid subscription id supplied"),
@ApiResponse(code = 404, message = "Entitlement not found")})
public Response uncancelEntitlementPlan(@PathParam("subscriptionId") final String subscriptionId,
+ @QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
@HeaderParam(HDR_CREATED_BY) final String createdBy,
@HeaderParam(HDR_REASON) final String reason,
@HeaderParam(HDR_COMMENT) final String comment,
@javax.ws.rs.core.Context final HttpServletRequest request) throws EntitlementApiException {
+ final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final UUID uuid = UUID.fromString(subscriptionId);
final Entitlement current = entitlementApi.getEntitlementForId(uuid, context.createContext(createdBy, reason, comment, request));
- current.uncancelEntitlement(context.createContext(createdBy, reason, comment, request));
+ current.uncancelEntitlement(pluginProperties, context.createContext(createdBy, reason, comment, request));
return Response.status(Status.OK).build();
}
@@ -239,6 +244,7 @@ public class SubscriptionResource extends JaxRsResourceBase {
@QueryParam(QUERY_CALL_COMPLETION) @DefaultValue("false") final Boolean callCompletion,
@QueryParam(QUERY_CALL_TIMEOUT) @DefaultValue("3") final long timeoutSec,
@QueryParam(QUERY_BILLING_POLICY) final String policyString,
+ @QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
@HeaderParam(HDR_CREATED_BY) final String createdBy,
@HeaderParam(HDR_REASON) final String reason,
@HeaderParam(HDR_COMMENT) final String comment,
@@ -248,6 +254,7 @@ public class SubscriptionResource extends JaxRsResourceBase {
entitlement.getBillingPeriod(), "SubscriptionJson billingPeriod needs to be set",
entitlement.getPriceList(), "SubscriptionJson priceList needs to be set");
+ final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final CallContext callContext = context.createContext(createdBy, reason, comment, request);
final EntitlementCallCompletionCallback<Response> callback = new EntitlementCallCompletionCallback<Response>() {
@@ -270,12 +277,12 @@ public class SubscriptionResource extends JaxRsResourceBase {
final List<PlanPhasePriceOverride> overrides = PhasePriceOverrideJson.toPlanPhasePriceOverrides(entitlement.getPriceOverrides(), planSpec, account.getCurrency());
if (requestedDate == null && policyString == null) {
- newEntitlement = current.changePlan(entitlement.getProductName(), BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList(), overrides, ctx);
+ newEntitlement = current.changePlan(entitlement.getProductName(), BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList(), overrides, pluginProperties, ctx);
} else if (policyString == null) {
- newEntitlement = current.changePlanWithDate(entitlement.getProductName(), BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList(), overrides, inputLocalDate, ctx);
+ newEntitlement = current.changePlanWithDate(entitlement.getProductName(), BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList(), overrides, inputLocalDate, pluginProperties, ctx);
} else {
final BillingActionPolicy policy = BillingActionPolicy.valueOf(policyString.toUpperCase());
- newEntitlement = current.changePlanOverrideBillingPolicy(entitlement.getProductName(), BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList(), overrides, inputLocalDate, policy, ctx);
+ newEntitlement = current.changePlanOverrideBillingPolicy(entitlement.getProductName(), BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList(), overrides, inputLocalDate, policy, pluginProperties, ctx);
}
isImmediateOp = newEntitlement.getLastActiveProduct().getName().equals(entitlement.getProductName()) &&
newEntitlement.getLastActivePlan().getRecurringBillingPeriod() == BillingPeriod.valueOf(entitlement.getBillingPeriod()) &&
@@ -315,12 +322,14 @@ public class SubscriptionResource extends JaxRsResourceBase {
@QueryParam(QUERY_ENTITLEMENT_POLICY) final String entitlementPolicyString,
@QueryParam(QUERY_BILLING_POLICY) final String billingPolicyString,
@QueryParam(QUERY_USE_REQUESTED_DATE_FOR_BILLING) @DefaultValue("false") final Boolean useRequestedDateForBilling,
+ @QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
@HeaderParam(HDR_CREATED_BY) final String createdBy,
@HeaderParam(HDR_REASON) final String reason,
@HeaderParam(HDR_COMMENT) final String comment,
@javax.ws.rs.core.Context final UriInfo uriInfo,
@javax.ws.rs.core.Context final HttpServletRequest request) throws EntitlementApiException, AccountApiException, SubscriptionApiException {
final CallContext callContext = context.createContext(createdBy, reason, comment, request);
+ final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final EntitlementCallCompletionCallback<Response> callback = new EntitlementCallCompletionCallback<Response>() {
@@ -336,17 +345,17 @@ public class SubscriptionResource extends JaxRsResourceBase {
final LocalDate inputLocalDate = toLocalDate(current.getAccountId(), requestedDate, callContext);
final Entitlement newEntitlement;
if (billingPolicyString == null && entitlementPolicyString == null) {
- newEntitlement = current.cancelEntitlementWithDate(inputLocalDate, useRequestedDateForBilling, ctx);
+ newEntitlement = current.cancelEntitlementWithDate(inputLocalDate, useRequestedDateForBilling, pluginProperties, ctx);
} else if (billingPolicyString == null && entitlementPolicyString != null) {
final EntitlementActionPolicy entitlementPolicy = EntitlementActionPolicy.valueOf(entitlementPolicyString);
- newEntitlement = current.cancelEntitlementWithPolicy(entitlementPolicy, ctx);
+ newEntitlement = current.cancelEntitlementWithPolicy(entitlementPolicy, pluginProperties, ctx);
} else if (billingPolicyString != null && entitlementPolicyString == null) {
final BillingActionPolicy billingPolicy = BillingActionPolicy.valueOf(billingPolicyString.toUpperCase());
- newEntitlement = current.cancelEntitlementWithDateOverrideBillingPolicy(inputLocalDate, billingPolicy, ctx);
+ newEntitlement = current.cancelEntitlementWithDateOverrideBillingPolicy(inputLocalDate, billingPolicy, pluginProperties, ctx);
} else {
final EntitlementActionPolicy entitlementPolicy = EntitlementActionPolicy.valueOf(entitlementPolicyString);
final BillingActionPolicy billingPolicy = BillingActionPolicy.valueOf(billingPolicyString.toUpperCase());
- newEntitlement = current.cancelEntitlementWithPolicyOverrideBillingPolicy(entitlementPolicy, billingPolicy, ctx);
+ newEntitlement = current.cancelEntitlementWithPolicyOverrideBillingPolicy(entitlementPolicy, billingPolicy, pluginProperties, ctx);
}
final Subscription subscription = subscriptionApi.getSubscriptionForEntitlementId(newEntitlement.getId(), ctx);
diff --git a/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestDefaultInternalBillingApi.java b/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestDefaultInternalBillingApi.java
index 7088620..d413692 100644
--- a/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestDefaultInternalBillingApi.java
+++ b/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestDefaultInternalBillingApi.java
@@ -20,6 +20,7 @@ import java.util.List;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
+import org.killbill.billing.payment.api.PluginProperty;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -58,7 +59,7 @@ public class TestDefaultInternalBillingApi extends JunctionTestSuiteWithEmbedded
testListener.pushExpectedEvent(NextEvent.CREATE);
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
- final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, callContext);
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
final SubscriptionBase subscription = subscriptionInternalApi.getSubscriptionFromId(entitlement.getId(), internalCallContext);
assertListenerStatus();
@@ -195,7 +196,7 @@ public class TestDefaultInternalBillingApi extends JunctionTestSuiteWithEmbedded
testListener.pushExpectedEvent(NextEvent.CREATE);
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
- final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, callContext);
+ final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, initialDate, ImmutableList.<PluginProperty>of(), callContext);
final SubscriptionBase subscription = subscriptionInternalApi.getSubscriptionFromId(entitlement.getId(), internalCallContext);
assertListenerStatus();
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/applicator/OverdueStateApplicator.java b/overdue/src/main/java/org/killbill/billing/overdue/applicator/OverdueStateApplicator.java
index 99bc820..ab8e2ba 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/applicator/OverdueStateApplicator.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/applicator/OverdueStateApplicator.java
@@ -57,6 +57,7 @@ import org.killbill.billing.overdue.glue.DefaultOverdueModule;
import org.killbill.billing.overdue.notification.OverdueCheckNotificationKey;
import org.killbill.billing.overdue.notification.OverdueCheckNotifier;
import org.killbill.billing.overdue.notification.OverduePoster;
+import org.killbill.billing.payment.api.PluginProperty;
import org.killbill.billing.tag.TagInternalApi;
import org.killbill.billing.util.api.TagApiException;
import org.killbill.billing.util.callcontext.CallContext;
@@ -300,7 +301,7 @@ public class OverdueStateApplicator {
for (final Entitlement cur : toBeCancelled) {
try {
- cur.cancelEntitlementWithDateOverrideBillingPolicy(new LocalDate(clock.getUTCNow(), account.getTimeZone()), actionPolicy, callContext);
+ cur.cancelEntitlementWithDateOverrideBillingPolicy(new LocalDate(clock.getUTCNow(), account.getTimeZone()), actionPolicy, ImmutableList.<PluginProperty>of(), callContext);
} catch (final EntitlementApiException e) {
// If subscription has already been cancelled, there is nothing to do so we can ignore
if (e.getCode() != ErrorCode.SUB_CANCEL_BAD_STATE.getCode()) {