Search in sources :

Example 31 with DefaultBlockingState

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();
}
Also used : Account(org.killbill.billing.account.api.Account) Invoice(org.killbill.billing.invoice.api.Invoice) BillingPeriod(org.killbill.billing.catalog.api.BillingPeriod) ArrayList(java.util.ArrayList) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) BlockingState(org.killbill.billing.entitlement.api.BlockingState) ExpectedInvoiceItemCheck(org.killbill.billing.beatrix.util.InvoiceChecker.ExpectedInvoiceItemCheck) LocalDate(org.joda.time.LocalDate) DateTime(org.joda.time.DateTime) BigDecimal(java.math.BigDecimal) DefaultEntitlement(org.killbill.billing.entitlement.api.DefaultEntitlement) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) Test(org.testng.annotations.Test)

Example 32 with DefaultBlockingState

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();
}
Also used : PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) DefaultEntitlementSpecifier(org.killbill.billing.entitlement.api.DefaultEntitlementSpecifier) Account(org.killbill.billing.account.api.Account) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) BlockingState(org.killbill.billing.entitlement.api.BlockingState) DateTime(org.joda.time.DateTime) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) Test(org.testng.annotations.Test)

Example 33 with DefaultBlockingState

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();
}
Also used : PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) DefaultEntitlementSpecifier(org.killbill.billing.entitlement.api.DefaultEntitlementSpecifier) Account(org.killbill.billing.account.api.Account) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) BlockingState(org.killbill.billing.entitlement.api.BlockingState) UUID(java.util.UUID) Entitlement(org.killbill.billing.entitlement.api.Entitlement) DateTime(org.joda.time.DateTime) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) Test(org.testng.annotations.Test)

Example 34 with DefaultBlockingState

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);
}
Also used : PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) Account(org.killbill.billing.account.api.Account) BillingEvent(org.killbill.billing.junction.BillingEvent) Entitlement(org.killbill.billing.entitlement.api.Entitlement) LocalDate(org.joda.time.LocalDate) DateTime(org.joda.time.DateTime) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) Test(org.testng.annotations.Test)

Example 35 with DefaultBlockingState

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);
}
Also used : WithEntitlementPlugin(org.killbill.billing.entitlement.api.EntitlementPluginExecution.WithEntitlementPlugin) EventsStream(org.killbill.billing.entitlement.EventsStream) ArrayList(java.util.ArrayList) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) DateTime(org.joda.time.DateTime) SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) EntitlementLoggingHelper.logPauseResumeEntitlement(org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logPauseResumeEntitlement) EntitlementLoggingHelper.logTransferEntitlement(org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logTransferEntitlement) EntitlementLoggingHelper.logCreateEntitlement(org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logCreateEntitlement) EntitlementContext(org.killbill.billing.entitlement.plugin.api.EntitlementContext) DefaultBlockingState(org.killbill.billing.junction.DefaultBlockingState) SubscriptionBaseApiException(org.killbill.billing.subscription.api.user.SubscriptionBaseApiException) PlanPhasePriceOverride(org.killbill.billing.catalog.api.PlanPhasePriceOverride)

Aggregations

DefaultBlockingState (org.killbill.billing.junction.DefaultBlockingState)63 UUID (java.util.UUID)46 DateTime (org.joda.time.DateTime)38 BlockingState (org.killbill.billing.entitlement.api.BlockingState)37 Test (org.testng.annotations.Test)35 LocalDate (org.joda.time.LocalDate)34 Account (org.killbill.billing.account.api.Account)23 ArrayList (java.util.ArrayList)21 PlanPhaseSpecifier (org.killbill.billing.catalog.api.PlanPhaseSpecifier)19 DateTimeZone (org.joda.time.DateTimeZone)14 DefaultEntitlementSpecifier (org.killbill.billing.entitlement.api.DefaultEntitlementSpecifier)14 SubscriptionBaseTransition (org.killbill.billing.subscription.api.user.SubscriptionBaseTransition)11 SubscriptionBase (org.killbill.billing.subscription.api.SubscriptionBase)9 Entitlement (org.killbill.billing.entitlement.api.Entitlement)8 InternalCallContext (org.killbill.billing.callcontext.InternalCallContext)7 WithEntitlementPlugin (org.killbill.billing.entitlement.api.EntitlementPluginExecution.WithEntitlementPlugin)7 EntitlementContext (org.killbill.billing.entitlement.plugin.api.EntitlementContext)7 SubscriptionBaseApiException (org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)7 BigDecimal (java.math.BigDecimal)6 BillingEvent (org.killbill.billing.junction.BillingEvent)6