Search in sources :

Example 46 with BillingPeriod

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

the class TestCatalogRetireElements method testRetirePriceList.

@Test(groups = "slow")
public void testRetirePriceList() throws Exception {
    // Catalog v1 starts in 2011-01-01
    // Catalog v2 starts in 2015-12-01
    // Catalog v3 starts in 2016-01-01
    final LocalDate today = new LocalDate(2015, 11, 1);
    // Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
    clock.setDay(today);
    final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(1));
    //accountUserApi.createAccount(getAccountData(1), callContext);
    final String productName = "Pistol";
    final BillingPeriod term = BillingPeriod.MONTHLY;
    final PlanPhaseSpecifier spec = new PlanPhaseSpecifier(productName, term, "SpecialDiscount", null);
    busHandler.pushExpectedEvents(NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
    final Entitlement bpEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, "externalKey", null, null, null, false, ImmutableList.<PluginProperty>of(), callContext);
    assertListenerStatus();
    assertNotNull(bpEntitlement);
    assertEquals(invoiceUserApi.getInvoicesByAccount(account.getId(), false, callContext).size(), 1);
    // Move out a month.
    busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
    clock.addMonths(1);
    assertListenerStatus();
    // Move out a month.
    busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
    clock.addMonths(1);
    assertListenerStatus();
    try {
        entitlementApi.createBaseEntitlement(account.getId(), spec, "externalKey2", null, null, null, false, ImmutableList.<PluginProperty>of(), callContext);
        // force to fail is there is not an exception
        fail();
    } catch (final EntitlementApiException e) {
        assertTrue(e.getLocalizedMessage().startsWith("Could not find any product named 'Pistol'"));
    }
    // Move out a month and verify 'Pistol' plan continue working as expected.
    busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
    clock.addMonths(1);
    assertListenerStatus();
    // Move out a month.
    busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.NULL_INVOICE, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
    clock.addMonths(1);
    assertListenerStatus();
    final List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), false, callContext);
    assertEquals(invoices.size(), 5);
    assertTrue(invoices.get(0).getInvoiceItems().get(0).getPhaseName().equals("discount-pistol-monthly-trial"));
    assertTrue(invoices.get(1).getInvoiceItems().get(0).getPhaseName().equals("discount-pistol-monthly-discount"));
    assertTrue(invoices.get(2).getInvoiceItems().get(0).getPhaseName().equals("discount-pistol-monthly-discount"));
    assertTrue(invoices.get(3).getInvoiceItems().get(0).getPhaseName().equals("discount-pistol-monthly-discount"));
    assertTrue(invoices.get(4).getInvoiceItems().get(0).getPhaseName().equals("discount-pistol-monthly-evergreen"));
}
Also used : PlanPhaseSpecifier(org.killbill.billing.catalog.api.PlanPhaseSpecifier) Account(org.killbill.billing.account.api.Account) Invoice(org.killbill.billing.invoice.api.Invoice) BillingPeriod(org.killbill.billing.catalog.api.BillingPeriod) EntitlementApiException(org.killbill.billing.entitlement.api.EntitlementApiException) Entitlement(org.killbill.billing.entitlement.api.Entitlement) DefaultEntitlement(org.killbill.billing.entitlement.api.DefaultEntitlement) LocalDate(org.joda.time.LocalDate) Test(org.testng.annotations.Test)

Example 47 with BillingPeriod

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

the class DefaultCase method satisfiesCase.

protected boolean satisfiesCase(final PlanSpecifier planPhase, final StaticCatalog c) throws CatalogApiException {
    final Product product;
    final BillingPeriod billingPeriod;
    final ProductCategory productCategory;
    final PriceList priceList;
    if (planPhase.getPlanName() != null) {
        final Plan plan = c.findCurrentPlan(planPhase.getPlanName());
        product = plan.getProduct();
        billingPeriod = plan.getRecurringBillingPeriod();
        productCategory = plan.getProduct().getCategory();
        priceList = c.findCurrentPricelist(plan.getPriceListName());
    } else {
        product = c.findCurrentProduct(planPhase.getProductName());
        billingPeriod = planPhase.getBillingPeriod();
        productCategory = product.getCategory();
        priceList = getPriceList() != null ? c.findCurrentPricelist(planPhase.getPriceListName()) : null;
    }
    return (getProduct() == null || getProduct().equals(product)) && (getProductCategory() == null || getProductCategory().equals(productCategory)) && (getBillingPeriod() == null || getBillingPeriod().equals(billingPeriod)) && (getPriceList() == null || getPriceList().equals(priceList));
}
Also used : BillingPeriod(org.killbill.billing.catalog.api.BillingPeriod) ProductCategory(org.killbill.billing.catalog.api.ProductCategory) DefaultProduct(org.killbill.billing.catalog.DefaultProduct) Product(org.killbill.billing.catalog.api.Product) Plan(org.killbill.billing.catalog.api.Plan) PriceList(org.killbill.billing.catalog.api.PriceList) DefaultPriceList(org.killbill.billing.catalog.DefaultPriceList)

Example 48 with BillingPeriod

use of org.killbill.billing.catalog.api.BillingPeriod 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)
private 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 BillingMode billingMode, final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDate, final InternalCallContext internalCallContext) throws InvoiceApiException {
    try {
        final List<InvoiceItem> items = new ArrayList<InvoiceItem>();
        // For FIXEDTERM phases we need to stop when the specified duration has been reached
        final LocalDate maxEndDate = thisEvent.getPlanPhase().getPhaseType() == PhaseType.FIXEDTERM ? thisEvent.getPlanPhase().getDuration().addToLocalDate(internalCallContext.toLocalDate(thisEvent.getEffectiveDate())) : null;
        // Handle recurring items
        final BillingPeriod billingPeriod = thisEvent.getBillingPeriod();
        if (billingPeriod != BillingPeriod.NO_BILLING_PERIOD) {
            final LocalDate startDate = internalCallContext.toLocalDate(thisEvent.getEffectiveDate());
            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, billingMode);
                } catch (final InvalidDateSequenceException e) {
                    throw new InvoiceApiException(ErrorCode.INVOICE_INVALID_DATE_SEQUENCE, startDate, endDate, targetDate);
                }
                for (final RecurringInvoiceItemData itemDatum : itemDataWithNextBillingCycleDate.getItemData()) {
                    // Stop if there a maxEndDate and we have reached it
                    if (maxEndDate != null && maxEndDate.compareTo(itemDatum.getEndDate()) < 0) {
                        break;
                    }
                    final BigDecimal rate = thisEvent.getRecurringPrice(internalCallContext.toUTCDateTime(itemDatum.getStartDate()));
                    if (rate != null) {
                        final BigDecimal amount = KillBillMoney.of(itemDatum.getNumberOfCycles().multiply(rate), currency);
                        final RecurringInvoiceItem recurringItem = new RecurringInvoiceItem(invoiceId, accountId, thisEvent.getSubscription().getBundleId(), thisEvent.getSubscription().getId(), thisEvent.getPlan().getName(), thisEvent.getPlanPhase().getName(), itemDatum.getStartDate(), itemDatum.getEndDate(), amount, rate, currency);
                        items.add(recurringItem);
                    }
                }
                updatePerSubscriptionNextNotificationDate(thisEvent.getSubscription().getId(), itemDataWithNextBillingCycleDate.getNextBillingCycleDate(), items, billingMode, perSubscriptionFutureNotificationDate);
            }
        }
        // For debugging purposes
        invoiceItemGeneratorLogger.append(thisEvent, items);
        return items;
    } catch (final CatalogApiException e) {
        throw new InvoiceApiException(e);
    }
}
Also used : FixedPriceInvoiceItem(org.killbill.billing.invoice.model.FixedPriceInvoiceItem) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) BillingPeriod(org.killbill.billing.catalog.api.BillingPeriod) InvoiceDateUtils.calculateProRationBeforeFirstBillingPeriod(org.killbill.billing.invoice.generator.InvoiceDateUtils.calculateProRationBeforeFirstBillingPeriod) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) ArrayList(java.util.ArrayList) RecurringInvoiceItemData(org.killbill.billing.invoice.model.RecurringInvoiceItemData) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal) InvalidDateSequenceException(org.killbill.billing.invoice.model.InvalidDateSequenceException) RecurringInvoiceItemDataWithNextBillingCycleDate(org.killbill.billing.invoice.model.RecurringInvoiceItemDataWithNextBillingCycleDate) InvoiceApiException(org.killbill.billing.invoice.api.InvoiceApiException) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException)

Example 49 with BillingPeriod

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

the class RawUsageOptimizer method getOptimizedRawUsageStartDate.

@VisibleForTesting
LocalDate getOptimizedRawUsageStartDate(final LocalDate firstEventStartDate, final LocalDate targetDate, final Iterable<InvoiceItem> existingUsageItems, final Map<String, Usage> knownUsage, final InternalCallContext internalCallContext) {
    if (!existingUsageItems.iterator().hasNext()) {
        return firstEventStartDate;
    }
    // Extract all usage billing period known in that catalog
    final Set<BillingPeriod> knownUsageBillingPeriod = ImmutableSet.copyOf(Iterables.transform(knownUsage.values(), new Function<Usage, BillingPeriod>() {

        @Nullable
        @Override
        public BillingPeriod apply(final Usage input) {
            return input.getBillingPeriod();
        }
    }));
    // Make sure all usage items are sorted by endDate
    final List<InvoiceItem> sortedUsageItems = USAGE_ITEM_ORDERING.sortedCopy(existingUsageItems);
    // Compute an array with one date per BillingPeriod:
    // If BillingPeriod is never defined in the catalog (no need to look for items), we initialize its value
    // such that it cannot be chosen
    //
    // Exclude the NO_BILLING_PERIOD
    final LocalDate[] perBillingPeriodMostRecentConsumableInArrearItemEndDate = new LocalDate[BillingPeriod.values().length - 1];
    int idx = 0;
    for (final BillingPeriod bp : BillingPeriod.values()) {
        if (bp != BillingPeriod.NO_BILLING_PERIOD) {
            final LocalDate makerDateThanCannotBeChosenAsTheMinOfAllDates = InvoiceDateUtils.advanceByNPeriods(targetDate, bp, config.getMaxRawUsagePreviousPeriod(internalCallContext));
            perBillingPeriodMostRecentConsumableInArrearItemEndDate[idx++] = (knownUsageBillingPeriod.contains(bp)) ? null : makerDateThanCannotBeChosenAsTheMinOfAllDates;
        }
    }
    final ListIterator<InvoiceItem> iterator = sortedUsageItems.listIterator(sortedUsageItems.size());
    while (iterator.hasPrevious()) {
        final InvoiceItem previous = iterator.previous();
        Preconditions.checkState(previous instanceof UsageInvoiceItem);
        final UsageInvoiceItem item = (UsageInvoiceItem) previous;
        final Usage usage = knownUsage.get(item.getUsageName());
        if (perBillingPeriodMostRecentConsumableInArrearItemEndDate[usage.getBillingPeriod().ordinal()] == null) {
            perBillingPeriodMostRecentConsumableInArrearItemEndDate[usage.getBillingPeriod().ordinal()] = item.getEndDate();
            if (!containsNullEntries(perBillingPeriodMostRecentConsumableInArrearItemEndDate)) {
                break;
            }
        }
    }
    // Extract the min from all the dates
    LocalDate targetStartDate = null;
    idx = 0;
    for (final BillingPeriod bp : BillingPeriod.values()) {
        if (bp != BillingPeriod.NO_BILLING_PERIOD) {
            final LocalDate tmp = perBillingPeriodMostRecentConsumableInArrearItemEndDate[idx];
            final LocalDate targetBillingPeriodDate = tmp != null ? InvoiceDateUtils.recedeByNPeriods(tmp, bp, config.getMaxRawUsagePreviousPeriod(internalCallContext)) : null;
            if (targetStartDate == null || (targetBillingPeriodDate != null && targetBillingPeriodDate.compareTo(targetStartDate) < 0)) {
                targetStartDate = targetBillingPeriodDate;
            }
            idx++;
        }
    }
    final LocalDate result = targetStartDate.compareTo(firstEventStartDate) > 0 ? targetStartDate : firstEventStartDate;
    return result;
}
Also used : Function(com.google.common.base.Function) Usage(org.killbill.billing.catalog.api.Usage) RawUsage(org.killbill.billing.usage.RawUsage) UsageInvoiceItem(org.killbill.billing.invoice.model.UsageInvoiceItem) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) BillingPeriod(org.killbill.billing.catalog.api.BillingPeriod) UsageInvoiceItem(org.killbill.billing.invoice.model.UsageInvoiceItem) LocalDate(org.joda.time.LocalDate) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 50 with BillingPeriod

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

the class BlockingCalculator method createNewDisableEvent.

protected BillingEvent createNewDisableEvent(final DateTime odEventTime, final BillingEvent previousEvent, final Catalog catalog, final InternalTenantContext context) throws CatalogApiException {
    final int billCycleDay = previousEvent.getBillCycleDayLocal();
    final SubscriptionBase subscription = previousEvent.getSubscription();
    final DateTime effectiveDate = odEventTime;
    final PlanPhase planPhase = previousEvent.getPlanPhase();
    final Plan plan = previousEvent.getPlan();
    // Make sure to set the fixed price to null and the billing period to NO_BILLING_PERIOD,
    // which makes invoice disregard this event
    final BigDecimal fixedPrice = null;
    final BillingPeriod billingPeriod = BillingPeriod.NO_BILLING_PERIOD;
    final Currency currency = previousEvent.getCurrency();
    final String description = "";
    final SubscriptionBaseTransitionType type = SubscriptionBaseTransitionType.START_BILLING_DISABLED;
    final Long totalOrdering = globaltotalOrder.getAndIncrement();
    final DateTimeZone tz = previousEvent.getTimeZone();
    return new DefaultBillingEvent(subscription, effectiveDate, true, plan, planPhase, fixedPrice, currency, billingPeriod, billCycleDay, description, totalOrdering, type, tz, catalog, true);
}
Also used : BillingPeriod(org.killbill.billing.catalog.api.BillingPeriod) SubscriptionBaseTransitionType(org.killbill.billing.subscription.api.SubscriptionBaseTransitionType) Plan(org.killbill.billing.catalog.api.Plan) DateTime(org.joda.time.DateTime) BigDecimal(java.math.BigDecimal) DateTimeZone(org.joda.time.DateTimeZone) SubscriptionBase(org.killbill.billing.subscription.api.SubscriptionBase) Currency(org.killbill.billing.catalog.api.Currency) AtomicLong(java.util.concurrent.atomic.AtomicLong) PlanPhase(org.killbill.billing.catalog.api.PlanPhase)

Aggregations

BillingPeriod (org.killbill.billing.catalog.api.BillingPeriod)80 Test (org.testng.annotations.Test)69 DateTime (org.joda.time.DateTime)53 LocalDate (org.joda.time.LocalDate)30 DefaultEntitlement (org.killbill.billing.entitlement.api.DefaultEntitlement)29 BigDecimal (java.math.BigDecimal)28 Account (org.killbill.billing.account.api.Account)27 Invoice (org.killbill.billing.invoice.api.Invoice)26 ExpectedInvoiceItemCheck (org.killbill.billing.beatrix.util.InvoiceChecker.ExpectedInvoiceItemCheck)20 Interval (org.joda.time.Interval)18 Plan (org.killbill.billing.catalog.api.Plan)16 PlanPhase (org.killbill.billing.catalog.api.PlanPhase)16 ArrayList (java.util.ArrayList)11 Duration (org.killbill.billing.catalog.api.Duration)9 SubscriptionBase (org.killbill.billing.subscription.api.SubscriptionBase)9 DefaultSubscriptionBase (org.killbill.billing.subscription.api.user.DefaultSubscriptionBase)9 Account (org.killbill.billing.client.model.Account)7 Subscription (org.killbill.billing.client.model.Subscription)7 SubscriptionBaseBundle (org.killbill.billing.subscription.api.user.SubscriptionBaseBundle)7 UUID (java.util.UUID)6