use of org.killbill.billing.catalog.api.PlanPhase in project killbill by killbill.
the class TestUserApiChangePlan method testCorrectPhaseAlignmentOnChange.
@Test(groups = "slow")
public void testCorrectPhaseAlignmentOnChange() throws SubscriptionBaseApiException {
DefaultSubscriptionBase subscription = testUtil.createSubscription(bundle, "Shotgun", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME);
PlanPhase trialPhase = subscription.getCurrentPhase();
assertEquals(trialPhase.getPhaseType(), PhaseType.TRIAL);
// MOVE 2 DAYS AHEAD
Interval it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusDays(2));
clock.addDeltaFromReality(it.toDurationMillis());
// CHANGE IMMEDIATE TO A 3 PHASES PLAN
testListener.pushExpectedEvent(NextEvent.CHANGE);
subscription.changePlan(new PlanSpecifier("Assault-Rifle", BillingPeriod.ANNUAL, "gunclubDiscount"), null, callContext);
assertListenerStatus();
// CHECK EVERYTHING LOOKS CORRECT
final Plan currentPlan = subscription.getCurrentPlan();
assertNotNull(currentPlan);
assertEquals(currentPlan.getProduct().getName(), "Assault-Rifle");
assertEquals(currentPlan.getProduct().getCategory(), ProductCategory.BASE);
assertEquals(currentPlan.getRecurringBillingPeriod(), BillingPeriod.ANNUAL);
trialPhase = subscription.getCurrentPhase();
assertEquals(trialPhase.getPhaseType(), PhaseType.TRIAL);
// MOVE AFTER TRIAL PERIOD -> DISCOUNT
testListener.pushExpectedEvent(NextEvent.PHASE);
it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusDays(30));
clock.addDeltaFromReality(it.toDurationMillis());
assertListenerStatus();
trialPhase = subscription.getCurrentPhase();
assertEquals(trialPhase.getPhaseType(), PhaseType.DISCOUNT);
subscription = (DefaultSubscriptionBase) subscriptionInternalApi.getSubscriptionFromId(subscription.getId(), internalCallContext);
final DateTime expectedNextPhaseDate = subscription.getStartDate().plusDays(30).plusMonths(6);
final SubscriptionBaseTransition nextPhase = subscription.getPendingTransition();
final DateTime nextPhaseEffectiveDate = nextPhase.getEffectiveTransitionTime();
assertEquals(nextPhaseEffectiveDate, expectedNextPhaseDate);
assertListenerStatus();
}
use of org.killbill.billing.catalog.api.PlanPhase in project killbill by killbill.
the class TestUserApiChangePlan method checkChangePlan.
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);
}
use of org.killbill.billing.catalog.api.PlanPhase in project killbill by killbill.
the class TestUserApiError method testChangeSubscriptionFutureCancelled.
@Test(groups = "fast")
public void testChangeSubscriptionFutureCancelled() throws SubscriptionBaseApiException {
SubscriptionBase subscription = testUtil.createSubscription(bundle, "Shotgun", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME);
final PlanPhase trialPhase = subscription.getCurrentPhase();
// MOVE TO NEXT PHASE
final PlanPhase currentPhase = subscription.getCurrentPhase();
testListener.pushExpectedEvent(NextEvent.PHASE);
final Interval it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusDays(31));
clock.addDeltaFromReality(it.toDurationMillis());
assertListenerStatus();
// SET CTD TO CANCEL IN FUTURE
final DateTime expectedPhaseTrialChange = TestSubscriptionHelper.addDuration(subscription.getStartDate(), trialPhase.getDuration());
final Duration ctd = testUtil.getDurationMonth(1);
final DateTime newChargedThroughDate = TestSubscriptionHelper.addDuration(expectedPhaseTrialChange, ctd);
subscriptionInternalApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate, internalCallContext);
subscription = subscriptionInternalApi.getSubscriptionFromId(subscription.getId(), internalCallContext);
subscription.cancelWithPolicy(BillingActionPolicy.END_OF_TERM, null, -1, callContext);
try {
subscription.changePlanWithDate(new PlanSpecifier("Pistol", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME), null, clock.getUTCNow(), callContext);
} catch (final SubscriptionBaseApiException e) {
assertEquals(e.getCode(), ErrorCode.SUB_CHANGE_FUTURE_CANCELLED.getCode());
}
assertListenerStatus();
}
use of org.killbill.billing.catalog.api.PlanPhase in project killbill by killbill.
the class BlockingStateOrdering method toSubscriptionEvent.
private SubscriptionEvent toSubscriptionEvent(@Nullable final SubscriptionEvent prev, @Nullable final SubscriptionEvent next, final UUID entitlementId, final BlockingState in, final SubscriptionEventType eventType, final InternalTenantContext internalTenantContext) {
final Product prevProduct;
final Plan prevPlan;
final PlanPhase prevPlanPhase;
final PriceList prevPriceList;
final BillingPeriod prevBillingPeriod;
// Enforce prev = null for start events
if (prev == null || SubscriptionEventType.START_ENTITLEMENT.equals(eventType) || SubscriptionEventType.START_BILLING.equals(eventType)) {
prevProduct = null;
prevPlan = null;
prevPlanPhase = null;
prevPriceList = null;
prevBillingPeriod = null;
} else {
// We look for the next for the 'prev' meaning we we are headed to, but if this is null -- for example on cancellation we get the prev which gives the correct state.
prevProduct = (prev.getNextProduct() != null ? prev.getNextProduct() : prev.getPrevProduct());
prevPlan = (prev.getNextPlan() != null ? prev.getNextPlan() : prev.getPrevPlan());
prevPlanPhase = (prev.getNextPhase() != null ? prev.getNextPhase() : prev.getPrevPhase());
prevPriceList = (prev.getNextPriceList() != null ? prev.getNextPriceList() : prev.getPrevPriceList());
prevBillingPeriod = (prev.getNextBillingPeriod() != null ? prev.getNextBillingPeriod() : prev.getPrevBillingPeriod());
}
final Product nextProduct;
final Plan nextPlan;
final PlanPhase nextPlanPhase;
final PriceList nextPriceList;
final BillingPeriod nextBillingPeriod;
if (SubscriptionEventType.PAUSE_ENTITLEMENT.equals(eventType) || SubscriptionEventType.PAUSE_BILLING.equals(eventType) || SubscriptionEventType.RESUME_ENTITLEMENT.equals(eventType) || SubscriptionEventType.RESUME_BILLING.equals(eventType) || (SubscriptionEventType.SERVICE_STATE_CHANGE.equals(eventType) && (prev == null || (!SubscriptionEventType.STOP_ENTITLEMENT.equals(prev.getSubscriptionEventType()) && !SubscriptionEventType.STOP_BILLING.equals(prev.getSubscriptionEventType()))))) {
// Enforce next = prev for pause/resume events as well as service changes
nextProduct = prevProduct;
nextPlan = prevPlan;
nextPlanPhase = prevPlanPhase;
nextPriceList = prevPriceList;
nextBillingPeriod = prevBillingPeriod;
} else if (next == null) {
// Enforce next = null for stop events
if (prev == null || SubscriptionEventType.STOP_ENTITLEMENT.equals(eventType) || SubscriptionEventType.STOP_BILLING.equals(eventType)) {
nextProduct = null;
nextPlan = null;
nextPlanPhase = null;
nextPriceList = null;
nextBillingPeriod = null;
} else {
nextProduct = prev.getNextProduct();
nextPlan = prev.getNextPlan();
nextPlanPhase = prev.getNextPhase();
nextPriceList = prev.getNextPriceList();
nextBillingPeriod = prev.getNextBillingPeriod();
}
} else if (prev != null && (SubscriptionEventType.START_ENTITLEMENT.equals(eventType) || SubscriptionEventType.START_BILLING.equals(eventType))) {
// For start events, next is actually the prev (e.g. the trial, not the phase)
nextProduct = prev.getNextProduct();
nextPlan = prev.getNextPlan();
nextPlanPhase = prev.getNextPhase();
nextPriceList = prev.getNextPriceList();
nextBillingPeriod = prev.getNextBillingPeriod();
} else {
nextProduct = next.getNextProduct();
nextPlan = next.getNextPlan();
nextPlanPhase = next.getNextPhase();
nextPriceList = next.getNextPriceList();
nextBillingPeriod = next.getNextBillingPeriod();
}
// See https://github.com/killbill/killbill/issues/135
final String serviceName = getRealServiceNameForEntitlementOrExternalServiceName(in.getService(), eventType);
return new DefaultSubscriptionEvent(in.getId(), entitlementId, in.getEffectiveDate(), eventType, in.isBlockEntitlement(), in.isBlockBilling(), serviceName, in.getStateName(), prevProduct, prevPlan, prevPlanPhase, prevPriceList, prevBillingPeriod, nextProduct, nextPlan, nextPlanPhase, nextPriceList, nextBillingPeriod, in.getCreatedDate(), internalTenantContext);
}
use of org.killbill.billing.catalog.api.PlanPhase in project killbill by killbill.
the class EventsStreamBuilder method createPlanPhaseSpecifier.
private PlanPhaseSpecifier createPlanPhaseSpecifier(final SubscriptionBase subscription) {
final String lastActiveProductName;
final BillingPeriod billingPeriod;
final ProductCategory productCategory;
final String priceListName;
final PhaseType phaseType;
if (subscription.getState() == EntitlementState.PENDING) {
final SubscriptionBaseTransition transition = subscription.getPendingTransition();
final Product pendingProduct = transition.getNextPlan().getProduct();
lastActiveProductName = pendingProduct.getName();
productCategory = pendingProduct.getCategory();
final PlanPhase pendingPlanPhase = transition.getNextPhase();
billingPeriod = pendingPlanPhase.getRecurring() != null ? pendingPlanPhase.getRecurring().getBillingPeriod() : BillingPeriod.NO_BILLING_PERIOD;
priceListName = transition.getNextPriceList().getName();
phaseType = transition.getNextPhase().getPhaseType();
} else {
final Product lastActiveProduct = subscription.getLastActiveProduct();
lastActiveProductName = lastActiveProduct.getName();
productCategory = lastActiveProduct.getCategory();
final PlanPhase lastActivePlanPhase = subscription.getLastActivePhase();
billingPeriod = lastActivePlanPhase.getRecurring() != null ? lastActivePlanPhase.getRecurring().getBillingPeriod() : BillingPeriod.NO_BILLING_PERIOD;
priceListName = subscription.getLastActivePlan().getPriceListName();
phaseType = subscription.getLastActivePhase().getPhaseType();
}
return new PlanPhaseSpecifier(lastActiveProductName, billingPeriod, priceListName, phaseType);
}
Aggregations