use of org.killbill.billing.junction.BillingEvent in project killbill by killbill.
the class TestBlockingCalculator method testCreateNewEventsClosedPrevBetw.
// Closed duration with a previous event and in-between event
// --X--[------Y-----]---------------------
@Test(groups = "fast")
public void testCreateNewEventsClosedPrevBetw() throws CatalogApiException {
final DateTime now = clock.getUTCNow();
final List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
final SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
billingEvents.add(createRealEvent(now.plusDays(1), subscription1));
final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, subscription1, internalCallContext);
assertEquals(results.size(), 2);
assertEquals(results.first().getEffectiveDate(), now);
assertNull(results.first().getFixedPrice());
assertNull(results.first().getRecurringPrice(null));
assertEquals(results.first().getBillingPeriod(), BillingPeriod.NO_BILLING_PERIOD);
assertEquals(results.first().getTransitionType(), SubscriptionBaseTransitionType.START_BILLING_DISABLED);
assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
assertEquals(results.last().getRecurringPrice(null), billingEvents.first().getRecurringPrice(null));
assertEquals(results.last().getTransitionType(), SubscriptionBaseTransitionType.END_BILLING_DISABLED);
}
use of org.killbill.billing.junction.BillingEvent in project killbill by killbill.
the class TestBlockingCalculator method testCreateNewEventsOpenPrevFollow.
// Open with previous and following events
// --X--[----Y-----------------------------
@Test(groups = "fast")
public void testCreateNewEventsOpenPrevFollow() throws CatalogApiException {
final DateTime now = clock.getUTCNow();
final List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
final SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
disabledDuration.add(new DisabledDuration(now, null));
billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
billingEvents.add(createRealEvent(now.plusDays(1), subscription1));
final SortedSet<BillingEvent> results = blockingCalculator.createNewEvents(disabledDuration, billingEvents, subscription1, internalCallContext);
assertEquals(results.size(), 1);
assertEquals(results.first().getEffectiveDate(), now);
assertNull(results.first().getFixedPrice());
assertNull(results.first().getRecurringPrice(null));
assertEquals(results.first().getBillingPeriod(), BillingPeriod.NO_BILLING_PERIOD);
assertEquals(results.first().getTransitionType(), SubscriptionBaseTransitionType.START_BILLING_DISABLED);
}
use of org.killbill.billing.junction.BillingEvent in project killbill by killbill.
the class TestBlockingCalculator method testInsertBlockingEventsForBundle.
// S1-S2-S3 subscriptions in B1
// B1 -----[--------]
// S1 --A-------------------------------------
// S2 --B------C------------------------------
// S3 ------------------D---------------------
//Result
// S1 --A--[-------]--------------------------
// S2 --B--[-------]--------------------------
// S3 ------------------D---------------------
@Test(groups = "fast")
public void testInsertBlockingEventsForBundle() throws CatalogApiException {
final DateTime now = clock.getUTCNow();
final BillingEvent A = createRealEvent(now.minusDays(1).minusHours(1), subscription1);
final BillingEvent B = createRealEvent(now.minusDays(1), subscription2);
final BillingEvent C = createRealEvent(now.plusDays(1), subscription2);
final BillingEvent D = createRealEvent(now.plusDays(3), subscription3);
final SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
billingEvents.add(A);
billingEvents.add(B);
billingEvents.add(C);
billingEvents.add(D);
final BlockingState blockingState1 = new DefaultBlockingState(bundleId1, BlockingStateType.SUBSCRIPTION_BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now);
final BlockingState blockingState2 = new DefaultBlockingState(bundleId1, BlockingStateType.SUBSCRIPTION_BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(2));
blockingStateDao.setBlockingStatesAndPostBlockingTransitionEvent(ImmutableMap.<BlockingState, Optional<UUID>>of(blockingState1, Optional.<UUID>absent(), blockingState2, Optional.<UUID>absent()), internalCallContext);
blockingCalculator.insertBlockingEvents(billingEvents, new HashSet<UUID>(), internalCallContext);
assertEquals(billingEvents.size(), 7);
final SortedSet<BillingEvent> s1Events = blockingCalculator.filter(billingEvents, subscription1);
final Iterator<BillingEvent> it1 = s1Events.iterator();
assertEquals(it1.next(), A);
assertEquals(it1.next().getTransitionType(), SubscriptionBaseTransitionType.START_BILLING_DISABLED);
assertEquals(it1.next().getTransitionType(), SubscriptionBaseTransitionType.END_BILLING_DISABLED);
final SortedSet<BillingEvent> s2Events = blockingCalculator.filter(billingEvents, subscription2);
final Iterator<BillingEvent> it2 = s2Events.iterator();
assertEquals(it2.next(), B);
assertEquals(it2.next().getTransitionType(), SubscriptionBaseTransitionType.START_BILLING_DISABLED);
assertEquals(it2.next().getTransitionType(), SubscriptionBaseTransitionType.END_BILLING_DISABLED);
final SortedSet<BillingEvent> s3Events = blockingCalculator.filter(billingEvents, subscription3);
final Iterator<BillingEvent> it3 = s3Events.iterator();
assertEquals(it3.next(), D);
}
use of org.killbill.billing.junction.BillingEvent in project killbill by killbill.
the class FixedAndRecurringInvoiceItemGenerator method processFixedBillingEvents.
@VisibleForTesting
void processFixedBillingEvents(final UUID invoiceId, final UUID accountId, final BillingEventSet events, final LocalDate targetDate, final Currency currency, final List<InvoiceItem> proposedItems, final InternalCallContext internalCallContext) throws InvoiceApiException {
if (events.isEmpty()) {
return;
}
InvoiceItem prevItem = null;
// Pretty-print the generated invoice items from the junction events
final InvoiceItemGeneratorLogger invoiceItemGeneratorLogger = new InvoiceItemGeneratorLogger(invoiceId, accountId, "fixed", log);
final Iterator<BillingEvent> eventIt = events.iterator();
while (eventIt.hasNext()) {
final BillingEvent thisEvent = eventIt.next();
final InvoiceItem currentFixedPriceItem = generateFixedPriceItem(invoiceId, accountId, thisEvent, targetDate, currency, invoiceItemGeneratorLogger, internalCallContext);
if (!isSameDayAndSameSubscription(prevItem, thisEvent, internalCallContext) && prevItem != null) {
proposedItems.add(prevItem);
}
prevItem = currentFixedPriceItem;
}
// The last one if not null can always be inserted as there is nothing after to cancel it off.
if (prevItem != null) {
proposedItems.add(prevItem);
}
invoiceItemGeneratorLogger.logItems();
}
use of org.killbill.billing.junction.BillingEvent 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);
}
}
Aggregations