@BeforeMethod(groups = "fast") public void beforeMethod() throws Exception { super.beforeMethod(); final SubscriptionBaseBundle bundle = Mockito.mock(SubscriptionBaseBundle.class); Mockito.when(bundle.getId()).thenReturn(bunId); final List<SubscriptionBaseBundle> bundles = ImmutableList.<SubscriptionBaseBundle>of(bundle); effectiveSubscriptionTransitions = new LinkedList<EffectiveSubscriptionInternalEvent>(); final DateTime subscriptionStartDate = clock.getUTCNow().minusDays(3); subscription = new MockSubscription(subId, bunId, null, subscriptionStartDate, effectiveSubscriptionTransitions); final List<SubscriptionBase> subscriptions = ImmutableList.<SubscriptionBase>of(subscription); Mockito.when(subscriptionInternalApi.getBundlesForAccount(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(bundles); Mockito.when(subscriptionInternalApi.getSubscriptionsForBundle(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(subscriptions); Mockito.when(subscriptionInternalApi.getSubscriptionFromId(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(subscription); Mockito.when(subscriptionInternalApi.getBundleFromId(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(bundle); Mockito.when(subscriptionInternalApi.getBaseSubscription(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(subscription); Mockito.when(subscriptionInternalApi.getBillingTransitions(Mockito.<SubscriptionBase>any(), Mockito.<InternalTenantContext>any())).thenReturn(effectiveSubscriptionTransitions); Mockito.when(subscriptionInternalApi.getAllTransitions(Mockito.<SubscriptionBase>any(), Mockito.<InternalTenantContext>any())).thenReturn(effectiveSubscriptionTransitions); catalog = ((MockCatalog) catalogService.getCurrentCatalog()); // TODO The MockCatalog module returns two different things for full vs current catalog Mockito.when(catalogService.getFullCatalog()).thenReturn(catalog); // Set a default alignment catalog.setBillingAlignment(BillingAlignment.ACCOUNT); // Cleanup mock daos ((MockBlockingStateDao) blockingStateDao).clear(); ((MockTagDao) tagDao).clear(); }
@Override public Entitlement createBaseEntitlement(final UUID accountId, final PlanPhaseSpecifier planPhaseSpecifier, final String externalKey, final LocalDate effectiveDate, final CallContext callContext) throws EntitlementApiException { final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(accountId, callContext); try { if (entitlementUtils.getFirstActiveSubscriptionIdForKeyOrNull(externalKey, contextWithValidAccountRecordId) != null) { 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, requestedDate, contextWithValidAccountRecordId); return new DefaultEntitlement(subscription.getId(), eventsStreamBuilder, this, blockingStateDao, subscriptionBaseInternalApi, checker, notificationQueueService, entitlementUtils, dateHelper, clock, internalCallContextFactory, callContext); } catch (SubscriptionBaseApiException e) { throw new EntitlementApiException(e); } }
@Override public List<EntitlementAOStatusDryRun> getDryRunStatusForChange(final UUID bundleId, final String targetProductName, final LocalDate effectiveDate, final TenantContext context) throws EntitlementApiException { final InternalTenantContext internalContext = internalCallContextFactory.createInternalTenantContext(context); try { final SubscriptionBaseBundle bundle = subscriptionBaseInternalApi.getBundleFromId(bundleId, internalContext); final SubscriptionBase baseSubscription = subscriptionBaseInternalApi.getBaseSubscription(bundleId, internalContext); final InternalTenantContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalTenantContext(bundle.getAccountId(), context); final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(effectiveDate, baseSubscription.getStartDate(), contextWithValidAccountRecordId); return subscriptionBaseInternalApi.getDryRunChangePlanStatus(baseSubscription.getId(), targetProductName, requestedDate, contextWithValidAccountRecordId); } catch (SubscriptionBaseApiException e) { throw new EntitlementApiException(e); } }
public EventsStream buildForEntitlement(final UUID entitlementId, final InternalTenantContext internalTenantContext) throws EntitlementApiException { final SubscriptionBaseBundle bundle; final SubscriptionBase subscription; final List<SubscriptionBase> allSubscriptionsForBundle; final SubscriptionBase baseSubscription; try { subscription = subscriptionInternalApi.getSubscriptionFromId(entitlementId, internalTenantContext); bundle = subscriptionInternalApi.getBundleFromId(subscription.getBundleId(), internalTenantContext); allSubscriptionsForBundle = subscriptionInternalApi.getSubscriptionsForBundle(subscription.getBundleId(), internalTenantContext); baseSubscription = Iterables.<SubscriptionBase>tryFind(allSubscriptionsForBundle, new Predicate<SubscriptionBase>() { @Override public boolean apply(final SubscriptionBase input) { return ProductCategory.BASE.equals(input.getLastActiveProduct().getCategory()); } }).orNull(); // null for standalone subscriptions } catch (SubscriptionBaseApiException e) { throw new EntitlementApiException(e); } final Account account; try { account = accountInternalApi.getAccountById(bundle.getAccountId(), internalTenantContext); } catch (AccountApiException e) { throw new EntitlementApiException(e); } // Retrieve the blocking states final List<BlockingState> blockingStatesForAccount = defaultBlockingStateDao.getBlockingAllForAccountRecordId(internalTenantContext); return buildForEntitlement(blockingStatesForAccount, account, bundle, baseSubscription, subscription, allSubscriptionsForBundle, internalTenantContext); }
final DateTime ctd = baseSubscription.getStartDate().plusDays(30); subscriptionInternalApi.setChargedThroughDate(baseSubscription.getId(), ctd, internalCallContext); final SubscriptionBase oldBaseSubscription = subscriptionInternalApi.getSubscriptionFromId(baseSubscription.getId(), internalCallContext); assertNotNull(oldBaseSubscription.getFutureEndDate()); assertTrue(oldBaseSubscription.getFutureEndDate().compareTo(ctd) == 0); final List<SubscriptionBaseBundle> bundlesForAccountAndKey = subscriptionInternalApi.getBundlesForAccountAndKey(newAccountId, bundle.getExternalKey(), internalCallContext); assertEquals(bundlesForAccountAndKey.size(), 1); final List<SubscriptionBase> subscriptions = subscriptionInternalApi.getSubscriptionsForBundle(newBundle.getId(), internalCallContext); assertEquals(subscriptions.size(), 1); assertEquals(subscriptionInternalApi.getAllTransitions(newBaseSubscription, internalCallContext).size(), 2); assertTrue(subscriptionInternalApi.getAllTransitions(newBaseSubscription, internalCallContext).get(1).getEffectiveTransitionTime().compareTo(evergreenPhaseDate) == 0);
@Override public void doTest() throws SubscriptionBaseRepairException, SubscriptionBaseApiException { final BundleBaseTimeline bundleRepair = repairApi.getBundleTimeline(bundle.getId(), callContext); testUtil.sortEventsOnBundle(bundleRepair); final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.EVERGREEN); final NewEvent ne = testUtil.createNewEvent(SubscriptionBaseTransitionType.CHANGE, baseSubscription.getStartDate().plusDays(10), spec); final List<DeletedEvent> des = new LinkedList<SubscriptionBaseTimeline.DeletedEvent>(); des.add(testUtil.createDeletedEvent(bundleRepair.getSubscriptions().get(0).getExistingEvents().get(0).getEventId())); des.add(testUtil.createDeletedEvent(bundleRepair.getSubscriptions().get(0).getExistingEvents().get(1).getEventId())); final SubscriptionBaseTimeline sRepair = testUtil.createSubscriptionRepair(baseSubscription.getId(), des, Collections.singletonList(ne)); final BundleBaseTimeline bRepair = testUtil.createBundleRepair(bundle.getId(), bundleRepair.getViewId(), Collections.singletonList(sRepair)); final DateTime newChargedThroughDate = baseSubscription.getStartDate().plusDays(30).plusMonths(1); // Move clock at least a sec to make sure the last_sys_update from bundle is different-- and therefore generates a different viewId clock.setDeltaFromReality(1000); subscriptionInternalApi.setChargedThroughDate(baseSubscription.getId(), newChargedThroughDate, internalCallContext); subscriptionInternalApi.getSubscriptionFromId(baseSubscription.getId(), internalCallContext); repairApi.repairBundle(bRepair, true, callContext); assertListenerStatus(); } }, ErrorCode.SUB_REPAIR_VIEW_CHANGED);
@Override public void handleReadyNotification(final NotificationEvent notificationKey, final DateTime eventDate, final UUID userToken, final Long accountRecordId, final Long tenantRecordId) { try { if (!(notificationKey instanceof NextBillingDateNotificationKey)) { log.error("Invoice service received an unexpected event type {}", notificationKey.getClass().getName()); return; } final NextBillingDateNotificationKey key = (NextBillingDateNotificationKey) notificationKey; try { final SubscriptionBase subscription = subscriptionApi.getSubscriptionFromId(key.getUuidKey(), callContextFactory.createInternalTenantContext(tenantRecordId, accountRecordId)); if (subscription == null) { log.warn("Next Billing Date Notification Queue handled spurious notification (key: " + key + ")"); } else { processEvent(key.getUuidKey(), eventDate, userToken, accountRecordId, tenantRecordId); } } catch (SubscriptionBaseApiException e) { log.warn("Next Billing Date Notification Queue handled spurious notification (key: " + key + ")", e); } } catch (IllegalArgumentException e) { log.error("The key returned from the NextBillingNotificationQueue is not a valid UUID", e); } } };
@Test(groups = "slow") public void testSingleBasePlan() throws SubscriptionBaseMigrationApiException { final DateTime startDate = clock.getUTCNow().minusMonths(2); final DateTime beforeMigration = clock.getUTCNow(); final AccountMigration toBeMigrated = testUtil.createAccountForMigrationWithRegularBasePlan(startDate); final DateTime afterMigration = clock.getUTCNow(); testListener.pushExpectedEvent(NextEvent.MIGRATE_ENTITLEMENT); migrationApi.migrate(toBeMigrated, callContext); assertListenerStatus(); final List<SubscriptionBaseBundle> bundles = subscriptionInternalApi.getBundlesForAccount(toBeMigrated.getAccountKey(), internalCallContext); assertEquals(bundles.size(), 1); final SubscriptionBaseBundle bundle = bundles.get(0); final List<SubscriptionBase> subscriptions = subscriptionInternalApi.getSubscriptionsForBundle(bundle.getId(), internalCallContext); assertEquals(subscriptions.size(), 1); final SubscriptionBase subscription = subscriptions.get(0); assertTrue(subscription.getStartDate().compareTo(startDate) == 0); assertEquals(subscription.getEndDate(), null); assertEquals(subscription.getCurrentPriceList().getName(), PriceListSet.DEFAULT_PRICELIST_NAME); assertEquals(subscription.getCurrentPhase().getPhaseType(), PhaseType.EVERGREEN); assertEquals(subscription.getState(), EntitlementState.ACTIVE); assertEquals(subscription.getCurrentPlan().getName(), "shotgun-annual"); assertEquals(subscription.getChargedThroughDate(), startDate.plusYears(1)); assertListenerStatus(); }
assertListenerStatus(); final List<SubscriptionBaseBundle> bundles = subscriptionInternalApi.getBundlesForAccount(toBeMigrated.getAccountKey(), internalCallContext); assertEquals(bundles.size(), 1); final SubscriptionBaseBundle bundle = bundles.get(0); final List<SubscriptionBase> subscriptions = subscriptionInternalApi.getSubscriptionsForBundle(bundle.getId(), internalCallContext); assertEquals(subscriptions.size(), 1); final SubscriptionBase subscription = subscriptions.get(0); assertEquals(subscription.getChargedThroughDate(), startDate.plusYears(1)); assertEquals(subscriptionInternalApi.getBillingTransitions(subscription, internalCallContext).size(), 1); assertEquals(subscriptionInternalApi.getBillingTransitions(subscription, internalCallContext).get(0).getTransitionType(), SubscriptionBaseTransitionType.MIGRATE_BILLING); assertTrue(subscriptionInternalApi.getBillingTransitions(subscription, internalCallContext).get(0).getEffectiveTransitionTime().compareTo(clock.getUTCNow()) > 0); assertListenerStatus(); assertListenerStatus(); final SubscriptionBase oldBaseSubscription = subscriptionInternalApi.getBaseSubscription(bundle.getId(), internalCallContext); assertTrue(oldBaseSubscription.getState() == EntitlementState.CANCELLED); assertEquals(subscriptionInternalApi.getBillingTransitions(oldBaseSubscription, internalCallContext).size(), 0);
final Duration ctd = testUtil.getDurationMonth(1); final DateTime newChargedThroughDate = TestSubscriptionHelper.addDuration(now, ctd); subscriptionInternalApi.setChargedThroughDate(baseSubscription.getId(), newChargedThroughDate, internalCallContext); baseSubscription = (DefaultSubscriptionBase) subscriptionInternalApi.getSubscriptionFromId(baseSubscription.getId(), internalCallContext); final String newBasePriceList = PriceListSet.DEFAULT_PRICELIST_NAME; final List<EntitlementAOStatusDryRun> aoStatus = subscriptionInternalApi.getDryRunChangePlanStatus(baseSubscription.getId(), newBaseProduct, now, internalCallContext); assertEquals(aoStatus.size(), 1); aoSubscription = (DefaultSubscriptionBase) subscriptionInternalApi.getSubscriptionFromId(aoSubscription.getId(), internalCallContext); assertEquals(aoSubscription.getState(), EntitlementState.CANCELLED);
@Test(groups = "slow") public void testCreateBundlesWithSameExternalKeys() throws SubscriptionBaseApiException { final DateTime init = clock.getUTCNow(); final DateTime requestedDate = init.minusYears(1); final String productName = "Shotgun"; final BillingPeriod term = BillingPeriod.MONTHLY; final String planSetName = PriceListSet.DEFAULT_PRICELIST_NAME; testListener.pushExpectedEvents(NextEvent.CREATE, NextEvent.PHASE); final DefaultSubscriptionBase subscription = (DefaultSubscriptionBase) subscriptionInternalApi.createSubscription(bundle.getId(), testUtil.getProductSpecifier(productName, planSetName, term, null), requestedDate, internalCallContext); assertListenerStatus(); assertNotNull(subscription); testListener.pushExpectedEvent(NextEvent.CANCEL); subscription.cancelWithDate(clock.getUTCNow(), callContext); assertListenerStatus(); final SubscriptionBaseBundle newBundle = subscriptionInternalApi.createBundleForAccount(bundle.getAccountId(), DefaultSubscriptionTestInitializer.DEFAULT_BUNDLE_KEY, internalCallContext); assertNotNull(newBundle); assertEquals(newBundle.getOriginalCreatedDate().compareTo(bundle.getCreatedDate()), 0); testListener.pushExpectedEvents(NextEvent.CREATE, NextEvent.PHASE); final DefaultSubscriptionBase newSubscription = (DefaultSubscriptionBase) subscriptionInternalApi.createSubscription(newBundle.getId(), testUtil.getProductSpecifier(productName, planSetName, term, null), requestedDate, internalCallContext); subscriptionInternalApi.updateExternalKey(newBundle.getId(), "myNewSuperKey", internalCallContext); final SubscriptionBaseBundle bundleWithNewKey = subscriptionInternalApi.getBundleFromId(newBundle.getId(), internalCallContext); assertEquals(bundleWithNewKey.getExternalKey(), "myNewSuperKey"); assertListenerStatus(); assertNotNull(newSubscription); }
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);
subscriptionInternalApi.setChargedThroughDate(baseSubscription.getId(), ctd, internalCallContext); subscriptionInternalApi.setChargedThroughDate(aoSubscription1.getId(), ctd, internalCallContext); assertListenerStatus(); final List<SubscriptionBaseBundle> bundlesForAccountAndKey = subscriptionInternalApi.getBundlesForAccountAndKey(newAccountId, bundle.getExternalKey(), internalCallContext); assertEquals(bundlesForAccountAndKey.size(), 1); final List<SubscriptionBase> subscriptions = subscriptionInternalApi.getSubscriptionsForBundle(newBundle.getId(), internalCallContext); assertEquals(subscriptions.size(), 1);
DefaultSubscriptionBase subscription = (DefaultSubscriptionBase) subscriptionInternalApi.createSubscription(bundle.getId(), testUtil.getProductSpecifier(productName, planSetName, term, null), clock.getUTCNow(), internalCallContext); assertNotNull(subscription); assertListenerStatus(); subscription = (DefaultSubscriptionBase) subscriptionInternalApi.getSubscriptionFromId(subscription.getId(), internalCallContext); currentPhase = subscription.getCurrentPhase(); assertNotNull(currentPhase);
public EventsStream buildForBaseSubscription(final UUID bundleId, final TenantContext tenantContext) throws EntitlementApiException { final SubscriptionBase baseSubscription; try { final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(tenantContext); baseSubscription = subscriptionInternalApi.getBaseSubscription(bundleId, internalTenantContext); } catch (SubscriptionBaseApiException e) { throw new EntitlementApiException(e); } return buildForEntitlement(baseSubscription.getId(), tenantContext); }
private void tCreateSubscriptionInternal(@Nullable final UUID bundleId, @Nullable final String productName, @Nullable final BillingPeriod term, final String planSet, final ErrorCode expected) { try { subscriptionInternalApi.createSubscription(bundleId, testUtil.getProductSpecifier(productName, planSet, term, null), clock.getUTCNow(), internalCallContext); Assert.fail("Exception expected, error code: " + expected); } catch (SubscriptionBaseApiException e) { assertEquals(e.getCode(), expected.getCode()); } }
@Override public BillingEventSet getBillingEventsForAccountAndUpdateAccountBCD(final UUID accountId, final InternalCallContext context) { final List<SubscriptionBaseBundle> bundles = subscriptionApi.getBundlesForAccount(accountId, context); final DefaultBillingEventSet result = new DefaultBillingEventSet(); try { final Account account = accountApi.getAccountById(accountId, context); // Check to see if billing is off for the account final List<Tag> accountTags = tagApi.getTags(accountId, ObjectType.ACCOUNT, context); final boolean found_AUTO_INVOICING_OFF = is_AUTO_INVOICING_OFF(accountTags); if (found_AUTO_INVOICING_OFF) { result.setAccountAutoInvoiceIsOff(true); return result; // billing is off, we are done } addBillingEventsForBundles(bundles, account, context, result); } catch (AccountApiException e) { log.warn("Failed while getting BillingEvent", e); } // Pretty-print the events, before and after the blocking calculator does its magic final StringBuilder logStringBuilder = new StringBuilder("Computed billing events for accountId ").append(accountId); eventsToString(logStringBuilder, result, "\nBilling Events Raw"); blockCalculator.insertBlockingEvents(result, context); eventsToString(logStringBuilder, result, "\nBilling Events After Blocking"); log.info(logStringBuilder.toString()); return result; }
private void addBillingEventsForBundles(final List<SubscriptionBaseBundle> bundles, final Account account, final InternalCallContext context, final DefaultBillingEventSet result) { for (final SubscriptionBaseBundle bundle : bundles) { final List<SubscriptionBase> subscriptions = subscriptionApi.getSubscriptionsForBundle(bundle.getId(), context); //Check if billing is off for the bundle final List<Tag> bundleTags = tagApi.getTags(bundle.getId(), ObjectType.BUNDLE, context); boolean found_AUTO_INVOICING_OFF = is_AUTO_INVOICING_OFF(bundleTags); if (found_AUTO_INVOICING_OFF) { for (final SubscriptionBase subscription : subscriptions) { // billing is off so list sub ids in set to be excluded result.getSubscriptionIdsWithAutoInvoiceOff().add(subscription.getId()); } } else { // billing is not off addBillingEventsForSubscription(subscriptions, bundle, account, context, result); } } }
@Override public List<Entitlement> getAllEntitlementsForBundle(final UUID bundleId, final TenantContext tenantContext) throws EntitlementApiException { final InternalTenantContext internalContext = internalCallContextFactory.createInternalTenantContext(tenantContext); final UUID accountId; try { accountId = subscriptionBaseInternalApi.getBundleFromId(bundleId, internalContext).getAccountId(); } catch (SubscriptionBaseApiException e) { throw new EntitlementApiException(e); } return ImmutableList.<Entitlement>copyOf(Iterables.<Entitlement>filter(getAllEntitlementsForAccountId(accountId, tenantContext), new Predicate<Entitlement>() { @Override public boolean apply(final Entitlement input) { return bundleId.equals(input.getBundleId()); } })); }
final List<EffectiveSubscriptionInternalEvent> transitions = subscriptionApi.getAllTransitions(subscription, context); if (transitions.size() == 0) { initialPhaseType = null;