public DefaultPlanPhase setPlan(final Plan plan) { this.planName = plan.getName(); this.product = plan.getProduct(); return this; }
private boolean isBaseSpecifier(final Plan inputPlan) { return inputPlan.getProduct().getCategory() == ProductCategory.BASE; }
private boolean isStandaloneSpecifier(final Plan inputPlan) { return inputPlan.getProduct().getCategory() == ProductCategory.STANDALONE; }
private int countCurrentAddOnsWithSamePlanName(final Iterable<Plan> entitlementsPlans, final Plan currentPlan) { int countCurrentAddOns = 0; for (final Plan plan : entitlementsPlans) { if (plan.getName().equalsIgnoreCase(currentPlan.getName()) && plan.getProduct().getCategory() != null && ProductCategory.ADD_ON.equals(plan.getProduct().getCategory())) { countCurrentAddOns++; } } return countCurrentAddOns; } }
public boolean isAddonAvailable(final Product baseProduct, final Plan targetAddOnPlan) { final Product targetAddonProduct = targetAddOnPlan.getProduct(); final Collection<Product> availableAddOns = baseProduct.getAvailable(); for (final Product curAv : availableAddOns) { if (curAv.getName().equals(targetAddonProduct.getName())) { return true; } } return false; }
public boolean isAddonIncluded(final Product baseProduct, final Plan targetAddOnPlan) { final Product targetAddonProduct = targetAddOnPlan.getProduct(); final Collection<Product> includedAddOns = baseProduct.getIncluded(); for (final Product curAv : includedAddOns) { if (curAv.getName().equals(targetAddonProduct.getName())) { return true; } } return false; }
@Override public Product getLastActiveProduct() { if (getState() == EntitlementState.CANCELLED) { final SubscriptionBaseTransition data = getPreviousTransition(); return data.getPreviousPlan().getProduct(); } else if (getState() == EntitlementState.PENDING) { final SubscriptionBaseTransition data = getPendingTransition(); return data.getNextPlan().getProduct(); } else { final Plan currentPlan = getCurrentPlan(); // currentPlan can be null when playing with the clock (subscription created in the future) return currentPlan == null ? null : currentPlan.getProduct(); } }
@Override public Collection<Plan> findPlans(final Product product, final BillingPeriod period) { final List<Plan> result = new ArrayList<Plan>(plans.size()); for (final Plan cur : getPlans()) { if (cur.getProduct().equals(product) && (cur.getRecurringBillingPeriod() != null && cur.getRecurringBillingPeriod().equals(period))) { result.add(cur); } } return result; }
@Override public List<Listing> getAvailableBasePlanListings() { final List<Listing> availBasePlans = new ArrayList<Listing>(); for (final Plan plan : getCurrentPlans()) { if (plan.getProduct().getCategory().equals(ProductCategory.BASE)) { for (final PriceList priceList : getPriceLists().getAllPriceLists()) { for (final Plan priceListPlan : priceList.getPlans()) { if (priceListPlan.getName().equals(plan.getName()) && priceListPlan.getProduct().getName().equals(plan.getProduct().getName())) { availBasePlans.add(new DefaultListing(priceListPlan, priceList)); } } } } } return availBasePlans; }
@Override public ProductCategory getLastActiveCategory() { if (getState() == EntitlementState.CANCELLED) { final SubscriptionBaseTransition data = getPreviousTransition(); return data.getPreviousPlan().getProduct().getCategory(); } else if (getState() == EntitlementState.PENDING) { final SubscriptionBaseTransition data = getPendingTransition(); return data.getNextPlan().getProduct().getCategory(); } else { final Plan currentPlan = getCurrentPlan(); // currentPlan can be null when playing with the clock (subscription created in the future) return currentPlan == null ? null : currentPlan.getProduct().getCategory(); } }
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.getRecurringBillingPeriod(), expBillingPeriod); final PlanPhase currentPhase = subscription.getCurrentPhase(); assertNotNull(currentPhase); assertEquals(currentPhase.getPhaseType(), expPhase); }
@Override public int handleBasePlanEvent(final DefaultSubscriptionBase subscription, final SubscriptionBaseEvent event, final Catalog catalog, final CallContext context) throws CatalogApiException { final InternalCallContext internalCallContext = createCallContextFromBundleId(subscription.getBundleId(), context); if (((ApiEvent) event).getApiEventType() == ApiEventType.CANCEL || ((ApiEvent) event).getApiEventType() == ApiEventType.CHANGE) { final Product baseProduct = (subscription.getState() == EntitlementState.CANCELLED) ? null : subscription.getCurrentPlan().getProduct(); final List<SubscriptionBaseEvent> cancelEvents = new LinkedList<SubscriptionBaseEvent>(); final List<DefaultSubscriptionBase> subscriptionsToBeCancelled = computeAddOnsToCancel(cancelEvents, baseProduct, subscription.getBundleId(), event.getEffectiveDate(), catalog, internalCallContext); dao.cancelSubscriptionsOnBasePlanEvent(subscription, event, subscriptionsToBeCancelled, cancelEvents, catalog, internalCallContext); return subscriptionsToBeCancelled.size(); } else { dao.notifyOnBasePlanEvent(subscription, event, catalog, internalCallContext); return 0; } }
public void checkAddonCreationRights(final SubscriptionBase baseSubscription, final Plan targetAddOnPlan, final DateTime requestedDate, final InternalTenantContext context) throws SubscriptionBaseApiException { if (baseSubscription.getState() == EntitlementState.CANCELLED || (baseSubscription.getState() == EntitlementState.PENDING && context.toLocalDate(baseSubscription.getStartDate()).compareTo(context.toLocalDate(requestedDate)) < 0)) { throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_AO_BP_NON_ACTIVE, targetAddOnPlan.getName()); } final Plan currentOrPendingPlan = baseSubscription.getCurrentOrPendingPlan(); final Product baseProduct = currentOrPendingPlan.getProduct(); if (isAddonIncluded(baseProduct, targetAddOnPlan)) { throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_AO_ALREADY_INCLUDED, targetAddOnPlan.getName(), currentOrPendingPlan.getProduct().getName()); } if (!isAddonAvailable(baseProduct, targetAddOnPlan)) { throw new SubscriptionBaseApiException(ErrorCode.SUB_CREATE_AO_NOT_AVAILABLE, targetAddOnPlan.getName(), currentOrPendingPlan.getProduct().getName()); } }
@Override public SubscriptionBase getBaseSubscription(final UUID bundleId, final Catalog catalog, final InternalTenantContext context) { for (final SubscriptionBase cur : subscriptions) { if (cur.getBundleId().equals(bundleId) && cur.getCurrentPlan().getProduct().getCategory() == ProductCategory.BASE) { return buildSubscription((DefaultSubscriptionBase) cur, context); } } return null; }
@Override public List<SubscriptionBaseEvent> getEventsOnCancelPlan(final DefaultSubscriptionBase subscription, final DateTime effectiveDate, final boolean addCancellationAddOnForEventsIfRequired, final Catalog fullCatalog, final InternalTenantContext internalTenantContext) throws CatalogApiException { final List<SubscriptionBaseEvent> cancelEvents = new ArrayList<SubscriptionBaseEvent>(); final SubscriptionBaseEvent cancelEvent = new ApiEventCancel(new ApiEventBuilder() .setSubscriptionId(subscription.getId()) .setEffectiveDate(effectiveDate) .setFromDisk(true)); cancelEvents.add(cancelEvent); if (subscription.getCategory() == ProductCategory.BASE && addCancellationAddOnForEventsIfRequired) { final Product currentBaseProduct = cancelEvent.getEffectiveDate().compareTo(clock.getUTCNow()) <= 0 ? null : subscription.getCurrentPlan().getProduct(); addCancellationAddOnForEventsIfRequired(cancelEvents, currentBaseProduct, subscription.getBundleId(), effectiveDate, fullCatalog, internalTenantContext); } return cancelEvents; }
@Test(groups = "slow") public void testCreateWithInitialPhase() throws SubscriptionBaseApiException { final DateTime init = clock.getUTCNow(); final String productName = "Shotgun"; final BillingPeriod term = BillingPeriod.MONTHLY; final String planSetName = PriceListSet.DEFAULT_PRICELIST_NAME; final DefaultSubscriptionBase subscription = testUtil.createSubscription(bundle, productName, term, planSetName, PhaseType.EVERGREEN, null); assertNotNull(subscription); assertEquals(subscription.getBundleExternalKey(), bundle.getExternalKey()); testUtil.assertDateWithin(subscription.getStartDate(), init, clock.getUTCNow()); testUtil.assertDateWithin(subscription.getBundleStartDate(), init, clock.getUTCNow()); final Plan currentPlan = subscription.getCurrentPlan(); assertNotNull(currentPlan); assertEquals(currentPlan.getProduct().getName(), productName); assertEquals(currentPlan.getProduct().getCategory(), ProductCategory.BASE); assertEquals(currentPlan.getRecurringBillingPeriod(), BillingPeriod.MONTHLY); final PlanPhase currentPhase = subscription.getCurrentPhase(); assertNotNull(currentPhase); assertEquals(currentPhase.getPhaseType(), PhaseType.EVERGREEN); assertListenerStatus(); }
public DefaultPlanPhase(final Plan parentPlan, final DefaultPlanPhase in, @Nullable final PlanPhasePriceOverride override) { this.type = in.getPhaseType(); this.duration = (DefaultDuration) in.getDuration(); this.fixed = override != null && override.getFixedPrice() != null ? new DefaultFixed((DefaultFixed) in.getFixed(), override) : (DefaultFixed) in.getFixed(); this.recurring = override != null && override.getRecurringPrice() != null ? new DefaultRecurring((DefaultRecurring) in.getRecurring(), override) : (DefaultRecurring) in.getRecurring(); this.usages = new DefaultUsage[in.getUsages().length]; for (int i = 0; i < in.getUsages().length; i++) { final Usage curUsage = in.getUsages()[i]; if (override != null && override.getUsagePriceOverrides() != null) { final UsagePriceOverride usagePriceOverride = Iterables.tryFind(override.getUsagePriceOverrides(), new Predicate<UsagePriceOverride>() { @Override public boolean apply(final UsagePriceOverride input) { return input != null && input.getName().equals(curUsage.getName()); } }).orNull(); usages[i] = (usagePriceOverride != null) ? new DefaultUsage(in.getUsages()[i], usagePriceOverride, override.getCurrency()) : (DefaultUsage) curUsage; } else { usages[i] = (DefaultUsage) curUsage; } } this.planName = parentPlan.getName(); this.product = parentPlan.getProduct(); }
private Plan toDefaultPlan(final StaticCatalog staticCatalog, final Plan input) { if (tmpDefaultPlans != null) { final Plan existingPlan = tmpDefaultPlans.get(input.getName()); if (existingPlan == null) throw new IllegalStateException("Unknown plan " + input.getName()); return existingPlan; } final DefaultPlan result = new DefaultPlan(); result.setName(input.getName()); result.setPrettyName(input.getPrettyName()); result.setRecurringBillingMode(input.getRecurringBillingMode()); result.setEffectiveDateForExistingSubscriptions(input.getEffectiveDateForExistingSubscriptions()); result.setFinalPhase(toDefaultPlanPhase(input.getFinalPhase())); result.setInitialPhases(toDefaultPlanPhases(ImmutableList.copyOf(input.getInitialPhases()))); result.setPlansAllowedInBundle(input.getPlansAllowedInBundle()); result.setProduct(toDefaultProduct(input.getProduct())); result.setPriceListName(input.getPriceListName()); return result; }
protected boolean satisfiesCase(final PlanSpecifier planPhase, final StaticCatalog c) throws CatalogApiException { final Product product; final BillingPeriod billingPeriod; final ProductCategory productCategory; final PriceList priceList; if (planPhase.getPlanName() != null) { final Plan plan = c.findCurrentPlan(planPhase.getPlanName()); product = plan.getProduct(); billingPeriod = plan.getRecurringBillingPeriod(); productCategory = plan.getProduct().getCategory(); priceList = c.findCurrentPricelist(plan.getPriceListName()); } else { product = c.findCurrentProduct(planPhase.getProductName()); billingPeriod = planPhase.getBillingPeriod(); productCategory = product.getCategory(); priceList = getPriceList() != null ? c.findCurrentPricelist(planPhase.getPriceListName()) : null; } return (getProduct() == null || getProduct().equals(product)) && (getProductCategory() == null || getProductCategory().equals(productCategory)) && (getBillingPeriod() == null || getBillingPeriod().equals(billingPeriod)) && (getPriceList() == null || getPriceList().equals(priceList)); }
@Override public DateTime getDryRunChangePlanEffectiveDate(final SubscriptionBase subscription, final EntitlementSpecifier spec, final DateTime requestedDateWithMs, final BillingActionPolicy requestedPolicy, final InternalCallContext context) throws SubscriptionBaseApiException, CatalogApiException { final TenantContext tenantContext = internalCallContextFactory.createTenantContext(context); final CallContext callContext = internalCallContextFactory.createCallContext(context); // verify the number of subscriptions (of the same kind) allowed per bundle final Catalog catalog = catalogInternalApi.getFullCatalog(true, true, context); final DateTime effectiveDate = (requestedDateWithMs != null) ? DefaultClock.truncateMs(requestedDateWithMs) : null; final DateTime effectiveCatalogDate = effectiveDate != null ? effectiveDate : context.getCreatedDate(); final PlanPhasePriceOverridesWithCallContext overridesWithContext = new DefaultPlanPhasePriceOverridesWithCallContext(spec.getOverrides(), callContext); final Plan plan = catalog.createOrFindPlan(spec.getPlanPhaseSpecifier(), overridesWithContext, effectiveCatalogDate, subscription.getStartDate()); if (ProductCategory.ADD_ON.toString().equalsIgnoreCase(plan.getProduct().getCategory().toString())) { if (plan.getPlansAllowedInBundle() != -1 && plan.getPlansAllowedInBundle() > 0 && addonUtils.countExistingAddOnsWithSamePlanName(getSubscriptionsForBundle(subscription.getBundleId(), null, catalog, addonUtils, callContext, context), plan.getName()) >= plan.getPlansAllowedInBundle()) { // the plan can be changed to the new value, because it has reached its limit by bundle throw new SubscriptionBaseApiException(ErrorCode.SUB_CHANGE_AO_MAX_PLAN_ALLOWED_BY_BUNDLE, plan.getName()); } } return apiService.dryRunChangePlan((DefaultSubscriptionBase) subscription, spec, effectiveDate, requestedPolicy, tenantContext); }