use of org.killbill.billing.catalog.api.PlanPhase in project killbill by killbill.
the class TestDefaultInvoiceGenerator method testRepairForPaidInvoice.
@Test(groups = "fast")
public void testRepairForPaidInvoice() throws CatalogApiException, InvoiceApiException {
// create an invoice
final LocalDate april25 = new LocalDate(2012, 4, 25);
// create a base plan on April 25th
final SubscriptionBase originalSubscription = createSubscription();
final Plan originalPlan = new MockPlan("original plan");
final MockInternationalPrice price10 = new MockInternationalPrice(new DefaultPrice(TEN, Currency.USD));
final PlanPhase originalPlanEvergreen = new MockPlanPhase(price10, null, BillingPeriod.MONTHLY, PhaseType.EVERGREEN);
final BillingEventSet events = new MockBillingEventSet();
events.add(createBillingEvent(originalSubscription.getId(), originalSubscription.getBundleId(), april25, originalPlan, originalPlanEvergreen, 25));
final InvoiceWithMetadata invoiceWithMetadata1 = generator.generateInvoice(account, events, null, april25, Currency.USD, internalCallContext);
final Invoice invoice1 = invoiceWithMetadata1.getInvoice();
printDetailInvoice(invoice1);
assertEquals(invoice1.getNumberOfItems(), 1);
final List<Invoice> invoices = new ArrayList<Invoice>();
invoices.add(invoice1);
// pay the invoice
invoice1.addPayment(new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, UUID.randomUUID(), invoice1.getId(), april25.toDateTimeAtCurrentTime(), TEN, Currency.USD, Currency.USD, null, true));
assertEquals(invoice1.getBalance().compareTo(ZERO), 0);
// change the plan (i.e. repair) on start date
events.clear();
final SubscriptionBase newSubscription = createSubscription();
final Plan newPlan = new MockPlan("new plan");
final MockInternationalPrice price5 = new MockInternationalPrice(new DefaultPrice(FIVE, Currency.USD));
final PlanPhase newPlanEvergreen = new MockPlanPhase(price5, null, BillingPeriod.MONTHLY, PhaseType.EVERGREEN);
events.add(createBillingEvent(newSubscription.getId(), originalSubscription.getBundleId(), april25, newPlan, newPlanEvergreen, 25));
// generate a new invoice
final InvoiceWithMetadata invoiceWithMetadata2 = generator.generateInvoice(account, events, invoices, april25, Currency.USD, internalCallContext);
final Invoice invoice2 = invoiceWithMetadata2.getInvoice();
printDetailInvoice(invoice2);
assertEquals(invoice2.getNumberOfItems(), 2);
invoices.add(invoice2);
// move items to the correct invoice (normally, the dao calls will sort that out)
distributeItems(invoices);
// ensure that the original invoice balance is zero
assertEquals(invoice1.getBalance().compareTo(BigDecimal.ZERO), 0);
// ensure that the account balance is correct
assertEquals(invoice2.getBalance().compareTo(new BigDecimal("-5.0")), 0);
}
use of org.killbill.billing.catalog.api.PlanPhase in project killbill by killbill.
the class TestInvoiceWithMetadata method testWith$0RecurringItem.
@Test(groups = "fast")
public void testWith$0RecurringItem() {
final LocalDate invoiceDate = new LocalDate(2016, 11, 15);
final DefaultInvoice originalInvoice = new DefaultInvoice(account.getId(), invoiceDate, account.getCurrency());
final Plan plan = new MockPlan("my-plan");
final MockInternationalPrice price = new MockInternationalPrice(new DefaultPrice(BigDecimal.TEN, account.getCurrency()));
final PlanPhase planPhase = new MockPlanPhase(price, null, BillingPeriod.MONTHLY, PhaseType.EVERGREEN);
final BillingEvent event = invoiceUtil.createMockBillingEvent(account, subscription, invoiceDate.toDateTimeAtStartOfDay(), plan, planPhase, null, BigDecimal.ZERO, account.getCurrency(), planPhase.getRecurring().getBillingPeriod(), 1, BillingMode.IN_ADVANCE, "Billing Event Desc", 1L, SubscriptionBaseTransitionType.CREATE);
final InvoiceItem invoiceItem = new RecurringInvoiceItem(UUID.randomUUID(), invoiceDate.toDateTimeAtStartOfDay(), originalInvoice.getId(), account.getId(), subscription.getBundleId(), subscription.getId(), event.getPlan().getName(), event.getPlanPhase().getName(), invoiceDate, invoiceDate.plusMonths(1), BigDecimal.ZERO, BigDecimal.ZERO, account.getCurrency());
originalInvoice.addInvoiceItem(invoiceItem);
final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDates = new HashMap<UUID, SubscriptionFutureNotificationDates>();
final SubscriptionFutureNotificationDates subscriptionFutureNotificationDates = new SubscriptionFutureNotificationDates(BillingMode.IN_ADVANCE);
subscriptionFutureNotificationDates.updateNextRecurringDateIfRequired(invoiceDate.plusMonths(1));
perSubscriptionFutureNotificationDates.put(subscription.getId(), subscriptionFutureNotificationDates);
final InvoiceWithMetadata invoiceWithMetadata = new InvoiceWithMetadata(originalInvoice, perSubscriptionFutureNotificationDates);
// We generate an invoice with one item, invoicing for $0
final Invoice resultingInvoice = invoiceWithMetadata.getInvoice();
Assert.assertNotNull(resultingInvoice);
Assert.assertEquals(resultingInvoice.getInvoiceItems().size(), 1);
Assert.assertEquals(resultingInvoice.getInvoiceItems().get(0).getAmount().compareTo(BigDecimal.ZERO), 0);
final Map<UUID, InvoiceWithMetadata.SubscriptionFutureNotificationDates> dateMap = invoiceWithMetadata.getPerSubscriptionFutureNotificationDates();
final InvoiceWithMetadata.SubscriptionFutureNotificationDates futureNotificationDates = dateMap.get(subscription.getId());
// We verify that we generated the future notification for a month ahead
Assert.assertNotNull(futureNotificationDates.getNextRecurringDate());
Assert.assertEquals(futureNotificationDates.getNextRecurringDate().compareTo(invoiceDate.plusMonths(1)), 0);
}
use of org.killbill.billing.catalog.api.PlanPhase in project killbill by killbill.
the class TestUserApiChangePlan method testChangePlanBundleAlignEOTWithChargeThroughDate.
private void testChangePlanBundleAlignEOTWithChargeThroughDate(final String fromProd, final BillingPeriod fromTerm, final String fromPlanSet, final String toProd, final BillingPeriod toTerm, final String toPlanSet) throws SubscriptionBillingApiException, SubscriptionBaseApiException {
// CREATE
DefaultSubscriptionBase subscription = testUtil.createSubscription(bundle, fromProd, fromTerm, fromPlanSet);
final PlanPhase trialPhase = subscription.getCurrentPhase();
final DateTime expectedPhaseTrialChange = TestSubscriptionHelper.addDuration(subscription.getStartDate(), trialPhase.getDuration());
assertEquals(trialPhase.getPhaseType(), PhaseType.TRIAL);
// MOVE TO NEXT PHASE
testListener.pushExpectedEvent(NextEvent.PHASE);
Interval it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusDays(31));
clock.addDeltaFromReality(it.toDurationMillis());
assertListenerStatus();
PlanPhase currentPhase = subscription.getCurrentPhase();
assertEquals(currentPhase.getPhaseType(), PhaseType.DISCOUNT);
// SET CTD
final Duration ctd = testUtil.getDurationMonth(1);
final DateTime newChargedThroughDate = TestSubscriptionHelper.addDuration(expectedPhaseTrialChange, ctd);
subscriptionInternalApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate, internalCallContext);
// RE READ SUBSCRIPTION + CHANGE PLAN
subscription = (DefaultSubscriptionBase) subscriptionInternalApi.getSubscriptionFromId(subscription.getId(), internalCallContext);
subscription.changePlan(new PlanSpecifier(toProd, toTerm, toPlanSet), null, callContext);
assertListenerStatus();
// CHECK CHANGE PLAN
currentPhase = subscription.getCurrentPhase();
checkChangePlan(subscription, fromProd, ProductCategory.BASE, fromTerm, PhaseType.DISCOUNT);
// NEXT PHASE
final DateTime nextExpectedPhaseChange = TestSubscriptionHelper.addDuration(expectedPhaseTrialChange, currentPhase.getDuration());
testUtil.checkNextPhaseChange(subscription, 2, nextExpectedPhaseChange);
// ALSO VERIFY PENDING CHANGE EVENT
final List<SubscriptionBaseEvent> events = dao.getPendingEventsForSubscription(subscription.getId(), internalCallContext);
assertTrue(events.get(0) instanceof ApiEvent);
// MOVE TO EOT
testListener.pushExpectedEvent(NextEvent.CHANGE);
it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusMonths(1));
clock.addDeltaFromReality(it.toDurationMillis());
assertListenerStatus();
subscription = (DefaultSubscriptionBase) subscriptionInternalApi.getSubscriptionFromId(subscription.getId(), internalCallContext);
currentPhase = subscription.getCurrentPhase();
checkChangePlan(subscription, toProd, ProductCategory.BASE, toTerm, PhaseType.DISCOUNT);
assertListenerStatus();
}
use of org.killbill.billing.catalog.api.PlanPhase in project killbill by killbill.
the class TestUserApiChangePlan method tChangePlanChangePlanAlignEOTWithChargeThroughDate.
private void tChangePlanChangePlanAlignEOTWithChargeThroughDate(final String fromProd, final BillingPeriod fromTerm, final String fromPlanSet, final String toProd, final BillingPeriod toTerm, final String toPlanSet) throws SubscriptionBillingApiException, SubscriptionBaseApiException {
DateTime currentTime = clock.getUTCNow();
DefaultSubscriptionBase subscription = testUtil.createSubscription(bundle, fromProd, fromTerm, fromPlanSet);
final PlanPhase trialPhase = subscription.getCurrentPhase();
final DateTime expectedPhaseTrialChange = TestSubscriptionHelper.addDuration(subscription.getStartDate(), trialPhase.getDuration());
assertEquals(trialPhase.getPhaseType(), PhaseType.TRIAL);
// MOVE TO NEXT PHASE
testListener.pushExpectedEvent(NextEvent.PHASE);
currentTime = clock.getUTCNow();
Interval it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusDays(31));
clock.addDeltaFromReality(it.toDurationMillis());
currentTime = clock.getUTCNow();
assertListenerStatus();
// SET CTD
final Duration ctd = testUtil.getDurationMonth(1);
final DateTime newChargedThroughDate = TestSubscriptionHelper.addDuration(expectedPhaseTrialChange, ctd);
subscriptionInternalApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate, internalCallContext);
// RE READ SUBSCRIPTION + CHECK CURRENT PHASE
subscription = (DefaultSubscriptionBase) subscriptionInternalApi.getSubscriptionFromId(subscription.getId(), internalCallContext);
PlanPhase currentPhase = subscription.getCurrentPhase();
assertNotNull(currentPhase);
assertEquals(currentPhase.getPhaseType(), PhaseType.EVERGREEN);
// CHANGE PLAN
currentTime = clock.getUTCNow();
subscription.changePlan(new PlanSpecifier(toProd, toTerm, toPlanSet), null, callContext);
checkChangePlan(subscription, fromProd, ProductCategory.BASE, fromTerm, PhaseType.EVERGREEN);
// CHECK CHANGE DID NOT KICK IN YET
assertListenerStatus();
// MOVE TO AFTER CTD
testListener.pushExpectedEvent(NextEvent.CHANGE);
it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusMonths(1));
clock.addDeltaFromReality(it.toDurationMillis());
currentTime = clock.getUTCNow();
assertListenerStatus();
// CHECK CORRECT PRODUCT, PHASE, PLAN SET
final String currentProduct = subscription.getCurrentPlan().getProduct().getName();
assertNotNull(currentProduct);
assertEquals(currentProduct, toProd);
currentPhase = subscription.getCurrentPhase();
assertNotNull(currentPhase);
assertEquals(currentPhase.getPhaseType(), PhaseType.DISCOUNT);
// MOVE TIME ABOUT ONE MONTH BEFORE NEXT EXPECTED PHASE CHANGE
it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusMonths(11));
clock.addDeltaFromReality(it.toDurationMillis());
currentTime = clock.getUTCNow();
assertListenerStatus();
final DateTime nextExpectedPhaseChange = TestSubscriptionHelper.addDuration(newChargedThroughDate, currentPhase.getDuration());
testUtil.checkNextPhaseChange(subscription, 1, nextExpectedPhaseChange);
// MOVE TIME RIGHT AFTER NEXT EXPECTED PHASE CHANGE
testListener.pushExpectedEvent(NextEvent.PHASE);
it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusMonths(1));
clock.addDeltaFromReality(it.toDurationMillis());
currentTime = clock.getUTCNow();
assertListenerStatus();
assertListenerStatus();
}
use of org.killbill.billing.catalog.api.PlanPhase in project killbill by killbill.
the class TestUserApiCreate method testSimpleCreateSubscription.
@Test(groups = "slow")
public void testSimpleCreateSubscription() throws SubscriptionBaseApiException {
final DateTime init = clock.getUTCNow();
final String productName = "Shotgun";
final BillingPeriod term = BillingPeriod.MONTHLY;
final String planSetName = PriceListSet.DEFAULT_PRICELIST_NAME;
testListener.pushExpectedEvent(NextEvent.CREATE);
final DefaultSubscriptionBase subscription = (DefaultSubscriptionBase) subscriptionInternalApi.createSubscription(bundle.getId(), testUtil.getProductSpecifier(productName, planSetName, term, null), null, clock.getUTCNow(), false, internalCallContext);
assertNotNull(subscription);
assertEquals(subscription.getBundleId(), bundle.getId());
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.TRIAL);
assertListenerStatus();
final List<SubscriptionBaseEvent> events = dao.getPendingEventsForSubscription(subscription.getId(), internalCallContext);
assertNotNull(events);
testUtil.printEvents(events);
assertTrue(events.size() == 1);
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);
testListener.pushExpectedEvent(NextEvent.PHASE);
final Interval it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusDays(31));
clock.addDeltaFromReality(it.toDurationMillis());
final DateTime futureNow = clock.getUTCNow();
assertTrue(futureNow.isAfter(nextPhaseChange));
assertListenerStatus();
}
Aggregations