use of org.killbill.billing.junction.DefaultBlockingState in project killbill by killbill.
the class TestWithBCDUpdate method testBlockPastUnpaidPeriodAndRealignBCD.
@Test(groups = "slow")
public void testBlockPastUnpaidPeriodAndRealignBCD() throws Exception {
final List<ExpectedInvoiceItemCheck> expectedInvoices = new ArrayList<ExpectedInvoiceItemCheck>();
List<Invoice> invoices = null;
final DateTime initialDate = new DateTime(2016, 4, 1, 0, 13, 42, 0, testTimeZone);
clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(0));
assertNotNull(account);
// BP creation : Will set Account BCD to the first (2016-4-1 + 30 days = 2016-5-1)
final String productName = "Shotgun";
final BillingPeriod term = BillingPeriod.MONTHLY;
final DefaultEntitlement baseEntitlement = createBaseEntitlementAndCheckForCompletion(account.getId(), "bundleKey", productName, ProductCategory.BASE, term, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
paymentPlugin.makeNextPaymentFailWithError();
// 2016-5-1 : BP out of TRIAL
busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT_ERROR, NextEvent.INVOICE_PAYMENT_ERROR);
clock.addDays(30);
assertListenerStatus();
//
// Let's assume 15 days later, the customer comes back and wants to continue using the service (after he updated his payment method)
//
// The company 'a.b.c' decides to block both the billing and entitlement for the past 15 days and also move his BCD to
// the 16 so he gets to pay right away and for a full period (MONTHLY)
//
// 2016-5-16
busHandler.pushExpectedEvents(NextEvent.INVOICE_PAYMENT_ERROR, NextEvent.PAYMENT_ERROR);
paymentPlugin.makeNextPaymentFailWithError();
clock.addDays(15);
assertListenerStatus();
// First BLOCK subscription starting from the 2016-5-1
// This will generate the credit for the full period, bringing by account balance to 0
busHandler.pushExpectedEvents(NextEvent.BLOCK, NextEvent.INVOICE, NextEvent.INVOICE_ADJUSTMENT);
final BlockingState blockingState = new DefaultBlockingState(baseEntitlement.getId(), BlockingStateType.SUBSCRIPTION, "COURTESY_BLOCK", "company.a.b.c", true, true, true, null);
subscriptionApi.addBlockingState(blockingState, new LocalDate(2016, 5, 1), ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
expectedInvoices.add(new ExpectedInvoiceItemCheck(new LocalDate(2016, 5, 1), new LocalDate(2016, 6, 1), InvoiceItemType.REPAIR_ADJ, new BigDecimal("-249.95")));
expectedInvoices.add(new ExpectedInvoiceItemCheck(new LocalDate(2016, 5, 16), new LocalDate(2016, 5, 16), InvoiceItemType.CBA_ADJ, new BigDecimal("249.95")));
invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), false, false, callContext);
invoiceChecker.checkInvoice(invoices.get(2).getId(), callContext, expectedInvoices);
expectedInvoices.clear();
// Second, move the BCD to the 16
// Because we did not unblock yet, we don't have a new invoice but we see the NULL_INVOICE event
busHandler.pushExpectedEvents(NextEvent.BCD_CHANGE, NextEvent.NULL_INVOICE);
subscriptionBaseInternalApi.updateBCD(baseEntitlement.getId(), 16, null, internalCallContext);
assertListenerStatus();
// Third, unblock starting at the 16, will generate a full period invoice
busHandler.pushExpectedEvents(NextEvent.BLOCK, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
final BlockingState unblockingState = new DefaultBlockingState(baseEntitlement.getId(), BlockingStateType.SUBSCRIPTION, "END_OF_COURTESY_BLOCK", "company.a.b.c", false, false, false, null);
subscriptionApi.addBlockingState(unblockingState, new LocalDate(2016, 5, 16), ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
expectedInvoices.add(new ExpectedInvoiceItemCheck(new LocalDate(2016, 5, 16), new LocalDate(2016, 6, 16), InvoiceItemType.RECURRING, new BigDecimal("249.95")));
invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), false, false, callContext);
invoiceChecker.checkInvoice(invoices.get(3).getId(), callContext, expectedInvoices);
expectedInvoices.clear();
}
use of org.killbill.billing.junction.DefaultBlockingState in project killbill by killbill.
the class TestMigrationSubscriptions method testBlockingStatesV1.
// Not exactly migration tests, but verify correct behavior when using BlockingState (see https://github.com/killbill/killbill/issues/744)
@Test(groups = "slow")
public void testBlockingStatesV1() throws Exception {
final DateTime initialDate = new DateTime(2017, 3, 1, 0, 1, 35, 0, DateTimeZone.UTC);
clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(0));
assertNotNull(account);
busHandler.pushExpectedEvents(NextEvent.BLOCK, NextEvent.NULL_INVOICE);
final BlockingState blockingState1 = new DefaultBlockingState(account.getId(), BlockingStateType.ACCOUNT, "state1", "Service", false, false, true, null);
subscriptionApi.addBlockingState(blockingState1, null, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
clock.addDays(1);
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("pistol-monthly-notrial", null);
busHandler.pushExpectedEvents(NextEvent.CREATE, NextEvent.BLOCK, NextEvent.NULL_INVOICE);
entitlementApi.createBaseEntitlement(account.getId(), new DefaultEntitlementSpecifier(spec), "bundleExternalKey", null, null, false, true, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
clock.addMonths(1);
busHandler.pushExpectedEvents(NextEvent.BLOCK, NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
final BlockingState blockingState2 = new DefaultBlockingState(account.getId(), BlockingStateType.ACCOUNT, "state2", "Service", false, false, false, null);
subscriptionApi.addBlockingState(blockingState2, null, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
clock.addMonths(1);
assertListenerStatus();
}
use of org.killbill.billing.junction.DefaultBlockingState in project killbill by killbill.
the class TestMigrationSubscriptions method testBlockingStatesV4.
@Test(groups = "slow")
public void testBlockingStatesV4() throws Exception {
final DateTime initialDate = new DateTime(2017, 3, 1, 0, 1, 35, 0, DateTimeZone.UTC);
clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(0));
assertNotNull(account);
busHandler.pushExpectedEvents(NextEvent.BLOCK, NextEvent.NULL_INVOICE);
final BlockingState blockingState1 = new DefaultBlockingState(account.getId(), BlockingStateType.ACCOUNT, "state1", "Service", false, false, true, null);
subscriptionApi.addBlockingState(blockingState1, null, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
clock.addDays(1);
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("pistol-monthly-notrial", null);
busHandler.pushExpectedEvents(NextEvent.CREATE, NextEvent.BLOCK, NextEvent.NULL_INVOICE);
final UUID baseEntitlementId = entitlementApi.createBaseEntitlement(account.getId(), new DefaultEntitlementSpecifier(spec), "bundleExternalKey", null, null, false, true, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
final Entitlement baseEntitlement = entitlementApi.getEntitlementForId(baseEntitlementId, callContext);
clock.addDays(1);
// Add an add-on while bundle is already blocked
final PlanPhaseSpecifier spec2 = new PlanPhaseSpecifier("cleaning-monthly", null);
busHandler.pushExpectedEvents(NextEvent.CREATE, NextEvent.BLOCK, NextEvent.NULL_INVOICE);
entitlementApi.addEntitlement(baseEntitlement.getBundleId(), new DefaultEntitlementSpecifier(spec2), null, null, false, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
clock.addMonths(1);
busHandler.pushExpectedEvents(NextEvent.BLOCK, NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
final BlockingState blockingState2 = new DefaultBlockingState(account.getId(), BlockingStateType.ACCOUNT, "state2", "Service", false, false, false, null);
subscriptionApi.addBlockingState(blockingState2, null, ImmutableList.<PluginProperty>of(), callContext);
assertListenerStatus();
busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.INVOICE_PAYMENT, NextEvent.PAYMENT);
clock.addMonths(1);
assertListenerStatus();
}
use of org.killbill.billing.junction.DefaultBlockingState in project killbill by killbill.
the class TestDefaultInternalBillingApi method testUnblockThenBlockBlockingStatesWithSameEffectiveDate.
// See https://github.com/killbill/killbill/commit/92042843e38a67f75495b207385e4c1f9ca60990#commitcomment-4749967
@Test(groups = "slow", description = "Check unblock then block states with same effective date are correctly handled", invocationCount = 10)
public void testUnblockThenBlockBlockingStatesWithSameEffectiveDate() throws Exception {
final LocalDate initialDate = new LocalDate(2013, 8, 7);
clock.setDay(initialDate);
final Account account = createAccount(getAccountData(7));
testListener.pushExpectedEvents(NextEvent.CREATE, NextEvent.BLOCK);
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, null, null, false, ImmutableList.<PluginProperty>of(), callContext);
final SubscriptionBase subscription = subscriptionInternalApi.getSubscriptionFromId(entitlement.getId(), internalCallContext);
assertListenerStatus();
final DateTime block1Date = clock.getUTCNow();
testListener.pushExpectedEvents(NextEvent.BLOCK);
final DefaultBlockingState state1 = new DefaultBlockingState(account.getId(), BlockingStateType.ACCOUNT, DefaultEntitlementApi.ENT_STATE_BLOCKED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, true, block1Date);
blockingInternalApi.setBlockingState(state1, internalCallContext);
clock.addDays(1);
final DateTime block2Date = clock.getUTCNow();
testListener.pushExpectedEvents(NextEvent.BLOCK, NextEvent.BLOCK);
final DefaultBlockingState state2 = new DefaultBlockingState(account.getId(), BlockingStateType.ACCOUNT, DefaultEntitlementApi.ENT_STATE_CLEAR, EntitlementService.ENTITLEMENT_SERVICE_NAME, false, false, false, block2Date);
blockingInternalApi.setBlockingState(state2, internalCallContext);
// Same date
final DefaultBlockingState state3 = new DefaultBlockingState(account.getId(), BlockingStateType.ACCOUNT, DefaultEntitlementApi.ENT_STATE_BLOCKED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, true, block2Date);
blockingInternalApi.setBlockingState(state3, internalCallContext);
assertListenerStatus();
// Nothing should happen
clock.addDays(3);
assertListenerStatus();
// Expected blocking duration:
// * 2013-08-07 to now [2013-08-07 to 2013-08-08 then 2013-08-08 to now]
final List<BillingEvent> events = ImmutableList.<BillingEvent>copyOf(billingInternalApi.getBillingEventsForAccountAndUpdateAccountBCD(account.getId(), null, internalCallContext));
Assert.assertEquals(events.size(), 2);
Assert.assertEquals(events.get(0).getTransitionType(), SubscriptionBaseTransitionType.CREATE);
Assert.assertEquals(events.get(0).getEffectiveDate(), subscription.getStartDate());
Assert.assertEquals(events.get(1).getTransitionType(), SubscriptionBaseTransitionType.START_BILLING_DISABLED);
Assert.assertEquals(events.get(1).getEffectiveDate(), block1Date);
}
use of org.killbill.billing.junction.DefaultBlockingState in project killbill by killbill.
the class DefaultEntitlementApi method addEntitlement.
@Override
public Entitlement addEntitlement(final UUID bundleId, final PlanPhaseSpecifier planPhaseSpecifier, final List<PlanPhasePriceOverride> overrides, @Nullable final LocalDate entitlementEffectiveDate, @Nullable final LocalDate billingEffectiveDate, final boolean isMigrated, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
logCreateEntitlement(log, bundleId, planPhaseSpecifier, overrides, entitlementEffectiveDate, billingEffectiveDate);
final EntitlementSpecifier entitlementSpecifier = new DefaultEntitlementSpecifier(planPhaseSpecifier, overrides);
final List<EntitlementSpecifier> entitlementSpecifierList = new ArrayList<EntitlementSpecifier>();
entitlementSpecifierList.add(entitlementSpecifier);
final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = new DefaultBaseEntitlementWithAddOnsSpecifier(bundleId, null, entitlementSpecifierList, entitlementEffectiveDate, billingEffectiveDate, isMigrated);
final List<BaseEntitlementWithAddOnsSpecifier> baseEntitlementWithAddOnsSpecifierList = new ArrayList<BaseEntitlementWithAddOnsSpecifier>();
baseEntitlementWithAddOnsSpecifierList.add(baseEntitlementWithAddOnsSpecifier);
final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.CREATE_SUBSCRIPTION, null, null, baseEntitlementWithAddOnsSpecifierList, null, properties, callContext);
final WithEntitlementPlugin<Entitlement> addEntitlementWithPlugin = new WithEntitlementPlugin<Entitlement>() {
@Override
public Entitlement doCall(final EntitlementApi entitlementApi, final EntitlementContext updatedPluginContext) throws EntitlementApiException {
final EventsStream eventsStreamForBaseSubscription = eventsStreamBuilder.buildForBaseSubscription(bundleId, callContext);
if (eventsStreamForBaseSubscription.isEntitlementCancelled() || (eventsStreamForBaseSubscription.isEntitlementPending() && (baseEntitlementWithAddOnsSpecifier.getEntitlementEffectiveDate() == null || baseEntitlementWithAddOnsSpecifier.getEntitlementEffectiveDate().compareTo(eventsStreamForBaseSubscription.getEntitlementEffectiveStartDate()) < 0))) {
throw new EntitlementApiException(ErrorCode.SUB_GET_NO_SUCH_BASE_SUBSCRIPTION, bundleId);
}
// Check the base entitlement state is not blocked
if (eventsStreamForBaseSubscription.isBlockChange()) {
throw new EntitlementApiException(new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, BlockingChecker.ACTION_CHANGE, BlockingChecker.TYPE_SUBSCRIPTION, eventsStreamForBaseSubscription.getEntitlementId().toString()));
}
try {
final BaseEntitlementWithAddOnsSpecifier baseEntitlementWithAddOnsSpecifier = getFirstBaseEntitlementWithAddOnsSpecifier(updatedPluginContext.getBaseEntitlementWithAddOnsSpecifiers());
final EntitlementSpecifier specifier = getFirstEntitlementSpecifier(baseEntitlementWithAddOnsSpecifier);
final InternalCallContext context = internalCallContextFactory.createInternalCallContext(eventsStreamForBaseSubscription.getAccountId(), callContext);
final DateTime billingRequestedDate = dateHelper.fromLocalDateAndReferenceTime(baseEntitlementWithAddOnsSpecifier.getBillingEffectiveDate(), context);
final SubscriptionBase subscription = subscriptionBaseInternalApi.createSubscription(bundleId, specifier.getPlanPhaseSpecifier(), specifier.getOverrides(), billingRequestedDate, isMigrated, context);
final DateTime entitlementRequestedDate = dateHelper.fromLocalDateAndReferenceTime(baseEntitlementWithAddOnsSpecifier.getEntitlementEffectiveDate(), context);
final BlockingState newBlockingState = new DefaultBlockingState(subscription.getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_START, EntitlementService.ENTITLEMENT_SERVICE_NAME, false, false, false, entitlementRequestedDate);
entitlementUtils.setBlockingStatesAndPostBlockingTransitionEvent(ImmutableList.<BlockingState>of(newBlockingState), subscription.getBundleId(), context);
return new DefaultEntitlement(eventsStreamForBaseSubscription.getAccountId(), subscription.getId(), eventsStreamBuilder, entitlementApi, pluginExecution, blockingStateDao, subscriptionBaseInternalApi, checker, notificationQueueService, entitlementUtils, dateHelper, clock, securityApi, internalCallContextFactory, callContext);
} catch (final SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
}
}
};
return pluginExecution.executeWithPlugin(addEntitlementWithPlugin, pluginContext);
}
Aggregations