Search in sources :

Example 86 with RecurringInvoiceItem

use of org.killbill.billing.invoice.model.RecurringInvoiceItem in project killbill by killbill.

the class TestFixedAndRecurringInvoiceItemGeneratorWithOptimization method testRecurringInAdvance.

@Test(groups = "fast")
public void testRecurringInAdvance() throws InvoiceApiException {
    final DateTime startDate = new DateTime("2020-01-01");
    final BillingEventSet events = new MockBillingEventSet();
    final BigDecimal amount = BigDecimal.TEN;
    final MockInternationalPrice price = new MockInternationalPrice(new DefaultPrice(amount, account.getCurrency()));
    final Plan plan = new MockPlan("my-plan");
    final PlanPhase planPhase = new MockPlanPhase(price, null, BillingPeriod.MONTHLY, PhaseType.EVERGREEN);
    final BillingEvent event = invoiceUtil.createMockBillingEvent(account, subscription, startDate, plan, planPhase, null, amount, account.getCurrency(), planPhase.getRecurring().getBillingPeriod(), 1, BillingMode.IN_ADVANCE, "Billing Event Desc", 1L, SubscriptionBaseTransitionType.CREATE);
    events.add(event);
    // Only look for older invoices 1 month from NOW (we assume targetDate = NOW as time pass normally)
    final Period maxInvoiceLimit = new Period("P1m");
    // Initial invoicing (targetDate1  = startDate)
    // There is no existing invoice
    // => Should generate the item
    // 2020-01-01
    final LocalDate targetDate1 = startDate.toLocalDate();
    final LocalDate cuttoffDate1 = targetDate1.minus(maxInvoiceLimit);
    final AccountInvoices existingInvoices1 = new AccountInvoicesExp(cuttoffDate1, null, ImmutableList.of());
    final InvoiceGeneratorResult result1 = fixedAndRecurringInvoiceItemGenerator.generateItems(account, UUID.randomUUID(), events, existingInvoices1, targetDate1, account.getCurrency(), new HashMap<UUID, SubscriptionFutureNotificationDates>(), null, internalCallContext);
    assertEquals(result1.getItems().size(), 1);
    assertEquals(result1.getItems().get(0).getInvoiceItemType(), InvoiceItemType.RECURRING);
    assertEquals(result1.getItems().get(0).getStartDate().compareTo(new LocalDate("2020-01-01")), 0);
    assertEquals(result1.getItems().get(0).getEndDate().compareTo(new LocalDate("2020-02-01")), 0);
    // One month after invoicing, optimization does not kick-in yet
    // There is an existing invoice
    // => Should not regenerate the item, but should correctly generate the next RECURRING item
    // 2020-02-01
    final LocalDate targetDate2 = startDate.toLocalDate().plusMonths(1);
    final LocalDate cuttoffDate2 = targetDate2.minus(maxInvoiceLimit);
    final Invoice invoice2 = new DefaultInvoice(account.getId(), clock.getUTCToday(), targetDate2, account.getCurrency());
    invoice2.addInvoiceItem(new RecurringInvoiceItem(UUID.randomUUID(), startDate, invoice2.getId(), account.getId(), subscription.getBundleId(), subscription.getId(), null, event.getPlan().getName(), event.getPlanPhase().getName(), null, startDate.toLocalDate(), startDate.plusMonths(1).toLocalDate(), amount, amount, account.getCurrency()));
    final AccountInvoices existingInvoices2 = new AccountInvoicesExp(cuttoffDate2, null, ImmutableList.of(invoice2));
    final InvoiceGeneratorResult result2 = fixedAndRecurringInvoiceItemGenerator.generateItems(account, UUID.randomUUID(), events, existingInvoices2, targetDate2, account.getCurrency(), new HashMap<UUID, SubscriptionFutureNotificationDates>(), null, internalCallContext);
    assertEquals(result2.getItems().size(), 1);
    assertEquals(result2.getItems().get(0).getInvoiceItemType(), InvoiceItemType.RECURRING);
    assertEquals(result2.getItems().get(0).getStartDate().compareTo(new LocalDate("2020-02-01")), 0);
    assertEquals(result2.getItems().get(0).getEndDate().compareTo(new LocalDate("2020-03-01")), 0);
    // Two month after invoicing, optimization **does** kick-in
    // There are 2 existing invoices but the first one is ignored (optimization)
    // => Should not regenerate the item
    // 2020-03-01
    final LocalDate targetDate3 = startDate.toLocalDate().plusMonths(2);
    final LocalDate cuttoffDate3 = targetDate3.minus(maxInvoiceLimit);
    final Invoice invoice3 = new DefaultInvoice(account.getId(), clock.getUTCToday(), targetDate3, account.getCurrency());
    invoice3.addInvoiceItem(new RecurringInvoiceItem(UUID.randomUUID(), startDate.plusMonths(1), invoice3.getId(), account.getId(), subscription.getBundleId(), subscription.getId(), null, event.getPlan().getName(), event.getPlanPhase().getName(), null, startDate.plusMonths(1).toLocalDate(), startDate.plusMonths(2).toLocalDate(), amount, amount, account.getCurrency()));
    final AccountInvoices existingInvoices3 = new AccountInvoicesExp(cuttoffDate3, null, ImmutableList.of(invoice3));
    final InvoiceGeneratorResult result3 = fixedAndRecurringInvoiceItemGenerator.generateItems(account, UUID.randomUUID(), events, existingInvoices3, targetDate3, account.getCurrency(), new HashMap<UUID, SubscriptionFutureNotificationDates>(), null, internalCallContext);
    assertEquals(result3.getItems().size(), 1);
    assertEquals(result3.getItems().get(0).getInvoiceItemType(), InvoiceItemType.RECURRING);
    assertEquals(result3.getItems().get(0).getStartDate().compareTo(new LocalDate("2020-03-01")), 0);
    assertEquals(result3.getItems().get(0).getEndDate().compareTo(new LocalDate("2020-04-01")), 0);
}
Also used : SubscriptionFutureNotificationDates(org.killbill.billing.invoice.generator.InvoiceWithMetadata.SubscriptionFutureNotificationDates) AccountInvoices(org.killbill.billing.invoice.optimizer.InvoiceOptimizerBase.AccountInvoices) Invoice(org.killbill.billing.invoice.api.Invoice) DefaultInvoice(org.killbill.billing.invoice.model.DefaultInvoice) MockBillingEventSet(org.killbill.billing.invoice.MockBillingEventSet) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) Period(org.joda.time.Period) BillingPeriod(org.killbill.billing.catalog.api.BillingPeriod) MockPlan(org.killbill.billing.catalog.MockPlan) Plan(org.killbill.billing.catalog.api.Plan) InvoiceGeneratorResult(org.killbill.billing.invoice.generator.InvoiceItemGenerator.InvoiceGeneratorResult) LocalDate(org.joda.time.LocalDate) DateTime(org.joda.time.DateTime) BigDecimal(java.math.BigDecimal) MockInternationalPrice(org.killbill.billing.catalog.MockInternationalPrice) AccountInvoicesExp(org.killbill.billing.invoice.optimizer.InvoiceOptimizerExp.AccountInvoicesExp) MockPlan(org.killbill.billing.catalog.MockPlan) MockPlanPhase(org.killbill.billing.catalog.MockPlanPhase) MockBillingEventSet(org.killbill.billing.invoice.MockBillingEventSet) BillingEventSet(org.killbill.billing.junction.BillingEventSet) PlanPhase(org.killbill.billing.catalog.api.PlanPhase) MockPlanPhase(org.killbill.billing.catalog.MockPlanPhase) BillingEvent(org.killbill.billing.junction.BillingEvent) DefaultPrice(org.killbill.billing.catalog.DefaultPrice) UUID(java.util.UUID) DefaultInvoice(org.killbill.billing.invoice.model.DefaultInvoice) Test(org.testng.annotations.Test)

Example 87 with RecurringInvoiceItem

use of org.killbill.billing.invoice.model.RecurringInvoiceItem in project killbill by killbill.

the class TestSubscriptionItemTree method testSimpleRepair.

@Test(groups = "fast")
public void testSimpleRepair() {
    final LocalDate startDate = new LocalDate(2014, 1, 1);
    final LocalDate endDate = new LocalDate(2014, 2, 1);
    final LocalDate repairDate = new LocalDate(2014, 1, 23);
    final BigDecimal rate1 = new BigDecimal("12.00");
    final BigDecimal amount1 = rate1;
    final BigDecimal rate2 = new BigDecimal("14.85");
    final BigDecimal amount2 = rate2;
    final InvoiceItem initial = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, productName, planName, phaseName, null, startDate, endDate, amount1, rate1, currency);
    final InvoiceItem newItem = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, "someelse", "someelse", "someelse", null, repairDate, endDate, amount2, rate2, currency);
    final InvoiceItem repair = new RepairAdjInvoiceItem(invoiceId, accountId, repairDate, endDate, amount1.negate(), currency, initial.getId());
    final List<InvoiceItem> expectedResult = Lists.newLinkedList();
    final InvoiceItem expected1 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, productName, planName, phaseName, null, startDate, repairDate, new BigDecimal("8.52"), rate1, currency);
    expectedResult.add(expected1);
    final InvoiceItem expected2 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, "someelse", "someelse", "someelse", null, repairDate, endDate, amount2, rate2, currency);
    expectedResult.add(expected2);
    SubscriptionItemTree tree = new SubscriptionItemTree(subscriptionId, invoiceId);
    tree.addItem(initial);
    tree.addItem(newItem);
    tree.addItem(repair);
    tree.build();
}
Also used : FixedPriceInvoiceItem(org.killbill.billing.invoice.model.FixedPriceInvoiceItem) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) ItemAdjInvoiceItem(org.killbill.billing.invoice.model.ItemAdjInvoiceItem) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) RepairAdjInvoiceItem(org.killbill.billing.invoice.model.RepairAdjInvoiceItem) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal) RepairAdjInvoiceItem(org.killbill.billing.invoice.model.RepairAdjInvoiceItem) Test(org.testng.annotations.Test)

Example 88 with RecurringInvoiceItem

use of org.killbill.billing.invoice.model.RecurringInvoiceItem in project killbill by killbill.

the class TestSubscriptionItemTree method testMaxedOutProRation.

@Test(groups = "fast", description = "https://github.com/killbill/killbill/issues/286")
public void testMaxedOutProRation() throws IOException {
    final LocalDate startDate = new LocalDate(2014, 1, 1);
    final LocalDate cancelDate = new LocalDate(2014, 1, 25);
    final LocalDate endDate = new LocalDate(2014, 2, 1);
    final BigDecimal monthlyRate1 = new BigDecimal("12.00");
    final BigDecimal monthlyAmount1 = monthlyRate1;
    final SubscriptionItemTree tree = new SubscriptionItemTree(subscriptionId, invoiceId);
    final InvoiceItem existing1 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, productName, planName, phaseName, null, startDate, endDate, monthlyAmount1, monthlyRate1, currency);
    tree.addItem(existing1);
    // Fully item adjust the recurring item
    final InvoiceItem existingItemAdj1 = new ItemAdjInvoiceItem(existing1, startDate, monthlyRate1.negate(), currency);
    tree.addItem(existingItemAdj1);
    tree.flatten(true);
    // printTree(tree);
    final InvoiceItem proposed1 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, productName, planName, phaseName, null, startDate, cancelDate, monthlyAmount1, monthlyRate1, currency);
    tree.mergeProposedItem(proposed1);
    tree.buildForMerge();
    // printTree(tree);
    // We except to see a repair for the piece cancelled with a $0 price since item was fully adjusted
    final List<InvoiceItem> expectedResult = ImmutableList.<InvoiceItem>of(new RepairAdjInvoiceItem(invoiceId, accountId, cancelDate, endDate, BigDecimal.ZERO, Currency.USD, existing1.getId()));
    verifyResult(tree.getView(), expectedResult);
}
Also used : FixedPriceInvoiceItem(org.killbill.billing.invoice.model.FixedPriceInvoiceItem) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) ItemAdjInvoiceItem(org.killbill.billing.invoice.model.ItemAdjInvoiceItem) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) RepairAdjInvoiceItem(org.killbill.billing.invoice.model.RepairAdjInvoiceItem) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) ItemAdjInvoiceItem(org.killbill.billing.invoice.model.ItemAdjInvoiceItem) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal) RepairAdjInvoiceItem(org.killbill.billing.invoice.model.RepairAdjInvoiceItem) Test(org.testng.annotations.Test)

Example 89 with RecurringInvoiceItem

use of org.killbill.billing.invoice.model.RecurringInvoiceItem in project killbill by killbill.

the class TestSubscriptionItemTree method testMergeUpgradeWithFinalRepair.

@Test(groups = "fast")
public void testMergeUpgradeWithFinalRepair() {
    final LocalDate startDate = new LocalDate(2014, 1, 1);
    final LocalDate upgradeDate = new LocalDate(2014, 1, 25);
    final LocalDate endDate = new LocalDate(2014, 2, 1);
    final BigDecimal monthlyRate1 = new BigDecimal("12.00");
    final BigDecimal monthlyAmount1 = monthlyRate1;
    final BigDecimal monthlyRate2 = new BigDecimal("20.00");
    final BigDecimal monthlyAmount2 = monthlyRate1;
    final SubscriptionItemTree tree = new SubscriptionItemTree(subscriptionId, invoiceId);
    final InvoiceItem monthly1 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, productName, planName, phaseName, null, startDate, endDate, monthlyAmount1, monthlyRate1, currency);
    tree.addItem(monthly1);
    tree.flatten(true);
    final InvoiceItem proposed1 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, productName, planName, phaseName, null, startDate, upgradeDate, monthlyAmount1, monthlyRate1, currency);
    final InvoiceItem proposed2 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, "foo", "foo", "foo", null, upgradeDate, endDate, monthlyAmount2, monthlyRate2, currency);
    tree.mergeProposedItem(proposed1);
    tree.mergeProposedItem(proposed2);
    tree.buildForMerge();
    final List<InvoiceItem> expectedResult = Lists.newLinkedList();
    final InvoiceItem repair = new RepairAdjInvoiceItem(invoiceId, accountId, upgradeDate, endDate, new BigDecimal("-2.71"), currency, monthly1.getId());
    expectedResult.add(proposed2);
    expectedResult.add(repair);
    verifyResult(tree.getView(), expectedResult);
}
Also used : FixedPriceInvoiceItem(org.killbill.billing.invoice.model.FixedPriceInvoiceItem) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) ItemAdjInvoiceItem(org.killbill.billing.invoice.model.ItemAdjInvoiceItem) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) RepairAdjInvoiceItem(org.killbill.billing.invoice.model.RepairAdjInvoiceItem) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal) RepairAdjInvoiceItem(org.killbill.billing.invoice.model.RepairAdjInvoiceItem) Test(org.testng.annotations.Test)

Example 90 with RecurringInvoiceItem

use of org.killbill.billing.invoice.model.RecurringInvoiceItem in project killbill by killbill.

the class TestSubscriptionItemTree method testMergeWithSecondRepair.

@Test(groups = "fast")
public void testMergeWithSecondRepair() {
    final LocalDate startDate = new LocalDate(2012, 5, 1);
    final LocalDate endDate = new LocalDate(2012, 6, 1);
    final LocalDate change1 = new LocalDate(2012, 5, 7);
    final LocalDate change2 = new LocalDate(2012, 5, 8);
    final BigDecimal rate1 = new BigDecimal("599.95");
    final BigDecimal amount1 = rate1;
    final BigDecimal rate2 = new BigDecimal("9.95");
    final BigDecimal proratedAmount2 = new BigDecimal("8.02");
    final BigDecimal rate3 = new BigDecimal("29.95");
    final BigDecimal proratedAmount3 = new BigDecimal("23.19");
    final SubscriptionItemTree tree = new SubscriptionItemTree(subscriptionId, invoiceId);
    final InvoiceItem initial = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, productName, planName, phaseName, null, startDate, endDate, amount1, rate1, currency);
    final InvoiceItem newItem1 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, "foo", "foo", "foo", null, change1, endDate, proratedAmount2, rate2, currency);
    final InvoiceItem repair1 = new RepairAdjInvoiceItem(invoiceId, accountId, change1, endDate, new BigDecimal("-483.86"), currency, initial.getId());
    tree.addItem(initial);
    tree.addItem(newItem1);
    tree.addItem(repair1);
    tree.flatten(true);
    final InvoiceItem proposed1 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, productName, planName, phaseName, null, startDate, change1, amount1, rate1, currency);
    final InvoiceItem proposed2 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, "foo", "foo", "foo", null, change1, change2, proratedAmount3, rate2, currency);
    final InvoiceItem proposed3 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, "bar", "bar", "bar", null, change2, endDate, proratedAmount3, rate3, currency);
    tree.mergeProposedItem(proposed1);
    tree.mergeProposedItem(proposed2);
    tree.mergeProposedItem(proposed3);
    tree.buildForMerge();
    final List<InvoiceItem> expectedResult = Lists.newLinkedList();
    final InvoiceItem repair2 = new RepairAdjInvoiceItem(invoiceId, accountId, change2, endDate, new BigDecimal("-7.70"), currency, initial.getId());
    expectedResult.add(proposed3);
    expectedResult.add(repair2);
    verifyResult(tree.getView(), expectedResult);
}
Also used : FixedPriceInvoiceItem(org.killbill.billing.invoice.model.FixedPriceInvoiceItem) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) ItemAdjInvoiceItem(org.killbill.billing.invoice.model.ItemAdjInvoiceItem) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) RepairAdjInvoiceItem(org.killbill.billing.invoice.model.RepairAdjInvoiceItem) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal) RepairAdjInvoiceItem(org.killbill.billing.invoice.model.RepairAdjInvoiceItem) Test(org.testng.annotations.Test)

Aggregations

RecurringInvoiceItem (org.killbill.billing.invoice.model.RecurringInvoiceItem)98 Test (org.testng.annotations.Test)90 LocalDate (org.joda.time.LocalDate)89 BigDecimal (java.math.BigDecimal)82 InvoiceItem (org.killbill.billing.invoice.api.InvoiceItem)73 FixedPriceInvoiceItem (org.killbill.billing.invoice.model.FixedPriceInvoiceItem)69 RepairAdjInvoiceItem (org.killbill.billing.invoice.model.RepairAdjInvoiceItem)69 ItemAdjInvoiceItem (org.killbill.billing.invoice.model.ItemAdjInvoiceItem)65 DefaultInvoice (org.killbill.billing.invoice.model.DefaultInvoice)39 Invoice (org.killbill.billing.invoice.api.Invoice)38 UUID (java.util.UUID)34 MockPlan (org.killbill.billing.catalog.MockPlan)16 MockPlanPhase (org.killbill.billing.catalog.MockPlanPhase)16 Plan (org.killbill.billing.catalog.api.Plan)16 MockBillingEventSet (org.killbill.billing.invoice.MockBillingEventSet)16 AccountInvoices (org.killbill.billing.invoice.optimizer.InvoiceOptimizerBase.AccountInvoices)16 BillingEventSet (org.killbill.billing.junction.BillingEventSet)16 HashMap (java.util.HashMap)15 PlanPhase (org.killbill.billing.catalog.api.PlanPhase)15 BillingEvent (org.killbill.billing.junction.BillingEvent)15