Search in sources :

Example 1 with BillingMode

use of org.killbill.billing.catalog.api.BillingMode in project killbill by killbill.

the class TestFixedAndRecurringInvoiceItemGenerator method testInAdvance5.

// 
// Scenario: Call processRecurringEvent 2 in a row
// - IN_ADVANCE
// - one CREATE billing event
// - one future CHANGE billing event (used to compute period endDate)
// - targetDate = CHANGE date
// 
// => Expect one item + 1 notification
// 
@Test(groups = "fast")
public void testInAdvance5() throws InvoiceApiException {
    final BillingMode billingMode = BillingMode.IN_ADVANCE;
    final UUID invoiceId = UUID.randomUUID();
    final InvoiceItemGeneratorLogger invoiceItemGeneratorLogger = new InvoiceItemGeneratorLogger(invoiceId, account.getId(), "recurring", logger);
    final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDates = new HashMap<>();
    final LocalDate eventDate1 = new LocalDate("2020-01-01");
    final BillingEvent event1 = createDefaultBillingEvent(eventDate1, null, BigDecimal.TEN, SubscriptionBaseTransitionType.CREATE, 1, 1, billingMode);
    final LocalDate eventDate2 = new LocalDate("2020-01-15");
    final BillingEvent event2 = createDefaultBillingEvent(eventDate2, null, BigDecimal.ONE, SubscriptionBaseTransitionType.CHANGE, 1, 2, billingMode);
    final LocalDate targetDate = eventDate2;
    List<InvoiceItem> invoiceItems = fixedAndRecurringInvoiceItemGenerator.processRecurringEvent(invoiceId, account.getId(), event1, event2, targetDate, account.getCurrency(), invoiceItemGeneratorLogger, perSubscriptionFutureNotificationDates, internalCallContext);
    assertEquals(invoiceItems.size(), 1);
    assertEquals(invoiceItems.get(0).getStartDate(), eventDate1);
    assertEquals(invoiceItems.get(0).getEndDate(), eventDate2);
    assertEquals(invoiceItems.get(0).getAmount().compareTo(BigDecimal.TEN), -1);
    SubscriptionFutureNotificationDates notifications = perSubscriptionFutureNotificationDates.get(subscription.getId());
    assertEquals(notifications.getNextRecurringDate(), eventDate2);
    // Call processRecurringEvent another time for  eventDate2
    invoiceItems = fixedAndRecurringInvoiceItemGenerator.processRecurringEvent(invoiceId, account.getId(), event2, null, targetDate, account.getCurrency(), invoiceItemGeneratorLogger, perSubscriptionFutureNotificationDates, internalCallContext);
    assertEquals(invoiceItems.size(), 1);
    assertEquals(invoiceItems.get(0).getStartDate(), eventDate2);
    assertEquals(invoiceItems.get(0).getEndDate(), eventDate1.plusMonths(1));
    assertEquals(invoiceItems.get(0).getAmount().compareTo(BigDecimal.TEN), -1);
    notifications = perSubscriptionFutureNotificationDates.get(subscription.getId());
    assertEquals(notifications.getNextRecurringDate(), eventDate1.plusMonths(1));
}
Also used : SubscriptionFutureNotificationDates(org.killbill.billing.invoice.generator.InvoiceWithMetadata.SubscriptionFutureNotificationDates) FixedPriceInvoiceItem(org.killbill.billing.invoice.model.FixedPriceInvoiceItem) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) RepairAdjInvoiceItem(org.killbill.billing.invoice.model.RepairAdjInvoiceItem) ItemAdjInvoiceItem(org.killbill.billing.invoice.model.ItemAdjInvoiceItem) HashMap(java.util.HashMap) BillingMode(org.killbill.billing.catalog.api.BillingMode) DefaultBillingEvent(org.killbill.billing.junction.plumbing.billing.DefaultBillingEvent) BillingEvent(org.killbill.billing.junction.BillingEvent) UUID(java.util.UUID) InvoiceItemGeneratorLogger(org.killbill.billing.invoice.generator.InvoiceItemGenerator.InvoiceItemGeneratorLogger) LocalDate(org.joda.time.LocalDate) Test(org.testng.annotations.Test)

Example 2 with BillingMode

use of org.killbill.billing.catalog.api.BillingMode in project killbill by killbill.

the class TestFixedAndRecurringInvoiceItemGenerator method testInArrear4b.

// 
// Scenario: Similar to testInArrear4b but change event is 1 MONTH after leading to 1 item being generated
// - IN_ARREAR
// - one CREATE billing event
// - one future CHANGE billing event (used to compute period endDate)
// - targetDate = CREATE date + 1 month
// 
// => Expect 1 item + 1 notification
// 
@Test(groups = "fast")
public void testInArrear4b() throws InvoiceApiException {
    final BillingMode billingMode = BillingMode.IN_ARREAR;
    final UUID invoiceId = UUID.randomUUID();
    final InvoiceItemGeneratorLogger invoiceItemGeneratorLogger = new InvoiceItemGeneratorLogger(invoiceId, account.getId(), "recurring", logger);
    final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDates = new HashMap<>();
    final LocalDate eventDate1 = new LocalDate("2020-01-01");
    final BillingEvent event1 = createDefaultBillingEvent(eventDate1, null, BigDecimal.TEN, SubscriptionBaseTransitionType.CREATE, 1, 1, billingMode);
    final LocalDate eventDate2 = new LocalDate("2020-02-15");
    final BillingEvent event2 = createDefaultBillingEvent(eventDate2, null, BigDecimal.ONE, SubscriptionBaseTransitionType.CHANGE, 1, 2, billingMode);
    final LocalDate targetDate = eventDate1.plusMonths(1);
    List<InvoiceItem> invoiceItems = fixedAndRecurringInvoiceItemGenerator.processRecurringEvent(invoiceId, account.getId(), event1, event2, targetDate, account.getCurrency(), invoiceItemGeneratorLogger, perSubscriptionFutureNotificationDates, internalCallContext);
    assertEquals(invoiceItems.size(), 1);
    assertEquals(invoiceItems.get(0).getStartDate(), eventDate1);
    assertEquals(invoiceItems.get(0).getEndDate(), eventDate1.plusMonths(1));
    assertEquals(invoiceItems.get(0).getAmount().compareTo(BigDecimal.TEN), 0);
    SubscriptionFutureNotificationDates notifications = perSubscriptionFutureNotificationDates.get(subscription.getId());
    assertEquals(notifications.getNextRecurringDate(), eventDate1.plusMonths(2));
    // Bonus 1: ... move targetDate to CHANGE date +. We see the same thing because 'thisEvent'=event1 we are still considering
    final LocalDate newTargetDate = eventDate2;
    invoiceItems = fixedAndRecurringInvoiceItemGenerator.processRecurringEvent(invoiceId, account.getId(), event1, event2, newTargetDate, account.getCurrency(), invoiceItemGeneratorLogger, perSubscriptionFutureNotificationDates, internalCallContext);
    assertEquals(invoiceItems.size(), 2);
    assertEquals(invoiceItems.get(0).getStartDate(), eventDate1);
    assertEquals(invoiceItems.get(0).getEndDate(), eventDate1.plusMonths(1));
    assertEquals(invoiceItems.get(0).getAmount().compareTo(BigDecimal.TEN), 0);
    assertEquals(invoiceItems.get(1).getStartDate(), eventDate1.plusMonths(1));
    assertEquals(invoiceItems.get(1).getEndDate(), eventDate2);
    assertEquals(invoiceItems.get(1).getAmount().compareTo(BigDecimal.TEN), -1);
    notifications = perSubscriptionFutureNotificationDates.get(subscription.getId());
    assertEquals(notifications.getNextRecurringDate(), eventDate1.plusMonths(2));
    // Bonus 2: ... thisEvent=event2
    invoiceItems = fixedAndRecurringInvoiceItemGenerator.processRecurringEvent(invoiceId, account.getId(), event2, null, newTargetDate, account.getCurrency(), invoiceItemGeneratorLogger, perSubscriptionFutureNotificationDates, internalCallContext);
    assertEquals(invoiceItems.size(), 0);
}
Also used : SubscriptionFutureNotificationDates(org.killbill.billing.invoice.generator.InvoiceWithMetadata.SubscriptionFutureNotificationDates) FixedPriceInvoiceItem(org.killbill.billing.invoice.model.FixedPriceInvoiceItem) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) RepairAdjInvoiceItem(org.killbill.billing.invoice.model.RepairAdjInvoiceItem) ItemAdjInvoiceItem(org.killbill.billing.invoice.model.ItemAdjInvoiceItem) HashMap(java.util.HashMap) BillingMode(org.killbill.billing.catalog.api.BillingMode) DefaultBillingEvent(org.killbill.billing.junction.plumbing.billing.DefaultBillingEvent) BillingEvent(org.killbill.billing.junction.BillingEvent) UUID(java.util.UUID) InvoiceItemGeneratorLogger(org.killbill.billing.invoice.generator.InvoiceItemGenerator.InvoiceItemGeneratorLogger) LocalDate(org.joda.time.LocalDate) Test(org.testng.annotations.Test)

Example 3 with BillingMode

use of org.killbill.billing.catalog.api.BillingMode in project killbill by killbill.

the class FixedAndRecurringInvoiceItemGenerator method processRecurringEvent.

// Turn a set of events into a list of invoice items. Note that the dates on the invoice items will be rounded (granularity of a day)
@VisibleForTesting
List<InvoiceItem> processRecurringEvent(final UUID invoiceId, final UUID accountId, final BillingEvent thisEvent, @Nullable final BillingEvent nextEvent, final LocalDate targetDate, final Currency currency, final InvoiceItemGeneratorLogger invoiceItemGeneratorLogger, final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDates, final InternalCallContext internalCallContext) throws InvoiceApiException {
    final List<InvoiceItem> items = new ArrayList<InvoiceItem>();
    final LocalDate thisEventEffectiveDate = internalCallContext.toLocalDate(thisEvent.getEffectiveDate());
    if (thisEventEffectiveDate.compareTo(targetDate) > 0) {
        return items;
    }
    // Handle recurring items
    final BillingPeriod billingPeriod = thisEvent.getBillingPeriod();
    if (billingPeriod != BillingPeriod.NO_BILLING_PERIOD) {
        final Plan currentPlan = thisEvent.getPlan();
        Preconditions.checkNotNull(currentPlan, "Unexpected null Plan name event = %s", thisEvent);
        final BillingMode recurringBillingMode = currentPlan.getRecurringBillingMode();
        final LocalDate startDate = thisEventEffectiveDate;
        if (!startDate.isAfter(targetDate)) {
            final LocalDate endDate = (nextEvent == null) ? null : internalCallContext.toLocalDate(nextEvent.getEffectiveDate());
            final int billCycleDayLocal = thisEvent.getBillCycleDayLocal();
            final RecurringInvoiceItemDataWithNextBillingCycleDate itemDataWithNextBillingCycleDate;
            try {
                itemDataWithNextBillingCycleDate = generateInvoiceItemData(startDate, endDate, targetDate, billCycleDayLocal, billingPeriod, recurringBillingMode);
            } catch (final InvalidDateSequenceException e) {
                throw new InvoiceApiException(ErrorCode.INVOICE_INVALID_DATE_SEQUENCE, startDate, endDate, targetDate);
            }
            for (final RecurringInvoiceItemData itemDatum : itemDataWithNextBillingCycleDate.getItemData()) {
                final BigDecimal rate = thisEvent.getRecurringPrice();
                if (rate != null) {
                    final BigDecimal amount = KillBillMoney.of(itemDatum.getNumberOfCycles().multiply(rate), currency);
                    final DateTime catalogEffectiveDate = thisEvent.getCatalogEffectiveDate() != null ? thisEvent.getCatalogEffectiveDate() : null;
                    final RecurringInvoiceItem recurringItem = new RecurringInvoiceItem(invoiceId, accountId, thisEvent.getBundleId(), thisEvent.getSubscriptionId(), currentPlan.getProduct().getName(), currentPlan.getName(), thisEvent.getPlanPhase().getName(), catalogEffectiveDate, itemDatum.getStartDate(), itemDatum.getEndDate(), amount, rate, currency);
                    items.add(recurringItem);
                }
            }
            updatePerSubscriptionNextNotificationDate(thisEvent.getSubscriptionId(), itemDataWithNextBillingCycleDate.getNextBillingCycleDate(), items, recurringBillingMode, perSubscriptionFutureNotificationDates);
        }
    } else {
        final SubscriptionFutureNotificationDates futureNotificationDates = perSubscriptionFutureNotificationDates.get(thisEvent.getSubscriptionId());
        if (futureNotificationDates != null) {
            futureNotificationDates.clearNextRecurringDate();
        }
    }
    // For debugging purposes
    invoiceItemGeneratorLogger.append(thisEvent, items);
    return items;
}
Also used : SubscriptionFutureNotificationDates(org.killbill.billing.invoice.generator.InvoiceWithMetadata.SubscriptionFutureNotificationDates) FixedPriceInvoiceItem(org.killbill.billing.invoice.model.FixedPriceInvoiceItem) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) InvoiceDateUtils.calculateProRationBeforeFirstBillingPeriod(org.killbill.billing.invoice.generator.InvoiceDateUtils.calculateProRationBeforeFirstBillingPeriod) BillingPeriod(org.killbill.billing.catalog.api.BillingPeriod) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) ArrayList(java.util.ArrayList) RecurringInvoiceItemData(org.killbill.billing.invoice.model.RecurringInvoiceItemData) Plan(org.killbill.billing.catalog.api.Plan) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal) DateTime(org.joda.time.DateTime) InvalidDateSequenceException(org.killbill.billing.invoice.model.InvalidDateSequenceException) RecurringInvoiceItemDataWithNextBillingCycleDate(org.killbill.billing.invoice.model.RecurringInvoiceItemDataWithNextBillingCycleDate) InvoiceApiException(org.killbill.billing.invoice.api.InvoiceApiException) BillingMode(org.killbill.billing.catalog.api.BillingMode) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 4 with BillingMode

use of org.killbill.billing.catalog.api.BillingMode in project killbill by killbill.

the class TestFixedAndRecurringInvoiceItemGenerator method testInArrear6.

// 
// Scenario: Start with future notification and verify the CANCEL event clears it
// - IN_ARREAR
// - one CANCEL billing event
// - targetDate = CANCEL date
// 
// => Expect nothing
// 
@Test(groups = "fast")
public void testInArrear6() throws InvoiceApiException {
    final BillingMode billingMode = BillingMode.IN_ARREAR;
    final UUID invoiceId = UUID.randomUUID();
    final InvoiceItemGeneratorLogger invoiceItemGeneratorLogger = new InvoiceItemGeneratorLogger(invoiceId, account.getId(), "recurring", logger);
    final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDates = new HashMap<>();
    final LocalDate eventDate1 = new LocalDate("2020-01-01");
    /*final BillingEvent event1 = */
    createDefaultBillingEvent(eventDate1, null, BigDecimal.TEN, SubscriptionBaseTransitionType.CREATE, 1, 1, billingMode);
    // Set next notification date
    SubscriptionFutureNotificationDates subscriptionFutureNotificationDates = new SubscriptionFutureNotificationDates(billingMode);
    subscriptionFutureNotificationDates.updateNextRecurringDateIfRequired(eventDate1.plusMonths(1));
    perSubscriptionFutureNotificationDates.put(subscription.getId(), subscriptionFutureNotificationDates);
    final LocalDate eventDate2 = new LocalDate("2020-01-15");
    final BillingEvent event2 = createDefaultBillingEvent(eventDate2, null, null, SubscriptionBaseTransitionType.CANCEL, 1, 2, billingMode);
    final LocalDate targetDate = eventDate2;
    final List<InvoiceItem> invoiceItems = fixedAndRecurringInvoiceItemGenerator.processRecurringEvent(invoiceId, account.getId(), event2, null, targetDate, account.getCurrency(), invoiceItemGeneratorLogger, perSubscriptionFutureNotificationDates, internalCallContext);
    assertEquals(invoiceItems.size(), 0);
    final SubscriptionFutureNotificationDates notifications = perSubscriptionFutureNotificationDates.get(subscription.getId());
    assertNull(notifications.getNextRecurringDate());
}
Also used : SubscriptionFutureNotificationDates(org.killbill.billing.invoice.generator.InvoiceWithMetadata.SubscriptionFutureNotificationDates) FixedPriceInvoiceItem(org.killbill.billing.invoice.model.FixedPriceInvoiceItem) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) RepairAdjInvoiceItem(org.killbill.billing.invoice.model.RepairAdjInvoiceItem) ItemAdjInvoiceItem(org.killbill.billing.invoice.model.ItemAdjInvoiceItem) HashMap(java.util.HashMap) BillingMode(org.killbill.billing.catalog.api.BillingMode) DefaultBillingEvent(org.killbill.billing.junction.plumbing.billing.DefaultBillingEvent) BillingEvent(org.killbill.billing.junction.BillingEvent) UUID(java.util.UUID) InvoiceItemGeneratorLogger(org.killbill.billing.invoice.generator.InvoiceItemGenerator.InvoiceItemGeneratorLogger) LocalDate(org.joda.time.LocalDate) Test(org.testng.annotations.Test)

Example 5 with BillingMode

use of org.killbill.billing.catalog.api.BillingMode in project killbill by killbill.

the class TestFixedAndRecurringInvoiceItemGenerator method testInAdvance4a.

// 
// Scenario:
// - IN_ADVANCE
// - one CREATE billing event
// - one future CHANGE billing event (used to compute period endDate)
// - targetDate = CREATE date
// 
// => Expect one item + 1 notification
// 
@Test(groups = "fast")
public void testInAdvance4a() throws InvoiceApiException {
    final BillingMode billingMode = BillingMode.IN_ADVANCE;
    final UUID invoiceId = UUID.randomUUID();
    final InvoiceItemGeneratorLogger invoiceItemGeneratorLogger = new InvoiceItemGeneratorLogger(invoiceId, account.getId(), "recurring", logger);
    final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDates = new HashMap<>();
    final LocalDate eventDate1 = new LocalDate("2020-01-01");
    final BillingEvent event1 = createDefaultBillingEvent(eventDate1, null, BigDecimal.TEN, SubscriptionBaseTransitionType.CREATE, 1, 1, billingMode);
    final LocalDate eventDate2 = new LocalDate("2020-01-15");
    final BillingEvent event2 = createDefaultBillingEvent(eventDate2, null, BigDecimal.ONE, SubscriptionBaseTransitionType.CHANGE, 1, 2, billingMode);
    final LocalDate targetDate = eventDate1;
    final List<InvoiceItem> invoiceItems = fixedAndRecurringInvoiceItemGenerator.processRecurringEvent(invoiceId, account.getId(), event1, event2, targetDate, account.getCurrency(), invoiceItemGeneratorLogger, perSubscriptionFutureNotificationDates, internalCallContext);
    assertEquals(invoiceItems.size(), 1);
    assertEquals(invoiceItems.get(0).getStartDate(), eventDate1);
    assertEquals(invoiceItems.get(0).getEndDate(), eventDate2);
    assertEquals(invoiceItems.get(0).getAmount().compareTo(BigDecimal.TEN), -1);
    final SubscriptionFutureNotificationDates notifications = perSubscriptionFutureNotificationDates.get(subscription.getId());
    assertEquals(notifications.getNextRecurringDate(), eventDate2);
}
Also used : SubscriptionFutureNotificationDates(org.killbill.billing.invoice.generator.InvoiceWithMetadata.SubscriptionFutureNotificationDates) FixedPriceInvoiceItem(org.killbill.billing.invoice.model.FixedPriceInvoiceItem) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) RepairAdjInvoiceItem(org.killbill.billing.invoice.model.RepairAdjInvoiceItem) ItemAdjInvoiceItem(org.killbill.billing.invoice.model.ItemAdjInvoiceItem) HashMap(java.util.HashMap) BillingMode(org.killbill.billing.catalog.api.BillingMode) DefaultBillingEvent(org.killbill.billing.junction.plumbing.billing.DefaultBillingEvent) BillingEvent(org.killbill.billing.junction.BillingEvent) UUID(java.util.UUID) InvoiceItemGeneratorLogger(org.killbill.billing.invoice.generator.InvoiceItemGenerator.InvoiceItemGeneratorLogger) LocalDate(org.joda.time.LocalDate) Test(org.testng.annotations.Test)

Aggregations

LocalDate (org.joda.time.LocalDate)15 BillingMode (org.killbill.billing.catalog.api.BillingMode)15 InvoiceItem (org.killbill.billing.invoice.api.InvoiceItem)15 SubscriptionFutureNotificationDates (org.killbill.billing.invoice.generator.InvoiceWithMetadata.SubscriptionFutureNotificationDates)15 FixedPriceInvoiceItem (org.killbill.billing.invoice.model.FixedPriceInvoiceItem)15 RecurringInvoiceItem (org.killbill.billing.invoice.model.RecurringInvoiceItem)15 HashMap (java.util.HashMap)14 UUID (java.util.UUID)14 InvoiceItemGeneratorLogger (org.killbill.billing.invoice.generator.InvoiceItemGenerator.InvoiceItemGeneratorLogger)14 ItemAdjInvoiceItem (org.killbill.billing.invoice.model.ItemAdjInvoiceItem)14 RepairAdjInvoiceItem (org.killbill.billing.invoice.model.RepairAdjInvoiceItem)14 BillingEvent (org.killbill.billing.junction.BillingEvent)14 DefaultBillingEvent (org.killbill.billing.junction.plumbing.billing.DefaultBillingEvent)14 Test (org.testng.annotations.Test)14 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 BigDecimal (java.math.BigDecimal)1 ArrayList (java.util.ArrayList)1 DateTime (org.joda.time.DateTime)1 BillingPeriod (org.killbill.billing.catalog.api.BillingPeriod)1 Plan (org.killbill.billing.catalog.api.Plan)1