@Test(groups = "fast") public void testCalculateBCDForAOWithBPCancelledBundleAligned() throws Exception { final DateTimeZone accountTimeZone = DateTimeZone.UTC; final DateTime bpStartDateUTC = new DateTime(2012, 7, 16, 21, 0, 0, DateTimeZone.UTC); final int expectedBCDUTC = 16; // Create a Bundle associated with a subscription final SubscriptionBaseBundle bundle = Mockito.mock(SubscriptionBaseBundle.class); final SubscriptionBase subscription = Mockito.mock(SubscriptionBase.class); Mockito.when(subscription.getStartDate()).thenReturn(bpStartDateUTC); // subscription.getCurrentPlan() will return null as expected (cancelled BP) Mockito.when(subscriptionInternalApi.getBaseSubscription(Mockito.<UUID>any(), Mockito.<InternalTenantContext>any())).thenReturn(subscription); // Create a the base plan associated with that subscription final Plan plan = Mockito.mock(Plan.class); Mockito.when(plan.dateOfFirstRecurringNonZeroCharge(bpStartDateUTC, null)).thenReturn(bpStartDateUTC); final Catalog catalog = Mockito.mock(Catalog.class); Mockito.when(catalog.findPlan(Mockito.anyString(), Mockito.<DateTime>any(), Mockito.<DateTime>any())).thenReturn(plan); Mockito.when(subscription.getLastActivePlan()).thenReturn(plan); final Account account = Mockito.mock(Account.class); Mockito.when(account.getTimeZone()).thenReturn(accountTimeZone); final Integer billCycleDayLocal = billCycleDayCalculator.calculateBcdForAlignment(BillingAlignment.BUNDLE, bundle, subscription, account, catalog, null, internalCallContext); Assert.assertEquals(billCycleDayLocal, (Integer) expectedBCDUTC); }
private void verifyBCDCalculation(final DateTimeZone accountTimeZone, final DateTime startDateUTC, final int bcdLocal) throws AccountApiException, CatalogApiException { final BillCycleDayCalculator billCycleDayCalculator = new BillCycleDayCalculator(Mockito.mock(CatalogService.class), Mockito.mock(SubscriptionBaseInternalApi.class)); final SubscriptionBase subscription = Mockito.mock(SubscriptionBase.class); Mockito.when(subscription.getStartDate()).thenReturn(startDateUTC); final Plan plan = Mockito.mock(Plan.class); Mockito.when(plan.dateOfFirstRecurringNonZeroCharge(startDateUTC, null)).thenReturn(startDateUTC); final Account account = Mockito.mock(Account.class); Mockito.when(account.getTimeZone()).thenReturn(accountTimeZone); final Integer bcd = billCycleDayCalculator.calculateBcdFromSubscription(subscription, plan, account, Mockito.mock(Catalog.class), internalCallContext); Assert.assertEquals(bcd, (Integer) bcdLocal); } }
@VisibleForTesting int calculateBcdForAlignment(final BillingAlignment alignment, final SubscriptionBaseBundle bundle, final SubscriptionBase subscription, final Account account, final Catalog catalog, final Plan plan, final InternalCallContext context) throws AccountApiException, SubscriptionBaseApiException, CatalogApiException { int result = 0; switch (alignment) { case ACCOUNT: result = account.getBillCycleDayLocal(); if (result == 0) { result = calculateBcdFromSubscription(subscription, plan, account, catalog, context); } break; case BUNDLE: final SubscriptionBase baseSub = subscriptionApi.getBaseSubscription(bundle.getId(), context); Plan basePlan = baseSub.getCurrentPlan(); if (basePlan == null) { // The BP has been cancelled basePlan = baseSub.getLastActivePlan(); } result = calculateBcdFromSubscription(baseSub, basePlan, account, catalog, context); break; case SUBSCRIPTION: result = calculateBcdFromSubscription(subscription, plan, account, catalog, context); break; } if (result == 0) { throw new CatalogApiException(ErrorCode.CAT_INVALID_BILLING_ALIGNMENT, alignment.toString()); } return result; }
private void addBillingEventsForSubscription(final List<SubscriptionBase> subscriptions, final SubscriptionBaseBundle bundle, final Account account, final InternalCallContext context, final DefaultBillingEventSet result) { boolean updatedAccountBCD = false; for (final SubscriptionBase subscription : subscriptions) { for (final EffectiveSubscriptionInternalEvent transition : subscriptionApi.getBillingTransitions(subscription, context)) { try { final int bcdLocal = bcdCalculator.calculateBcd(bundle, subscription, transition, account, context); if (account.getBillCycleDayLocal() == 0 && !updatedAccountBCD) { final MutableAccountData modifiedData = account.toMutableAccountData(); modifiedData.setBillCycleDayLocal(bcdLocal); accountApi.updateAccount(account.getExternalKey(), modifiedData, context); updatedAccountBCD = true; } final BillingEvent event = new DefaultBillingEvent(account, transition, subscription, bcdLocal, account.getCurrency(), catalogService.getFullCatalog()); result.add(event); } catch (CatalogApiException e) { log.error("Failing to identify catalog components while creating BillingEvent from transition: " + transition.getId().toString(), e); } catch (Exception e) { log.warn("Failed while getting BillingEvent", e); } } } }
protected int calculateBcd(final SubscriptionBaseBundle bundle, final SubscriptionBase subscription, final EffectiveSubscriptionInternalEvent transition, final Account account, final InternalCallContext context) throws CatalogApiException, AccountApiException, SubscriptionBaseApiException { final Catalog catalog = catalogService.getFullCatalog(); final Plan prevPlan = (transition.getPreviousPlan() != null) ? catalog.findPlan(transition.getPreviousPlan(), transition.getEffectiveTransitionTime(), transition.getSubscriptionStartDate()) : null; final Plan nextPlan = (transition.getNextPlan() != null) ? catalog.findPlan(transition.getNextPlan(), transition.getEffectiveTransitionTime(), transition.getSubscriptionStartDate()) : null; final Plan plan = (transition.getTransitionType() != SubscriptionBaseTransitionType.CANCEL) ? nextPlan : prevPlan; final Product product = plan.getProduct(); final PlanPhase prevPhase = (transition.getPreviousPhase() != null) ? catalog.findPhase(transition.getPreviousPhase(), transition.getEffectiveTransitionTime(), transition.getSubscriptionStartDate()) : null; final PlanPhase nextPhase = (transition.getNextPhase() != null) ? catalog.findPhase(transition.getNextPhase(), transition.getEffectiveTransitionTime(), transition.getSubscriptionStartDate()) : null; final PlanPhase phase = (transition.getTransitionType() != SubscriptionBaseTransitionType.CANCEL) ? nextPhase : prevPhase; final BillingAlignment alignment = catalog.billingAlignment( new PlanPhaseSpecifier(product.getName(), product.getCategory(), phase.getBillingPeriod(), transition.getNextPriceList(), phase.getPhaseType()), transition.getRequestedTransitionTime()); return calculateBcdForAlignment(alignment, bundle, subscription, account, catalog, plan, context); }