use of org.killbill.billing.invoice.api.Invoice in project killbill by killbill.
the class TestDefaultInvoiceGenerator method testEndDateIsCorrect.
@Test(groups = "fast")
public void testEndDateIsCorrect() throws InvoiceApiException, CatalogApiException {
final Plan plan = new MockPlan();
final PlanPhase planPhase = createMockMonthlyPlanPhase(ONE);
final BillingEventSet events = new MockBillingEventSet();
final LocalDate startDate = clock.getUTCToday().minusDays(1);
final LocalDate targetDate = startDate.plusDays(1);
events.add(createBillingEvent(UUID.randomUUID(), UUID.randomUUID(), startDate, plan, planPhase, startDate.getDayOfMonth()));
final InvoiceWithMetadata invoiceWithMetadata = generator.generateInvoice(account, events, null, targetDate, Currency.USD, internalCallContext);
final Invoice invoice = invoiceWithMetadata.getInvoice();
final RecurringInvoiceItem item = (RecurringInvoiceItem) invoice.getInvoiceItems().get(0);
// end date of the invoice item should be equal to exactly one month later (rounded)
assertEquals(item.getEndDate(), startDate.plusMonths(1));
}
use of org.killbill.billing.invoice.api.Invoice in project killbill by killbill.
the class TestDefaultInvoiceGenerator method testWithSingleThirtyDaysEvent.
@Test(groups = "fast")
public void testWithSingleThirtyDaysEvent() throws InvoiceApiException, CatalogApiException {
final BillingEventSet events = new MockBillingEventSet();
final SubscriptionBase sub = createSubscription();
final LocalDate startDate = invoiceUtil.buildDate(2011, 9, 1);
final Plan plan = new MockPlan();
final BigDecimal rate1 = TEN;
final PlanPhase phase = createMockThirtyDaysPlanPhase(rate1);
final BillingEvent event = createBillingEvent(sub.getId(), sub.getBundleId(), startDate, plan, phase, 1);
events.add(event);
final LocalDate targetDate = invoiceUtil.buildDate(2011, 10, 3);
final InvoiceWithMetadata invoiceWithMetadata = generator.generateInvoice(account, events, null, targetDate, Currency.USD, internalCallContext);
final Invoice invoice = invoiceWithMetadata.getInvoice();
assertNotNull(invoice);
assertEquals(invoice.getNumberOfItems(), 2);
assertEquals(invoice.getBalance(), KillBillMoney.of(TWENTY, invoice.getCurrency()));
assertEquals(invoice.getInvoiceItems().get(0).getSubscriptionId(), sub.getId());
assertEquals(invoice.getInvoiceItems().get(0).getInvoiceItemType(), InvoiceItemType.RECURRING);
assertEquals(invoice.getInvoiceItems().get(0).getStartDate(), new LocalDate(2011, 9, 1));
assertEquals(invoice.getInvoiceItems().get(0).getEndDate(), new LocalDate(2011, 10, 1));
assertEquals(invoice.getInvoiceItems().get(1).getInvoiceItemType(), InvoiceItemType.RECURRING);
assertEquals(invoice.getInvoiceItems().get(1).getStartDate(), new LocalDate(2011, 10, 1));
assertEquals(invoice.getInvoiceItems().get(1).getEndDate(), new LocalDate(2011, 10, 31));
}
use of org.killbill.billing.invoice.api.Invoice in project killbill by killbill.
the class TestDefaultInvoiceGenerator method testInvoiceGeneration.
private void testInvoiceGeneration(final UUID accountId, final BillingEventSet events, final List<Invoice> existingInvoices, final LocalDate targetDate, final int expectedNumberOfItems, final BigDecimal expectedAmount) throws InvoiceApiException {
final Currency currency = Currency.USD;
final InvoiceWithMetadata invoiceWithMetadata = generator.generateInvoice(account, events, existingInvoices, targetDate, currency, internalCallContext);
final Invoice invoice = invoiceWithMetadata.getInvoice();
assertNotNull(invoice);
assertEquals(invoice.getNumberOfItems(), expectedNumberOfItems);
existingInvoices.add(invoice);
distributeItems(existingInvoices);
assertEquals(invoice.getBalance(), KillBillMoney.of(expectedAmount, invoice.getCurrency()));
}
use of org.killbill.billing.invoice.api.Invoice in project killbill by killbill.
the class TestDefaultInvoiceGenerator method testMultipleDailyChangesDoNotTriggerBounds.
// Complex but plausible scenario, with multiple same-day changes, to verify bounds are not triggered
@Test(groups = "fast", description = "https://github.com/killbill/killbill/issues/664")
public void testMultipleDailyChangesDoNotTriggerBounds() throws InvoiceApiException, CatalogApiException {
final UUID accountId = UUID.randomUUID();
final UUID bundleId = UUID.randomUUID();
final UUID subscriptionId1 = UUID.randomUUID();
final BillingEventSet events = new MockBillingEventSet();
final List<Invoice> invoices = new ArrayList<Invoice>();
Invoice invoice;
final Plan plan1 = new MockPlan("plan1");
final PlanPhase plan1Phase1 = createMockMonthlyPlanPhase(null, EIGHT, PhaseType.TRIAL);
final PlanPhase plan1Phase2 = createMockMonthlyPlanPhase(TWELVE, PhaseType.DISCOUNT);
final LocalDate plan1StartDate = invoiceUtil.buildDate(2011, 1, 5);
final LocalDate plan1PhaseChangeDate = invoiceUtil.buildDate(2011, 4, 5);
final Plan plan2 = new MockPlan("plan2");
final PlanPhase plan2Phase1 = createMockMonthlyPlanPhase(null, TWENTY, PhaseType.TRIAL);
final PlanPhase plan2Phase2 = createMockMonthlyPlanPhase(THIRTY, PhaseType.DISCOUNT);
final PlanPhase plan2Phase3 = createMockMonthlyPlanPhase(FORTY, PhaseType.EVERGREEN);
final PlanPhase plan2Phase4 = createMockMonthlyPlanPhase();
final LocalDate plan2PhaseChangeToEvergreenDate = invoiceUtil.buildDate(2011, 6, 5);
final LocalDate plan2CancelDate = invoiceUtil.buildDate(2011, 6, 5);
// On 1/5/2011, start TRIAL on plan1
events.add(createBillingEvent(subscriptionId1, bundleId, plan1StartDate, plan1, plan1Phase1, 5));
testInvoiceGeneration(accountId, events, invoices, plan1StartDate, 1, EIGHT);
invoice = invoices.get(0);
assertEquals(invoice.getInvoiceItems().size(), 1);
assertEquals(invoice.getInvoiceItems().get(0).getSubscriptionId(), subscriptionId1);
assertEquals(invoice.getInvoiceItems().get(0).getInvoiceItemType(), InvoiceItemType.FIXED);
assertEquals(invoice.getInvoiceItems().get(0).getStartDate(), new LocalDate(2011, 1, 5));
assertNull(invoice.getInvoiceItems().get(0).getEndDate());
assertEquals(invoice.getInvoiceItems().get(0).getAmount().compareTo(EIGHT), 0);
// On 1/5/2011, change to TRIAL on plan2
events.add(createBillingEvent(subscriptionId1, bundleId, plan1StartDate, plan2, plan2Phase1, 5));
testInvoiceGeneration(accountId, events, invoices, plan1StartDate, 1, TWENTY);
assertEquals(invoices.get(0), invoice);
invoice = invoices.get(1);
assertEquals(invoice.getInvoiceItems().size(), 1);
assertEquals(invoice.getInvoiceItems().get(0).getSubscriptionId(), subscriptionId1);
assertEquals(invoice.getInvoiceItems().get(0).getInvoiceItemType(), InvoiceItemType.FIXED);
assertEquals(invoice.getInvoiceItems().get(0).getStartDate(), new LocalDate(2011, 1, 5));
assertNull(invoice.getInvoiceItems().get(0).getEndDate());
assertEquals(invoice.getInvoiceItems().get(0).getAmount().compareTo(TWENTY), 0);
// On 1/5/2011, change back to TRIAL on plan1
events.add(createBillingEvent(subscriptionId1, bundleId, plan1StartDate, plan1, plan1Phase1, 5));
// We don't repair FIXED items and one already exists for that date - nothing to generate
testNullInvoiceGeneration(events, invoices, plan1StartDate);
// On 4/5/2011, phase change to DISCOUNT on plan1
events.add(createBillingEvent(subscriptionId1, bundleId, plan1PhaseChangeDate, plan1, plan1Phase2, 5));
testInvoiceGeneration(accountId, events, invoices, plan1PhaseChangeDate, 1, TWELVE);
assertEquals(invoices.get(1), invoice);
invoice = invoices.get(2);
assertEquals(invoice.getInvoiceItems().size(), 1);
assertEquals(invoice.getInvoiceItems().get(0).getSubscriptionId(), subscriptionId1);
assertEquals(invoice.getInvoiceItems().get(0).getInvoiceItemType(), InvoiceItemType.RECURRING);
assertEquals(invoice.getInvoiceItems().get(0).getStartDate(), new LocalDate(2011, 4, 5));
assertEquals(invoice.getInvoiceItems().get(0).getEndDate(), new LocalDate(2011, 5, 5));
assertEquals(invoice.getInvoiceItems().get(0).getAmount().compareTo(TWELVE), 0);
// On 4/5/2011, change to DISCOUNT on plan2
events.add(createBillingEvent(subscriptionId1, bundleId, plan1PhaseChangeDate, plan2, plan2Phase2, 5));
testInvoiceGeneration(accountId, events, invoices, plan1PhaseChangeDate, 2, new BigDecimal("18"));
assertEquals(invoices.get(2), invoice);
invoice = invoices.get(3);
assertEquals(invoice.getInvoiceItems().get(0).getSubscriptionId(), subscriptionId1);
assertEquals(invoice.getInvoiceItems().get(0).getInvoiceItemType(), InvoiceItemType.RECURRING);
assertEquals(invoice.getInvoiceItems().get(0).getStartDate(), new LocalDate(2011, 4, 5));
assertEquals(invoice.getInvoiceItems().get(0).getEndDate(), new LocalDate(2011, 5, 5));
assertEquals(invoice.getInvoiceItems().get(0).getAmount().compareTo(THIRTY), 0);
assertEquals(invoice.getInvoiceItems().get(1).getLinkedItemId(), invoices.get(2).getInvoiceItems().get(0).getId());
assertEquals(invoice.getInvoiceItems().get(1).getInvoiceItemType(), InvoiceItemType.REPAIR_ADJ);
assertEquals(invoice.getInvoiceItems().get(1).getStartDate(), new LocalDate(2011, 4, 5));
assertEquals(invoice.getInvoiceItems().get(1).getEndDate(), new LocalDate(2011, 5, 5));
assertEquals(invoice.getInvoiceItems().get(1).getAmount().compareTo(TWELVE.negate()), 0);
// On 4/5/2011, change back to DISCOUNT on plan1
events.add(createBillingEvent(subscriptionId1, bundleId, plan1PhaseChangeDate, plan1, plan1Phase2, 5));
testInvoiceGeneration(accountId, events, invoices, plan1PhaseChangeDate, 2, new BigDecimal("-18"));
assertEquals(invoices.get(3), invoice);
invoice = invoices.get(4);
assertEquals(invoice.getInvoiceItems().get(0).getInvoiceItemType(), InvoiceItemType.RECURRING);
assertEquals(invoice.getInvoiceItems().get(0).getStartDate(), new LocalDate(2011, 4, 5));
assertEquals(invoice.getInvoiceItems().get(0).getEndDate(), new LocalDate(2011, 5, 5));
assertEquals(invoice.getInvoiceItems().get(0).getAmount().compareTo(TWELVE), 0);
assertEquals(invoice.getInvoiceItems().get(1).getLinkedItemId(), invoices.get(3).getInvoiceItems().get(0).getId());
assertEquals(invoice.getInvoiceItems().get(1).getInvoiceItemType(), InvoiceItemType.REPAIR_ADJ);
assertEquals(invoice.getInvoiceItems().get(1).getStartDate(), new LocalDate(2011, 4, 5));
assertEquals(invoice.getInvoiceItems().get(1).getEndDate(), new LocalDate(2011, 5, 5));
assertEquals(invoice.getInvoiceItems().get(1).getAmount().compareTo(THIRTY.negate()), 0);
// On 4/5/2011, change back to DISCOUNT on plan2
events.add(createBillingEvent(subscriptionId1, bundleId, plan1PhaseChangeDate, plan2, plan2Phase2, 5));
testInvoiceGeneration(accountId, events, invoices, plan1PhaseChangeDate, 2, new BigDecimal("18"));
assertEquals(invoices.get(4), invoice);
invoice = invoices.get(5);
assertEquals(invoice.getInvoiceItems().get(0).getSubscriptionId(), subscriptionId1);
assertEquals(invoice.getInvoiceItems().get(0).getInvoiceItemType(), InvoiceItemType.RECURRING);
assertEquals(invoice.getInvoiceItems().get(0).getStartDate(), new LocalDate(2011, 4, 5));
assertEquals(invoice.getInvoiceItems().get(0).getEndDate(), new LocalDate(2011, 5, 5));
assertEquals(invoice.getInvoiceItems().get(0).getAmount().compareTo(THIRTY), 0);
assertEquals(invoice.getInvoiceItems().get(1).getLinkedItemId(), invoices.get(4).getInvoiceItems().get(0).getId());
assertEquals(invoice.getInvoiceItems().get(1).getInvoiceItemType(), InvoiceItemType.REPAIR_ADJ);
assertEquals(invoice.getInvoiceItems().get(1).getStartDate(), new LocalDate(2011, 4, 5));
assertEquals(invoice.getInvoiceItems().get(1).getEndDate(), new LocalDate(2011, 5, 5));
assertEquals(invoice.getInvoiceItems().get(1).getAmount().compareTo(TWELVE.negate()), 0);
// On 6/5/2011, phase change to EVERGREEN on plan2
events.add(createBillingEvent(subscriptionId1, bundleId, plan2PhaseChangeToEvergreenDate, plan2, plan2Phase3, 5));
testInvoiceGeneration(accountId, events, invoices, plan2PhaseChangeToEvergreenDate, 2, new BigDecimal("70"));
assertEquals(invoices.get(5), invoice);
invoice = invoices.get(6);
assertEquals(invoice.getInvoiceItems().get(0).getSubscriptionId(), subscriptionId1);
assertEquals(invoice.getInvoiceItems().get(0).getInvoiceItemType(), InvoiceItemType.RECURRING);
assertEquals(invoice.getInvoiceItems().get(0).getStartDate(), new LocalDate(2011, 5, 5));
assertEquals(invoice.getInvoiceItems().get(0).getEndDate(), new LocalDate(2011, 6, 5));
assertEquals(invoice.getInvoiceItems().get(0).getAmount().compareTo(THIRTY), 0);
assertEquals(invoice.getInvoiceItems().get(1).getSubscriptionId(), subscriptionId1);
assertEquals(invoice.getInvoiceItems().get(1).getInvoiceItemType(), InvoiceItemType.RECURRING);
assertEquals(invoice.getInvoiceItems().get(1).getStartDate(), new LocalDate(2011, 6, 5));
assertEquals(invoice.getInvoiceItems().get(1).getEndDate(), new LocalDate(2011, 7, 5));
assertEquals(invoice.getInvoiceItems().get(1).getAmount().compareTo(FORTY), 0);
// On 6/5/2011, cancel subscription
events.add(createBillingEvent(subscriptionId1, bundleId, plan2CancelDate, plan2, plan2Phase4, 5));
testInvoiceGeneration(accountId, events, invoices, plan2PhaseChangeToEvergreenDate, 1, FORTY.negate());
assertEquals(invoices.get(6), invoice);
invoice = invoices.get(7);
assertEquals(invoice.getInvoiceItems().get(0).getLinkedItemId(), invoices.get(6).getInvoiceItems().get(1).getId());
assertEquals(invoice.getInvoiceItems().get(0).getInvoiceItemType(), InvoiceItemType.REPAIR_ADJ);
assertEquals(invoice.getInvoiceItems().get(0).getStartDate(), new LocalDate(2011, 6, 5));
assertEquals(invoice.getInvoiceItems().get(0).getEndDate(), new LocalDate(2011, 7, 5));
assertEquals(invoice.getInvoiceItems().get(0).getAmount().compareTo(FORTY.negate()), 0);
}
use of org.killbill.billing.invoice.api.Invoice in project killbill by killbill.
the class TestDefaultInvoiceGenerator method testWithFullRepairInvoiceGeneration.
@Test(groups = "fast")
public void testWithFullRepairInvoiceGeneration() throws CatalogApiException, InvoiceApiException {
final LocalDate april25 = new LocalDate(2012, 4, 25);
// create a base plan on April 25th
final SubscriptionBase baseSubscription = createSubscription();
final Plan basePlan = new MockPlan("base Plan");
final MockInternationalPrice price5 = new MockInternationalPrice(new DefaultPrice(FIVE, Currency.USD));
final MockInternationalPrice price10 = new MockInternationalPrice(new DefaultPrice(TEN, Currency.USD));
final MockInternationalPrice price20 = new MockInternationalPrice(new DefaultPrice(TWENTY, Currency.USD));
final PlanPhase basePlanEvergreen = new MockPlanPhase(price10, null, BillingPeriod.MONTHLY, PhaseType.EVERGREEN);
final BillingEventSet events = new MockBillingEventSet();
events.add(createBillingEvent(baseSubscription.getId(), baseSubscription.getBundleId(), april25, basePlan, basePlanEvergreen, 25));
// generate invoice
final InvoiceWithMetadata invoiceWithMetadata1 = generator.generateInvoice(account, events, null, april25, Currency.USD, internalCallContext);
final Invoice invoice1 = invoiceWithMetadata1.getInvoice();
assertNotNull(invoice1);
assertEquals(invoice1.getNumberOfItems(), 1);
assertEquals(invoice1.getBalance().compareTo(TEN), 0);
final List<Invoice> invoices = new ArrayList<Invoice>();
invoices.add(invoice1);
// create 2 add ons on April 28th
final LocalDate april28 = new LocalDate(2012, 4, 28);
final SubscriptionBase addOnSubscription1 = createSubscription();
final Plan addOn1Plan = new MockPlan("add on 1");
final PlanPhase addOn1PlanPhaseEvergreen = new MockPlanPhase(price5, null, BillingPeriod.MONTHLY, PhaseType.EVERGREEN);
events.add(createBillingEvent(addOnSubscription1.getId(), baseSubscription.getBundleId(), april28, addOn1Plan, addOn1PlanPhaseEvergreen, 25));
final SubscriptionBase addOnSubscription2 = createSubscription();
final Plan addOn2Plan = new MockPlan("add on 2");
final PlanPhase addOn2PlanPhaseEvergreen = new MockPlanPhase(price20, null, BillingPeriod.MONTHLY, PhaseType.EVERGREEN);
events.add(createBillingEvent(addOnSubscription2.getId(), baseSubscription.getBundleId(), april28, addOn2Plan, addOn2PlanPhaseEvergreen, 25));
// generate invoice
final InvoiceWithMetadata invoiceWithMetadata2 = generator.generateInvoice(account, events, invoices, april28, Currency.USD, internalCallContext);
final Invoice invoice2 = invoiceWithMetadata2.getInvoice();
invoices.add(invoice2);
assertNotNull(invoice2);
assertEquals(invoice2.getNumberOfItems(), 2);
assertEquals(invoice2.getBalance().compareTo(KillBillMoney.of(TWENTY_FIVE.multiply(new BigDecimal("0.9")), invoice2.getCurrency())), 0);
// perform a repair (change base plan; remove one add-on)
// event stream should include just two plans
final MockBillingEventSet newEvents = new MockBillingEventSet();
final Plan basePlan2 = new MockPlan("base plan 2");
final MockInternationalPrice price13 = new MockInternationalPrice(new DefaultPrice(THIRTEEN, Currency.USD));
final PlanPhase basePlan2Phase = new MockPlanPhase(price13, null, BillingPeriod.MONTHLY, PhaseType.EVERGREEN);
newEvents.add(createBillingEvent(baseSubscription.getId(), baseSubscription.getBundleId(), april25, basePlan2, basePlan2Phase, 25));
newEvents.add(createBillingEvent(addOnSubscription1.getId(), baseSubscription.getBundleId(), april28, addOn1Plan, addOn1PlanPhaseEvergreen, 25));
// generate invoice
final LocalDate may1 = new LocalDate(2012, 5, 1);
final InvoiceWithMetadata invoiceWithMetadata3 = generator.generateInvoice(account, newEvents, invoices, may1, Currency.USD, internalCallContext);
final Invoice invoice3 = invoiceWithMetadata3.getInvoice();
assertNotNull(invoice3);
assertEquals(invoice3.getNumberOfItems(), 3);
// -4.50 -18 - 10 (to correct the previous 2 invoices) + 4.50 + 13
assertEquals(invoice3.getBalance().compareTo(FIFTEEN.negate()), 0);
}
Aggregations