use of org.killbill.billing.junction.DefaultBlockingState in project killbill by killbill.
the class DefaultEntitlement method cancelEntitlementWithDateOverrideBillingPolicy.
// See also EntitlementInternalApi#cancel for the bulk API
@Override
public Entitlement cancelEntitlementWithDateOverrideBillingPolicy(@Nullable final LocalDate entitlementEffectiveDate, final BillingActionPolicy billingPolicy, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
logCancelEntitlement(log, this, entitlementEffectiveDate, null, null, billingPolicy);
checkForPermissions(Permission.ENTITLEMENT_CAN_CANCEL, callContext);
// Get the latest state from disk
refresh(callContext);
final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(getBundleId(), getBundleExternalKey(), null, entitlementEffectiveDate, entitlementEffectiveDate, false);
final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementWithAddOnsSpecifier);
final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CANCEL_SUBSCRIPTION, getAccountId(), null, baseEntitlementWithAddOnsSpecifierList, billingPolicy, properties, callContext);
final WithEntitlementPlugin<Entitlement> cancelEntitlementWithPlugin = new WithEntitlementPlugin<Entitlement>() {
@Override
public Entitlement doCall(final EntitlementApi entitlementApi, final DefaultEntitlementContext updatedPluginContext) throws EntitlementApiException {
if (eventsStream.isEntitlementCancelled()) {
throw new EntitlementApiException(ErrorCode.SUB_CANCEL_BAD_STATE, getId(), EntitlementState.CANCELLED);
}
final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
try {
// Cancel subscription base first, to correctly compute the add-ons entitlements we need to cancel (see below)
getSubscriptionBase().cancelWithPolicy(billingPolicy, callContext);
} catch (final SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
}
final DateTime effectiveCancelDate = dateHelper.fromLocalDateAndReferenceTimeWithMinimum(entitlementEffectiveDate, getEventsStream().getEntitlementEffectiveStartDateTime(), updatedPluginContext.getCreatedDate(), contextWithValidAccountRecordId);
final BlockingState newBlockingState = new DefaultBlockingState(getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_CANCELLED, KILLBILL_SERVICES.ENTITLEMENT_SERVICE.getServiceName(), true, true, false, effectiveCancelDate);
final Collection<NotificationEvent> notificationEvents = new ArrayList<NotificationEvent>();
final Collection<BlockingState> addOnsBlockingStates = computeAddOnBlockingStates(effectiveCancelDate, notificationEvents, callContext, contextWithValidAccountRecordId);
// Record the new state first, then insert the notifications to avoid race conditions
setBlockingStates(newBlockingState, addOnsBlockingStates, contextWithValidAccountRecordId);
for (final NotificationEvent notificationEvent : notificationEvents) {
recordFutureNotification(effectiveCancelDate, notificationEvent, contextWithValidAccountRecordId);
}
return entitlementApi.getEntitlementForId(getId(), callContext);
}
};
return pluginExecution.executeWithPlugin(cancelEntitlementWithPlugin, pluginContext);
}
use of org.killbill.billing.junction.DefaultBlockingState in project killbill by killbill.
the class DefaultEventsStream method computeAddonsBlockingStatesForSubscriptionBaseEvent.
private Collection<BlockingState> computeAddonsBlockingStatesForSubscriptionBaseEvent(@Nullable final Product baseTransitionTriggerNextProduct, final DateTime blockingStateEffectiveDate) {
if (baseSubscription == null || baseSubscription.getLastActivePlan() == null || !ProductCategory.BASE.equals(baseSubscription.getLastActivePlan().getProduct().getCategory())) {
return ImmutableList.<BlockingState>of();
}
// Compute included and available addons for the new product
final Collection<String> includedAddonsForProduct;
final Collection<String> availableAddonsForProduct;
if (baseTransitionTriggerNextProduct == null) {
includedAddonsForProduct = ImmutableList.<String>of();
availableAddonsForProduct = ImmutableList.<String>of();
} else {
includedAddonsForProduct = Collections2.<Product, String>transform(ImmutableSet.<Product>copyOf(baseTransitionTriggerNextProduct.getIncluded()), new Function<Product, String>() {
@Override
public String apply(final Product product) {
return product.getName();
}
});
availableAddonsForProduct = Collections2.<Product, String>transform(ImmutableSet.<Product>copyOf(baseTransitionTriggerNextProduct.getAvailable()), new Function<Product, String>() {
@Override
public String apply(final Product product) {
return product.getName();
}
});
}
// Retrieve all add-ons to block for that base subscription
final Collection<SubscriptionBase> futureBlockedAddons = Collections2.<SubscriptionBase>filter(allSubscriptionsForBundle, new Predicate<SubscriptionBase>() {
@Override
public boolean apply(final SubscriptionBase subscription) {
final Plan lastActivePlan = subscription.getLastActivePlan();
final boolean result = ProductCategory.ADD_ON.equals(subscription.getCategory()) && // Check the subscription started, if not we don't want it, and that way we avoid doing NPE a few lines below.
lastActivePlan != null && // Check the entitlement for that add-on hasn't been cancelled yet
getEntitlementCancellationEvent(subscription.getId()) == null && (// Base subscription cancelled
baseTransitionTriggerNextProduct == null || (// Change plan - check which add-ons to cancel
includedAddonsForProduct.contains(lastActivePlan.getProduct().getName()) || !availableAddonsForProduct.contains(subscription.getLastActivePlan().getProduct().getName())));
return result;
}
});
// Create the blocking states
return Collections2.<SubscriptionBase, BlockingState>transform(futureBlockedAddons, new Function<SubscriptionBase, BlockingState>() {
@Override
public BlockingState apply(final SubscriptionBase input) {
return new DefaultBlockingState(input.getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_CANCELLED, KILLBILL_SERVICES.ENTITLEMENT_SERVICE.getServiceName(), true, true, false, blockingStateEffectiveDate);
}
});
}
use of org.killbill.billing.junction.DefaultBlockingState in project killbill by killbill.
the class TestBlockingApi method testApi.
@Test(groups = "slow")
public void testApi() {
final UUID uuid = UUID.randomUUID();
final String overdueStateName = "WayPassedItMan";
final String service = "TEST";
final boolean blockChange = true;
final boolean blockEntitlement = false;
final boolean blockBilling = false;
testListener.pushExpectedEvent(NextEvent.BLOCK);
final BlockingState state1 = new DefaultBlockingState(uuid, BlockingStateType.ACCOUNT, overdueStateName, service, blockChange, blockEntitlement, blockBilling, clock.getUTCNow());
blockingInternalApi.setBlockingState(state1, internalCallContext);
assertListenerStatus();
clock.setDeltaFromReality(1000 * 3600 * 24);
testListener.pushExpectedEvent(NextEvent.BLOCK);
final String overdueStateName2 = "NoReallyThisCantGoOn";
final BlockingState state2 = new DefaultBlockingState(uuid, BlockingStateType.ACCOUNT, overdueStateName2, service, blockChange, blockEntitlement, blockBilling, clock.getUTCNow());
blockingInternalApi.setBlockingState(state2, internalCallContext);
assertListenerStatus();
Assert.assertEquals(blockingInternalApi.getBlockingStateForService(uuid, BlockingStateType.ACCOUNT, service, internalCallContext).getStateName(), overdueStateName2);
}
use of org.killbill.billing.junction.DefaultBlockingState in project killbill by killbill.
the class TestBlockingApi method testBlockingAcrossTypes.
@Test(groups = "slow")
public void testBlockingAcrossTypes() throws Exception {
final String stateNameBlock = "stateBlock";
final String stateNameUnBlock = "stateUnBlock";
final String service = "SVC_BLOC_TYPES";
final boolean blockChange = false;
final boolean blockEntitlement = true;
final boolean blockBilling = true;
final Account account = createAccount(getAccountData(7));
testListener.pushExpectedEvent(NextEvent.BLOCK);
final BlockingState state1 = new DefaultBlockingState(account.getId(), BlockingStateType.ACCOUNT, stateNameBlock, service, blockChange, blockEntitlement, blockBilling, clock.getUTCNow());
subscriptionApi.addBlockingState(state1, null, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, null);
testListener.pushExpectedEvents(NextEvent.CREATE, NextEvent.BLOCK);
final UUID baseEntitlementId = entitlementApi.createBaseEntitlement(account.getId(), new DefaultEntitlementSpecifier(spec), account.getExternalKey(), null, null, false, true, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
Entitlement baseEntitlement = entitlementApi.getEntitlementForId(baseEntitlementId, callContext);
assertEquals(baseEntitlement.getState(), EntitlementState.BLOCKED);
// Add blocking at bundle level.
clock.addDays(1);
testListener.pushExpectedEvent(NextEvent.BLOCK);
final BlockingState state2 = new DefaultBlockingState(baseEntitlement.getBundleId(), BlockingStateType.SUBSCRIPTION_BUNDLE, stateNameBlock, service, blockChange, blockEntitlement, blockBilling, null);
subscriptionApi.addBlockingState(state2, null, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
baseEntitlement = entitlementApi.getEntitlementForId(baseEntitlement.getId(), callContext);
assertEquals(baseEntitlement.getState(), EntitlementState.BLOCKED);
// Remove blocking at account level
clock.addDays(1);
testListener.pushExpectedEvent(NextEvent.BLOCK);
final BlockingState state3 = new DefaultBlockingState(account.getId(), BlockingStateType.ACCOUNT, stateNameUnBlock, service, false, false, false, clock.getUTCNow());
subscriptionApi.addBlockingState(state3, null, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
baseEntitlement = entitlementApi.getEntitlementForId(baseEntitlement.getId(), callContext);
assertEquals(baseEntitlement.getState(), EntitlementState.BLOCKED);
// Remove blocking at bundle level.
clock.addDays(1);
testListener.pushExpectedEvent(NextEvent.BLOCK);
final BlockingState state4 = new DefaultBlockingState(baseEntitlement.getBundleId(), BlockingStateType.SUBSCRIPTION_BUNDLE, stateNameUnBlock, service, false, false, false, null);
subscriptionApi.addBlockingState(state4, null, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
baseEntitlement = entitlementApi.getEntitlementForId(baseEntitlement.getId(), callContext);
assertEquals(baseEntitlement.getState(), EntitlementState.ACTIVE);
final List<BlockingState> blockingAll = blockingInternalApi.getBlockingActiveForAccount(catalog, null, internalCallContext);
final List<BlockingState> history = ImmutableList.<BlockingState>copyOf(Collections2.<BlockingState>filter(blockingAll, new Predicate<BlockingState>() {
@Override
public boolean apply(final BlockingState input) {
return input.getService().equals(service);
}
}));
Assert.assertEquals(history.size(), 4);
}
use of org.killbill.billing.junction.DefaultBlockingState in project killbill by killbill.
the class TestBlockingApi method testApiHistory.
@Test(groups = "slow")
public void testApiHistory() throws Exception {
final String overdueStateName = "WayPassedItMan";
final String service = "TEST";
final boolean blockChange = true;
final boolean blockEntitlement = false;
final boolean blockBilling = true;
final Account account = createAccount(getAccountData(7));
testListener.pushExpectedEvent(NextEvent.BLOCK);
final BlockingState state1 = new DefaultBlockingState(account.getId(), BlockingStateType.ACCOUNT, overdueStateName, service, blockChange, blockEntitlement, blockBilling, clock.getUTCNow());
blockingInternalApi.setBlockingState(state1, internalCallContext);
assertListenerStatus();
clock.setDeltaFromReality(1000 * 3600 * 24);
testListener.pushExpectedEvent(NextEvent.BLOCK);
final String overdueStateName2 = "NoReallyThisCantGoOn";
final BlockingState state2 = new DefaultBlockingState(account.getId(), BlockingStateType.ACCOUNT, overdueStateName2, service, blockChange, blockEntitlement, blockBilling, clock.getUTCNow());
blockingInternalApi.setBlockingState(state2, internalCallContext);
assertListenerStatus();
final List<BlockingState> blockingAll = blockingInternalApi.getBlockingActiveForAccount(catalog, null, internalCallContext);
final List<BlockingState> history = ImmutableList.<BlockingState>copyOf(Collections2.<BlockingState>filter(blockingAll, new Predicate<BlockingState>() {
@Override
public boolean apply(final BlockingState input) {
return input.getService().equals(service);
}
}));
Assert.assertEquals(history.size(), 2);
Assert.assertEquals(history.get(0).getStateName(), overdueStateName);
Assert.assertEquals(history.get(1).getStateName(), overdueStateName2);
}
Aggregations