slug = currentPhase.getName(); if (currentPhase.getPhaseType() != null) { phase = currentPhase.getPhaseType().toString(); } else { phase = null; if (currentPhase.getBillingPeriod() != null) { billingPeriod = currentPhase.getBillingPeriod().toString(); } else { billingPeriod = null; if (currentPhase.getRecurringPrice() != null) { tmpPrice = currentPhase.getRecurringPrice().getPrice(USD); } catch (CatalogApiException e) { tmpPrice = new BigDecimal(0); mrr = getMrrFromBillingPeriod(currentPhase.getBillingPeriod(), price); } else { price = BigDecimal.ZERO;
public BusinessInvoiceItemModelDao(@Nullable final String externalKey, final InvoiceItem invoiceItem, @Nullable final Plan plan, @Nullable final PlanPhase planPhase) { this(invoiceItem.getAmount(), planPhase != null ? planPhase.getBillingPeriod().toString() : null, invoiceItem.getCreatedDate(), invoiceItem.getCurrency(), /* Populate end date for fixed items for convenience (null in invoice_items table) */ (invoiceItem.getEndDate() == null && planPhase != null) ? invoiceItem.getStartDate().plus(planPhase.getDuration().toJodaPeriod()) : invoiceItem.getEndDate(), externalKey, invoiceItem.getInvoiceId(), invoiceItem.getId(), invoiceItem.getLinkedItemId(), invoiceItem.getInvoiceItemType().toString(), planPhase != null ? planPhase.getPhaseType().toString() : null, plan != null ? plan.getProduct().getCategory().toString() : null, plan != null ? plan.getProduct().getName() : null, plan != null ? plan.getProduct().getCatalogName() : null, planPhase != null ? planPhase.getName() : null, invoiceItem.getStartDate(), invoiceItem.getUpdatedDate()); }
private BillingEvent createBillingEvent(final UUID subscriptionId, final UUID bundleId, final LocalDate startDate, final Plan plan, final PlanPhase planPhase, final int billCycleDayLocal) throws CatalogApiException { final SubscriptionBase sub = createSubscription(subscriptionId, bundleId); final Currency currency = Currency.USD; return invoiceUtil.createMockBillingEvent(null, sub, startDate.toDateTimeAtStartOfDay(), plan, planPhase, planPhase.getFixedPrice() == null ? null : planPhase.getFixedPrice().getPrice(currency), planPhase.getRecurringPrice() == null ? null : planPhase.getRecurringPrice().getPrice(currency), currency, planPhase.getBillingPeriod(), billCycleDayLocal, BillingModeType.IN_ADVANCE, "Test", 1L, SubscriptionBaseTransitionType.CREATE); }
@Override public DateTime dateOfFirstRecurringNonZeroCharge(final DateTime subscriptionStartDate, final PhaseType initialPhaseType) { DateTime result = subscriptionStartDate.toDateTime(); boolean skipPhase = initialPhaseType == null ? false : true; for (final PlanPhase phase : getAllPhases()) { if (skipPhase) { if (phase.getPhaseType() != initialPhaseType) { continue; } else { skipPhase = false; } } if (phase.getRecurringPrice() == null || phase.getRecurringPrice().isZero()) { result = phase.getDuration().addToDateTime(result); } else { break; } } return result; }
private void checkFirstEvent(final SortedSet<BillingEvent> events, final Plan nextPlan, final int BCD, final UUID id, final DateTime time, final PlanPhase nextPhase, final String desc) throws CatalogApiException { Assert.assertEquals(events.size(), 1); checkEvent(events.first(), nextPlan, BCD, id, time, nextPhase, desc, nextPhase.getFixedPrice(), nextPhase.getRecurringPrice()); }
@Override public String toString() { // Note: we don't use all fields here, as the output would be overwhelming // (these events are printed in the logs in junction and invoice). final StringBuilder sb = new StringBuilder(); sb.append("DefaultBillingEvent"); sb.append("{type=").append(type); sb.append(", effectiveDate=").append(effectiveDate); sb.append(", planPhaseName=").append(planPhase.getName()); sb.append(", subscriptionId=").append(subscription.getId()); sb.append(", totalOrdering=").append(totalOrdering); sb.append(", accountId=").append(account.getId()); sb.append('}'); return sb.toString(); }
private void checkChangePlan(final DefaultSubscriptionBase subscription, final String expProduct, final ProductCategory expCategory, final BillingPeriod expBillingPeriod, final PhaseType expPhase) { final Plan currentPlan = subscription.getCurrentPlan(); assertNotNull(currentPlan); assertEquals(currentPlan.getProduct().getName(), expProduct); assertEquals(currentPlan.getProduct().getCategory(), expCategory); assertEquals(currentPlan.getBillingPeriod(), expBillingPeriod); final PlanPhase currentPhase = subscription.getCurrentPhase(); assertNotNull(currentPhase); assertEquals(currentPhase.getPhaseType(), expPhase); }
@Test(groups = "slow") public void testCancelSubscriptionEOTWithNoChargeThroughDate() throws SubscriptionBaseApiException { final String prod = "Shotgun"; final BillingPeriod term = BillingPeriod.MONTHLY; final String planSet = PriceListSet.DEFAULT_PRICELIST_NAME; // CREATE final DefaultSubscriptionBase subscription = testUtil.createSubscription(bundle, prod, term, planSet); PlanPhase trialPhase = subscription.getCurrentPhase(); assertEquals(trialPhase.getPhaseType(), PhaseType.TRIAL); // NEXT PHASE final DateTime expectedPhaseTrialChange = TestSubscriptionHelper.addDuration(subscription.getStartDate(), trialPhase.getDuration()); testUtil.checkNextPhaseChange(subscription, 1, expectedPhaseTrialChange); // MOVE TO NEXT PHASE testListener.pushExpectedEvent(NextEvent.PHASE); final Interval it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusDays(31)); clock.addDeltaFromReality(it.toDurationMillis()); assertListenerStatus(); trialPhase = subscription.getCurrentPhase(); assertEquals(trialPhase.getPhaseType(), PhaseType.EVERGREEN); testListener.pushExpectedEvent(NextEvent.CANCEL); // CANCEL subscription.cancel(callContext); assertListenerStatus(); final PlanPhase currentPhase = subscription.getCurrentPhase(); assertNull(currentPhase); testUtil.checkNextPhaseChange(subscription, 0, null); assertListenerStatus(); }
for (final PlanPhase phase : plan.getAllPhases()) { final List<PriceJson> prices = new LinkedList<PriceJson>(); if (phase.getRecurringPrice() != null) { for (final Price price : phase.getRecurringPrice().getPrices()) { prices.add(new PriceJson(price)); final PhaseJson phaseJson = new PhaseJson(phase.getPhaseType().toString(), prices); phases.add(phaseJson);
assertEquals(subscription.getEndDate(), null); assertEquals(subscription.getCurrentPriceList().getName(), PriceListSet.DEFAULT_PRICELIST_NAME); assertEquals(subscription.getCurrentPhase().getPhaseType(), PhaseType.TRIAL); assertEquals(subscription.getState(), EntitlementState.ACTIVE); assertEquals(subscription.getCurrentPlan().getName(), "assault-rifle-monthly"); 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(), "assault-rifle-monthly"); assertEquals(subscription.getCurrentPhase().getName(), "assault-rifle-monthly-evergreen");
public PlanDetailJson(final Listing listing) { final Plan plan = listing.getPlan(); if (plan == null) { this.productName = null; this.planName = null; this.billingPeriod = null; this.finalPhasePrice = ImmutableList.<PriceJson>of(); } else { this.productName = plan.getProduct() == null ? null : plan.getProduct().getName(); this.planName = plan.getName(); this.billingPeriod = plan.getBillingPeriod(); if (plan.getFinalPhase() == null || plan.getFinalPhase().getRecurringPrice() == null || plan.getFinalPhase().getRecurringPrice().getPrices() == null) { this.finalPhasePrice = ImmutableList.<PriceJson>of(); } else { this.finalPhasePrice = Lists.transform(ImmutableList.<Price>copyOf(plan.getFinalPhase().getRecurringPrice().getPrices()), new Function<Price, PriceJson>() { @Override public PriceJson apply(final Price price) { try { return new PriceJson(price); } catch (CurrencyValueNull e) { return new PriceJson(price.getCurrency().toString(), BigDecimal.ZERO); } } }); } } this.priceListName = listing.getPriceList() == null ? null : listing.getPriceList().getName(); }
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); }
private void cancelNextPhaseEvent(final UUID subscriptionId, final InternalTenantContext context) { final SubscriptionBase curSubscription = getSubscriptionFromId(subscriptionId, context); if (curSubscription.getCurrentPhase() == null || curSubscription.getCurrentPhase().getDuration().getUnit() == TimeUnit.UNLIMITED) { return; } synchronized (events) { final Iterator<SubscriptionBaseEvent> it = events.descendingIterator(); while (it.hasNext()) { final SubscriptionBaseEvent cur = it.next(); if (cur.getSubscriptionId() != subscriptionId) { continue; } if (cur.getType() == EventType.PHASE && cur.getEffectiveDate().isAfter(clock.getUTCNow())) { cur.deactivate(); break; } } } }
private void checkEvent(final BillingEvent event, final Plan nextPlan, final int BCD, final UUID id, final DateTime time, final PlanPhase nextPhase, final String desc, final InternationalPrice fixedPrice, final InternationalPrice recurringPrice) throws CatalogApiException { if (fixedPrice != null) { Assert.assertEquals(fixedPrice.getPrice(Currency.USD), event.getFixedPrice()); } else { assertNull(event.getFixedPrice()); } if (recurringPrice != null) { Assert.assertEquals(recurringPrice.getPrice(Currency.USD), event.getRecurringPrice()); } else { assertNull(event.getRecurringPrice()); } Assert.assertEquals(BCD, event.getBillCycleDayLocal()); Assert.assertEquals(id, event.getSubscription().getId()); Assert.assertEquals(time.getDayOfMonth(), event.getEffectiveDate().getDayOfMonth()); Assert.assertEquals(nextPhase, event.getPlanPhase()); Assert.assertEquals(nextPlan, event.getPlan()); if (!SubscriptionBaseTransitionType.START_BILLING_DISABLED.equals(event.getTransitionType())) { Assert.assertEquals(nextPhase.getBillingPeriod(), event.getBillingPeriod()); } Assert.assertEquals(BillingModeType.IN_ADVANCE, event.getBillingMode()); Assert.assertEquals(desc, event.getTransitionType().toString()); }
@Override public PlanPhase findPhase(final String name) throws CatalogApiException { for (final PlanPhase pp : getAllPhases()) { if (pp.getName().equals(name)) { return pp; } } throw new CatalogApiException(ErrorCode.CAT_NO_SUCH_PHASE, name); }
initialPhaseType = null; } else { initialPhaseType = initialPhase.getPhaseType();
assertEquals(currentPhase.getPhaseType(), PhaseType.TRIAL); assertListenerStatus(); assertTrue(events.get(0) instanceof PhaseEvent); final DateTime nextPhaseChange = ((PhaseEvent) events.get(0)).getEffectiveDate(); final DateTime nextExpectedPhaseChange = TestSubscriptionHelper.addDuration(subscription.getStartDate(), currentPhase.getDuration()); assertEquals(nextPhaseChange, nextExpectedPhaseChange);
@Test(groups = "fast") public void testBillingEventsWithBlock() throws CatalogApiException, AccountApiException { final Plan nextPlan = catalog.findPlan("PickupTrialEvergreen10USD", clock.getUTCNow()); final PlanPhase nextPhase = nextPlan.getAllPhases()[1]; final DateTime now = createSubscriptionCreationEvent(nextPlan, nextPhase); final Account account = createAccount(32); blockingStateDao.setBlockingState(new DefaultBlockingState(bunId, BlockingStateType.SUBSCRIPTION_BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1)), clock, internalCallContext); blockingStateDao.setBlockingState(new DefaultBlockingState(bunId, BlockingStateType.SUBSCRIPTION_BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(2)), clock, internalCallContext); final SortedSet<BillingEvent> events = billingInternalApi.getBillingEventsForAccountAndUpdateAccountBCD(account.getId(), internalCallContext); Assert.assertEquals(events.size(), 3); final Iterator<BillingEvent> it = events.iterator(); checkEvent(it.next(), nextPlan, account.getBillCycleDayLocal(), subId, now, nextPhase, SubscriptionBaseTransitionType.CREATE.toString(), nextPhase.getFixedPrice(), nextPhase.getRecurringPrice()); checkEvent(it.next(), nextPlan, account.getBillCycleDayLocal(), subId, now.plusDays(1), nextPhase, SubscriptionBaseTransitionType.START_BILLING_DISABLED.toString(), null, null); checkEvent(it.next(), nextPlan, account.getBillCycleDayLocal(), subId, now.plusDays(2), nextPhase, SubscriptionBaseTransitionType.END_BILLING_DISABLED.toString(), nextPhase.getFixedPrice(), nextPhase.getRecurringPrice()); }
@Test(groups = "fast") public void testFromListing() throws Exception { final Product product = Mockito.mock(Product.class); Mockito.when(product.getName()).thenReturn(UUID.randomUUID().toString()); final InternationalPrice price = Mockito.mock(InternationalPrice.class); final PlanPhase planPhase = Mockito.mock(PlanPhase.class); Mockito.when(planPhase.getRecurringPrice()).thenReturn(price); final Plan plan = Mockito.mock(Plan.class); Mockito.when(plan.getProduct()).thenReturn(product); Mockito.when(plan.getName()).thenReturn(UUID.randomUUID().toString()); Mockito.when(plan.getBillingPeriod()).thenReturn(BillingPeriod.QUARTERLY); Mockito.when(plan.getFinalPhase()).thenReturn(planPhase); final PriceList priceList = Mockito.mock(PriceList.class); Mockito.when(priceList.getName()).thenReturn(UUID.randomUUID().toString()); final Listing listing = Mockito.mock(Listing.class); Mockito.when(listing.getPlan()).thenReturn(plan); Mockito.when(listing.getPriceList()).thenReturn(priceList); final PlanDetailJson planDetailJason = new PlanDetailJson(listing); Assert.assertEquals(planDetailJason.getProductName(), plan.getProduct().getName()); Assert.assertEquals(planDetailJason.getPlanName(), plan.getName()); Assert.assertEquals(planDetailJason.getBillingPeriod(), plan.getBillingPeriod()); Assert.assertEquals(planDetailJason.getPriceListName(), priceList.getName()); Assert.assertEquals(planDetailJason.getFinalPhasePrice().size(), 0); } }
private void tChangePlanBundleAlignEOTWithNoChargeThroughDate(final String fromProd, final BillingPeriod fromTerm, final String fromPlanSet, final String toProd, final BillingPeriod toTerm, final String toPlanSet) { try { // CREATE final DefaultSubscriptionBase subscription = testUtil.createSubscription(bundle, fromProd, fromTerm, fromPlanSet); // MOVE TO NEXT PHASE PlanPhase currentPhase = subscription.getCurrentPhase(); testListener.pushExpectedEvent(NextEvent.PHASE); final Interval it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusDays(31)); clock.addDeltaFromReality(it.toDurationMillis()); final DateTime futureNow = clock.getUTCNow(); final DateTime nextExpectedPhaseChange = TestSubscriptionHelper.addDuration(subscription.getStartDate(), currentPhase.getDuration()); assertTrue(futureNow.isAfter(nextExpectedPhaseChange)); assertListenerStatus(); // CHANGE PLAN testListener.pushExpectedEvent(NextEvent.CHANGE); subscription.changePlan(toProd, toTerm, toPlanSet, callContext); assertListenerStatus(); // CHECK CHANGE PLAN currentPhase = subscription.getCurrentPhase(); checkChangePlan(subscription, toProd, ProductCategory.BASE, toTerm, PhaseType.EVERGREEN); assertListenerStatus(); } catch (SubscriptionBaseApiException e) { Assert.fail(e.getMessage()); } }