use of org.killbill.billing.catalog.api.Usage in project killbill by killbill.
the class TestXMLReader method testUsageCapacityInAdvance.
@Test(groups = "fast")
public void testUsageCapacityInAdvance() {
try {
final StandaloneCatalog catalog = XMLLoader.getObjectFromString(Resources.getResource("UsageExperimental.xml").toExternalForm(), StandaloneCatalog.class);
final Usage[] usages = getUsages(catalog, "capacity-in-advance-monthly");
assertEquals(usages.length, 1);
final Usage usage = usages[0];
assertEquals(usage.getName(), "capacity-in-advance-monthly-usage1");
assertEquals(usage.getBillingPeriod(), BillingPeriod.MONTHLY);
assertEquals(usage.getUsageType(), UsageType.CAPACITY);
assertEquals(usage.getBillingMode(), BillingMode.IN_ADVANCE);
assertEquals(usage.getBlocks().length, 0);
assertEquals(usage.getTiers().length, 0);
assertEquals(usage.getLimits().length, 1);
assertEquals(usage.getLimits()[0].getUnit().getName(), "members");
assertEquals(usage.getLimits()[0].getMax(), new Double("100"));
assertEquals(usage.getRecurringPrice().getPrices().length, 1);
assertEquals(usage.getRecurringPrice().getPrices()[0].getCurrency(), Currency.BTC);
assertEquals(usage.getRecurringPrice().getPrices()[0].getValue(), new BigDecimal("100.00"));
} catch (Exception e) {
Assert.fail(e.toString());
}
}
use of org.killbill.billing.catalog.api.Usage in project killbill by killbill.
the class TestXMLReader method testUsageConsumableInAdvancePrepayCredit.
@Test(groups = "fast")
public void testUsageConsumableInAdvancePrepayCredit() {
try {
final StandaloneCatalog catalog = XMLLoader.getObjectFromString(Resources.getResource("UsageExperimental.xml").toExternalForm(), StandaloneCatalog.class);
final Usage[] usages = getUsages(catalog, "consumable-in-advance-prepay-credit-monthly");
assertEquals(usages.length, 1);
final Usage usage = usages[0];
assertEquals(usage.getName(), "consumable-in-advance-prepay-credit-monthly-usage1");
assertEquals(usage.getBillingPeriod(), BillingPeriod.MONTHLY);
assertEquals(usage.getUsageType(), UsageType.CONSUMABLE);
assertEquals(usage.getBillingMode(), BillingMode.IN_ADVANCE);
assertEquals(usage.getLimits().length, 0);
assertEquals(usage.getTiers().length, 0);
assertEquals(usage.getBlocks().length, 1);
assertEquals(usage.getBlocks()[0].getUnit().getName(), "cell-phone-minutes");
assertEquals(usage.getBlocks()[0].getSize(), new Double("1000"));
assertEquals(usage.getBlocks()[0].getPrice().getPrices().length, 1);
assertEquals(usage.getBlocks()[0].getPrice().getPrices()[0].getCurrency(), Currency.BTC);
assertEquals(usage.getBlocks()[0].getPrice().getPrices()[0].getValue(), new BigDecimal("0.10"));
} catch (Exception e) {
Assert.fail(e.toString());
}
}
use of org.killbill.billing.catalog.api.Usage in project killbill by killbill.
the class TestXMLReader method getUsages.
private Usage[] getUsages(final StandaloneCatalog catalog, final String planName) throws CatalogApiException {
final Plan plan = catalog.findCurrentPlan(planName);
assertNotNull(plan);
final PlanPhase phase = plan.getFinalPhase();
assertNotNull(phase);
final Usage[] usages = phase.getUsages();
return usages;
}
use of org.killbill.billing.catalog.api.Usage in project killbill by killbill.
the class UsageInvoiceItemGenerator method generateItems.
@Override
public List<InvoiceItem> generateItems(final ImmutableAccountData account, final UUID invoiceId, final BillingEventSet eventSet, @Nullable final List<Invoice> existingInvoices, final LocalDate targetDate, final Currency targetCurrency, final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDates, final InternalCallContext internalCallContext) throws InvoiceApiException {
final Map<UUID, List<InvoiceItem>> perSubscriptionInArrearUsageItems = extractPerSubscriptionExistingInArrearUsageItems(eventSet.getUsages(), existingInvoices);
try {
// Pretty-print the generated invoice items from the junction events
final InvoiceItemGeneratorLogger invoiceItemGeneratorLogger = new InvoiceItemGeneratorLogger(invoiceId, account.getId(), "usage", log);
final LocalDate minBillingEventDate = getMinBillingEventDate(eventSet, internalCallContext);
final List<InvoiceItem> items = Lists.newArrayList();
final Iterator<BillingEvent> events = eventSet.iterator();
RawUsageOptimizerResult rawUsageOptimizerResult = null;
List<BillingEvent> curEvents = Lists.newArrayList();
UUID curSubscriptionId = null;
while (events.hasNext()) {
final BillingEvent event = events.next();
// Skip events that are posterior to the targetDate
final LocalDate eventLocalEffectiveDate = internalCallContext.toLocalDate(event.getEffectiveDate());
if (eventLocalEffectiveDate.isAfter(targetDate)) {
continue;
}
// Optimize to do the usage query only once after we know there are indeed some usage items
if (rawUsageOptimizerResult == null && Iterables.any(event.getUsages(), new Predicate<Usage>() {
@Override
public boolean apply(@Nullable final Usage input) {
return input.getBillingMode() == BillingMode.IN_ARREAR;
}
})) {
rawUsageOptimizerResult = rawUsageOptimizer.getInArrearUsage(minBillingEventDate, targetDate, Iterables.concat(perSubscriptionInArrearUsageItems.values()), eventSet.getUsages(), internalCallContext);
}
// None of the billing events report any usage IN_ARREAR sections
if (rawUsageOptimizerResult == null) {
continue;
}
final UUID subscriptionId = event.getSubscription().getId();
if (curSubscriptionId != null && !curSubscriptionId.equals(subscriptionId)) {
final SubscriptionUsageInArrear subscriptionUsageInArrear = new SubscriptionUsageInArrear(account.getId(), invoiceId, curEvents, rawUsageOptimizerResult.getRawUsage(), targetDate, rawUsageOptimizerResult.getRawUsageStartDate(), internalCallContext);
final List<InvoiceItem> usageInArrearItems = perSubscriptionInArrearUsageItems.get(curSubscriptionId);
final SubscriptionUsageInArrearItemsAndNextNotificationDate subscriptionResult = subscriptionUsageInArrear.computeMissingUsageInvoiceItems(usageInArrearItems != null ? usageInArrearItems : ImmutableList.<InvoiceItem>of(), invoiceItemGeneratorLogger);
final List<InvoiceItem> newInArrearUsageItems = subscriptionResult.getInvoiceItems();
items.addAll(newInArrearUsageItems);
updatePerSubscriptionNextNotificationUsageDate(curSubscriptionId, subscriptionResult.getPerUsageNotificationDates(), BillingMode.IN_ARREAR, perSubscriptionFutureNotificationDates);
curEvents = Lists.newArrayList();
}
curSubscriptionId = subscriptionId;
curEvents.add(event);
}
if (curSubscriptionId != null) {
final SubscriptionUsageInArrear subscriptionUsageInArrear = new SubscriptionUsageInArrear(account.getId(), invoiceId, curEvents, rawUsageOptimizerResult.getRawUsage(), targetDate, rawUsageOptimizerResult.getRawUsageStartDate(), internalCallContext);
final List<InvoiceItem> usageInArrearItems = perSubscriptionInArrearUsageItems.get(curSubscriptionId);
final SubscriptionUsageInArrearItemsAndNextNotificationDate subscriptionResult = subscriptionUsageInArrear.computeMissingUsageInvoiceItems(usageInArrearItems != null ? usageInArrearItems : ImmutableList.<InvoiceItem>of(), invoiceItemGeneratorLogger);
final List<InvoiceItem> newInArrearUsageItems = subscriptionResult.getInvoiceItems();
items.addAll(newInArrearUsageItems);
updatePerSubscriptionNextNotificationUsageDate(curSubscriptionId, subscriptionResult.getPerUsageNotificationDates(), BillingMode.IN_ARREAR, perSubscriptionFutureNotificationDates);
}
invoiceItemGeneratorLogger.logItems();
return items;
} catch (final CatalogApiException e) {
throw new InvoiceApiException(e);
}
}
use of org.killbill.billing.catalog.api.Usage 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;
}
Aggregations