use of org.killbill.billing.invoice.model.RecurringInvoiceItem in project killbill by killbill.
the class TestFixedAndRecurringInvoiceItemGeneratorWithOptimization method testRecurringInArrear.
@Test(groups = "fast")
public void testRecurringInArrear() 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 MockPlan plan = new MockPlan("my-plan");
plan.setRecurringBillingMode(BillingMode.IN_ARREAR);
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_ARREAR, "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 nothing to 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(), 0);
// Initial invoicing (targetDate2 = startDate + 1 month)
// There is no existing invoice
// => Should generate the item
// 2020-02-01
final LocalDate targetDate2 = startDate.plusMonths(1).toLocalDate();
final LocalDate cuttoffDate2 = targetDate2.minus(maxInvoiceLimit);
final AccountInvoices existingInvoices2 = new AccountInvoicesExp(cuttoffDate2, null, ImmutableList.of());
final InvoiceGeneratorResult result2 = fixedAndRecurringInvoiceItemGenerator.generateItems(account, UUID.randomUUID(), events, existingInvoices2, targetDate2, account.getCurrency(), new HashMap<UUID, SubscriptionFutureNotificationDates>(), null, internalCallContext);
assertEquals(result2.getItems().get(0).getInvoiceItemType(), InvoiceItemType.RECURRING);
assertEquals(result2.getItems().get(0).getStartDate().compareTo(new LocalDate("2020-01-01")), 0);
assertEquals(result2.getItems().get(0).getEndDate().compareTo(new LocalDate("2020-02-01")), 0);
// 2020-03-01
final LocalDate targetDate3 = startDate.plusMonths(2).toLocalDate();
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.toLocalDate(), startDate.plusMonths(1).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().get(0).getInvoiceItemType(), InvoiceItemType.RECURRING);
assertEquals(result3.getItems().get(0).getStartDate().compareTo(new LocalDate("2020-02-01")), 0);
assertEquals(result3.getItems().get(0).getEndDate().compareTo(new LocalDate("2020-03-01")), 0);
}
use of org.killbill.billing.invoice.model.RecurringInvoiceItem in project killbill by killbill.
the class TestInvoiceDaoHelper method testPopulateChildrenWithPayments.
@Test(groups = "slow")
public void testPopulateChildrenWithPayments() throws Exception {
final UUID accountId = account.getId();
final Invoice inputInvoice = new DefaultInvoice(accountId, clock.getUTCToday(), clock.getUTCToday(), Currency.USD);
final InvoiceItem invoiceItem = new RecurringInvoiceItem(inputInvoice.getId(), accountId, UUID.randomUUID(), UUID.randomUUID(), "test", "test-plan", "test-phase", null, today, today, BigDecimal.TEN, BigDecimal.TEN, Currency.USD);
inputInvoice.addInvoiceItem(invoiceItem);
invoiceUtil.createInvoice(inputInvoice, internalAccountContext);
final InvoicePayment payment = new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, UUID.randomUUID(), inputInvoice.getId(), new DateTime(), BigDecimal.TEN, Currency.USD, Currency.USD, null, true);
invoiceUtil.createPayment(payment, internalAccountContext);
final List<Tag> tags = ImmutableList.of();
final InvoiceModelDao invoice1 = getRawInvoice(inputInvoice.getId(), internalAccountContext);
populateChildrenByInvoiceId(invoice1, tags);
final InvoiceModelDao invoice2 = getRawInvoice(inputInvoice.getId(), internalAccountContext);
populateChildrenByAccountRecordId(invoice2, tags);
Assert.assertEquals(new DefaultInvoice(invoice1).getBalance().compareTo(BigDecimal.ZERO), 0);
Assert.assertEquals(new DefaultInvoice(invoice1).getPaidAmount().compareTo(BigDecimal.TEN), 0);
Assert.assertEquals(new DefaultInvoice(invoice2).getBalance().compareTo(BigDecimal.ZERO), 0);
Assert.assertEquals(new DefaultInvoice(invoice2).getPaidAmount().compareTo(BigDecimal.TEN), 0);
Assert.assertEquals(invoice1, invoice2);
}
use of org.killbill.billing.invoice.model.RecurringInvoiceItem in project killbill by killbill.
the class TestInvoiceDaoHelper method testPopulateChildrenSimple.
@Test(groups = "slow")
public void testPopulateChildrenSimple() throws Exception {
final UUID accountId = account.getId();
final Invoice inputInvoice = new DefaultInvoice(accountId, clock.getUTCToday(), clock.getUTCToday(), Currency.USD);
final InvoiceItem invoiceItem = new RecurringInvoiceItem(inputInvoice.getId(), accountId, UUID.randomUUID(), UUID.randomUUID(), "test", "test-plan", "test-phase", null, today, today, BigDecimal.TEN, BigDecimal.TEN, Currency.USD);
inputInvoice.addInvoiceItem(invoiceItem);
invoiceUtil.createInvoice(inputInvoice, internalAccountContext);
final List<Tag> tags = ImmutableList.of();
final InvoiceModelDao invoice1 = getRawInvoice(inputInvoice.getId(), internalAccountContext);
populateChildrenByInvoiceId(invoice1, tags);
final InvoiceModelDao invoice2 = getRawInvoice(inputInvoice.getId(), internalAccountContext);
populateChildrenByAccountRecordId(invoice2, tags);
Assert.assertEquals(invoice1, invoice2);
}
use of org.killbill.billing.invoice.model.RecurringInvoiceItem in project killbill by killbill.
the class TestFixedAndRecurringInvoiceItemGenerator method testSafetyBoundsTooManyInvoiceItemsForGivenSubscriptionAndInvoiceDate.
//
//
// GENERATE_ITEMS TESTS
//
//
@Test(groups = "fast")
public void testSafetyBoundsTooManyInvoiceItemsForGivenSubscriptionAndInvoiceDate() throws InvoiceApiException {
final int threshold = 15;
final LocalDate startDate = new LocalDate("2016-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.toDateTimeAtStartOfDay(), plan, planPhase, null, amount, account.getCurrency(), planPhase.getRecurring().getBillingPeriod(), 1, BillingMode.IN_ADVANCE, "Billing Event Desc", 1L, SubscriptionBaseTransitionType.CREATE);
events.add(event);
// Simulate a big catch-up
final List<Invoice> existingInvoices = new LinkedList<Invoice>();
for (int i = 0; i < threshold; i++) {
final Invoice invoice = new DefaultInvoice(account.getId(), clock.getUTCToday(), startDate.plusMonths(i), account.getCurrency());
invoice.addInvoiceItem(new RecurringInvoiceItem(UUID.randomUUID(), // Different days - should not trigger the safety bounds
startDate.plusMonths(i).toDateTimeAtStartOfDay(), invoice.getId(), account.getId(), subscription.getBundleId(), subscription.getId(), null, event.getPlan().getName(), event.getPlanPhase().getName(), null, startDate.plusMonths(i), startDate.plusMonths(1 + i), amount, amount, account.getCurrency()));
existingInvoices.add(invoice);
}
assertEquals(fixedAndRecurringInvoiceItemGenerator.generateItems(account, UUID.randomUUID(), events, new AccountInvoices(null, null, existingInvoices), startDate.plusMonths(threshold), account.getCurrency(), new HashMap<UUID, SubscriptionFutureNotificationDates>(), null, internalCallContext).getItems().size(), 1);
// Simulate a big catch-up on that day
for (int i = threshold; i < 2 * threshold; i++) {
final Invoice invoice = new DefaultInvoice(account.getId(), clock.getUTCToday(), startDate.plusMonths(i), account.getCurrency());
invoice.addInvoiceItem(new RecurringInvoiceItem(UUID.randomUUID(), // Same day
clock.getUTCNow(), invoice.getId(), account.getId(), subscription.getBundleId(), subscription.getId(), null, event.getPlan().getName(), event.getPlanPhase().getName(), null, startDate.plusMonths(i), startDate.plusMonths(1 + i), amount, amount, account.getCurrency()));
existingInvoices.add(invoice);
}
try {
final List<InvoiceItem> generatedItems = fixedAndRecurringInvoiceItemGenerator.generateItems(account, UUID.randomUUID(), events, new AccountInvoices(null, null, existingInvoices), startDate.plusMonths(2 * threshold), account.getCurrency(), new HashMap<UUID, SubscriptionFutureNotificationDates>(), null, internalCallContext).getItems();
fail();
} catch (final InvoiceApiException e) {
assertEquals(e.getCode(), ErrorCode.UNEXPECTED_ERROR.getCode());
}
}
use of org.killbill.billing.invoice.model.RecurringInvoiceItem in project killbill by killbill.
the class TestFixedAndRecurringInvoiceItemGenerator method testItemPartiallyRepairedAndInvalidAdjustment.
@Test(groups = "fast", description = "https://github.com/killbill/killbill/issues/664")
public void testItemPartiallyRepairedAndInvalidAdjustment() throws InvoiceApiException {
final LocalDate startDate = new LocalDate("2016-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 event1 = invoiceUtil.createMockBillingEvent(account, subscription, startDate.toDateTimeAtStartOfDay(), plan, planPhase, null, amount, account.getCurrency(), BillingPeriod.MONTHLY, 1, BillingMode.IN_ADVANCE, "Billing Event Desc", 1L, SubscriptionBaseTransitionType.CREATE);
events.add(event1);
final BillingEvent event2 = invoiceUtil.createMockBillingEvent(account, subscription, startDate.plusDays(1).toDateTimeAtStartOfDay(), plan, planPhase, null, null, Currency.USD, BillingPeriod.NO_BILLING_PERIOD, 1, BillingMode.IN_ADVANCE, "Billing Event Desc", 2L, SubscriptionBaseTransitionType.CANCEL);
events.add(event2);
// Subscription incorrectly invoiced
final List<Invoice> existingInvoices = new LinkedList<Invoice>();
final Invoice invoice = new DefaultInvoice(account.getId(), clock.getUTCToday(), startDate, account.getCurrency());
invoice.addInvoiceItem(new RecurringInvoiceItem(UUID.randomUUID(), startDate.toDateTimeAtStartOfDay(), invoice.getId(), account.getId(), subscription.getBundleId(), subscription.getId(), null, plan.getName(), planPhase.getName(), null, startDate, startDate.plusMonths(1), amount, amount, account.getCurrency()));
// Repaired by the system
invoice.addInvoiceItem(new RepairAdjInvoiceItem(UUID.randomUUID(), startDate.toDateTimeAtStartOfDay(), invoice.getId(), account.getId(), startDate.plusDays(1), startDate.plusMonths(1), new BigDecimal("9.68").negate(), account.getCurrency(), invoice.getInvoiceItems().get(0).getId()));
// Invalid adjustment (too much)
invoice.addInvoiceItem(new ItemAdjInvoiceItem(invoice.getInvoiceItems().get(0), startDate, new BigDecimal("9.68").negate(), account.getCurrency()));
existingInvoices.add(invoice);
try {
fixedAndRecurringInvoiceItemGenerator.generateItems(account, UUID.randomUUID(), events, new AccountInvoices(null, null, existingInvoices), startDate, account.getCurrency(), new HashMap<UUID, SubscriptionFutureNotificationDates>(), null, internalCallContext).getItems();
fail();
} catch (final InvoiceApiException e) {
assertEquals(e.getCode(), ErrorCode.UNEXPECTED_ERROR.getCode());
assertTrue(e.getCause().getMessage().startsWith("Too many repairs"));
}
}
Aggregations