Search in sources :

Example 11 with RawUsageRecord

use of org.killbill.billing.usage.api.RawUsageRecord in project killbill by killbill.

the class TestContiguousIntervalCapacityInArrear method testMultipleItemsAndTiersWithExistingItems.

@Test(groups = "fast")
public void testMultipleItemsAndTiersWithExistingItems() throws Exception {
    // let's assume we have some existing usage
    final UsageInArrearTierUnitDetail existingFooUsageTier1 = new UsageInArrearTierUnitDetail(1, "FOO", BigDecimal.ONE, 9L);
    final UsageInArrearTierUnitDetail existingBarUsageTier2 = new UsageInArrearTierUnitDetail(2, "BAR", BigDecimal.TEN, 200L);
    List<RawUsageRecord> rawUsageRecords = new ArrayList<RawUsageRecord>();
    // tier 3
    rawUsageRecords.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 60L, "tracking-1"));
    // tier 2
    rawUsageRecords.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 200L, "tracking-1"));
    final List<UsageInArrearTierUnitDetail> existingUsage = ImmutableList.of(existingFooUsageTier1, existingBarUsageTier2);
    final String existingUsageJson = objectMapper.writeValueAsString(new UsageCapacityInArrearAggregate(existingUsage, BigDecimal.TEN));
    final List<InvoiceItem> existingItems = new ArrayList<InvoiceItem>();
    final InvoiceItem ii1 = new UsageInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, productName, planName, phaseName, usageName, null, new LocalDate(2014, 03, 20), new LocalDate(2014, 04, 15), BigDecimal.TEN, null, currency, null, existingUsageJson);
    existingItems.add(ii1);
    List<InvoiceItem> result = produceInvoiceItems(rawUsageRecords, UsageDetailMode.AGGREGATE, existingItems);
    assertEquals(result.size(), 1);
    assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("90.00")), 0, String.format("%s != 90.0", result.get(0).getAmount()));
    UsageCapacityInArrearAggregate itemDetails = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<UsageCapacityInArrearAggregate>() {
    });
    assertEquals(itemDetails.getAmount().compareTo(new BigDecimal("100.00")), 0);
    assertEquals(itemDetails.getTierDetails().size(), 2);
    List<UsageInArrearTierUnitDetail> itemUnitDetails = itemDetails.getTierDetails();
    // BAR item detail
    assertEquals(itemUnitDetails.get(0).getTierUnit(), "BAR");
    assertEquals(itemUnitDetails.get(0).getTier(), 2);
    assertEquals(itemUnitDetails.get(0).getQuantity().intValue(), 200);
    assertEquals(itemUnitDetails.get(0).getTierPrice().compareTo(BigDecimal.TEN), 0);
    // FOO item detail
    assertEquals(itemUnitDetails.get(1).getTierUnit(), "FOO");
    assertEquals(itemUnitDetails.get(1).getTier(), 3);
    assertEquals(itemUnitDetails.get(1).getQuantity().intValue(), 60);
    assertEquals(itemUnitDetails.get(1).getTierPrice().compareTo(new BigDecimal("100.00")), 0);
}
Also used : FixedPriceInvoiceItem(org.killbill.billing.invoice.model.FixedPriceInvoiceItem) UsageInvoiceItem(org.killbill.billing.invoice.model.UsageInvoiceItem) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) UsageInvoiceItem(org.killbill.billing.invoice.model.UsageInvoiceItem) ArrayList(java.util.ArrayList) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal) RawUsageRecord(org.killbill.billing.usage.api.RawUsageRecord) UsageInArrearTierUnitDetail(org.killbill.billing.invoice.usage.details.UsageInArrearTierUnitDetail) DefaultRawUsage(org.killbill.billing.usage.api.svcs.DefaultRawUsage) UsageCapacityInArrearAggregate(org.killbill.billing.invoice.usage.details.UsageCapacityInArrearAggregate) Test(org.testng.annotations.Test)

Example 12 with RawUsageRecord

use of org.killbill.billing.usage.api.RawUsageRecord in project killbill by killbill.

the class ContiguousIntervalUsageInArrear method getRolledUpUsage.

@VisibleForTesting
RolledUpUnitsWithTracking getRolledUpUsage() throws InvoiceApiException {
    final List<RolledUpUsageWithMetadata> result = new ArrayList<RolledUpUsageWithMetadata>();
    final Set<TrackingRecordId> trackingIds = new HashSet<>();
    final Iterator<RawUsageRecord> rawUsageIterator = rawSubscriptionUsage.iterator();
    if (!rawUsageIterator.hasNext()) {
        return new RolledUpUnitsWithTracking(getEmptyRolledUpUsage(), ImmutableSet.of());
    }
    // 
    // Skip all items before our first transition date
    // 
    // 'prevRawUsage' keeps track of first unconsumed raw usage element
    RawUsageRecord prevRawUsage = null;
    while (rawUsageIterator.hasNext()) {
        final RawUsageRecord curRawUsage = rawUsageIterator.next();
        if (curRawUsage.getDate().compareTo(transitionTimes.get(0).getDate()) >= 0) {
            prevRawUsage = curRawUsage;
            break;
        }
    }
    // Optimize path where all raw usage items are outside or our transitionTimes range
    if (prevRawUsage == null || prevRawUsage.getDate().compareTo(transitionTimes.get(transitionTimes.size() - 1).getDate()) > 0) {
        return new RolledUpUnitsWithTracking(getEmptyRolledUpUsage(), ImmutableSet.of());
    }
    // 
    // Loop through each interval [prevDate, curDate) and consume as many rawSubscriptionUsage elements within that range
    // to create one RolledUpUsage per interval. The first loop will be used to set the 'prevDate'.
    // 
    LocalDate prevDate = null;
    DateTime prevCatalogEffectiveDate = null;
    for (int i = 0; i < transitionTimes.size(); i++) {
        final TransitionTime curTransition = transitionTimes.get(i);
        final LocalDate curDate = curTransition.getDate();
        if (prevDate != null) {
            // Allocate and initialize new perRangeUnitToAmount for this interval and populate with rawSubscriptionUsage items
            final Map<String, Long> perRangeUnitToAmount = new HashMap<String, Long>();
            for (String unitType : unitTypes) {
                perRangeUnitToAmount.put(unitType, 0L);
            }
            // Start consuming prevRawUsage element if it exists and falls into the range
            if (prevRawUsage != null) {
                // Special treatment for final cancellation to make sure we include this usage point as part of the interval and bill for usage reported on cancellation date
                final boolean isUsageForCancellationDay = i == transitionTimes.size() - 1 && curTransition.getTargetBillingEvent().getTransitionType() == SubscriptionBaseTransitionType.CANCEL && curDate.compareTo(prevRawUsage.getDate()) == 0;
                if (prevRawUsage.getDate().compareTo(prevDate) >= 0 && (prevRawUsage.getDate().compareTo(curDate) < 0 || isUsageForCancellationDay)) {
                    final Long currentAmount = perRangeUnitToAmount.get(prevRawUsage.getUnitType());
                    final Long updatedAmount = computeUpdatedAmount(currentAmount, prevRawUsage.getAmount());
                    perRangeUnitToAmount.put(prevRawUsage.getUnitType(), updatedAmount);
                    trackingIds.add(new TrackingRecordId(prevRawUsage.getTrackingId(), invoiceId, prevRawUsage.getSubscriptionId(), prevRawUsage.getUnitType(), prevRawUsage.getDate()));
                    prevRawUsage = null;
                }
            }
            // 
            if (prevRawUsage == null) {
                while (rawUsageIterator.hasNext()) {
                    final RawUsageRecord curRawUsage = rawUsageIterator.next();
                    final boolean isUsageForCancellationDay = i == transitionTimes.size() - 1 && curTransition.getTargetBillingEvent().getTransitionType() == SubscriptionBaseTransitionType.CANCEL && curDate.compareTo(curRawUsage.getDate()) == 0;
                    // Special treatment for final cancellation to make sure we include this usage point as part of the interval and bill for usage reported on cancellation date
                    if (!isUsageForCancellationDay && curRawUsage.getDate().compareTo(curDate) >= 0) {
                        prevRawUsage = curRawUsage;
                        break;
                    }
                    final Long currentAmount = perRangeUnitToAmount.get(curRawUsage.getUnitType());
                    final Long updatedAmount = computeUpdatedAmount(currentAmount, curRawUsage.getAmount());
                    perRangeUnitToAmount.put(curRawUsage.getUnitType(), updatedAmount);
                    trackingIds.add(new TrackingRecordId(curRawUsage.getTrackingId(), invoiceId, curRawUsage.getSubscriptionId(), curRawUsage.getUnitType(), curRawUsage.getDate()));
                }
            }
            // If we did find some usage for that date range, let's populate the result
            if (!perRangeUnitToAmount.isEmpty()) {
                final List<RolledUpUnit> rolledUpUnits = new ArrayList<RolledUpUnit>(perRangeUnitToAmount.size());
                for (final Entry<String, Long> entry : perRangeUnitToAmount.entrySet()) {
                    final String unitType = entry.getKey();
                    // Sanity check: https://github.com/killbill/killbill/issues/1275
                    if (!allSeenUnitTypes.get(curTransition.getTargetBillingEvent()).contains(unitType)) {
                        // We have found some reported usage with a unit type that hasn't been handled by any ContiguousIntervalUsageInArrear
                        if (invoiceConfig.shouldParkAccountsWithUnknownUsage(internalTenantContext)) {
                            throw new InvoiceApiException(ErrorCode.UNEXPECTED_ERROR, String.format("ILLEGAL INVOICING STATE: unit type %s is not defined in the catalog effective Date %s for subscription %s)", unitType, curTransition.getTargetBillingEvent().getCatalogEffectiveDate(), curTransition.getTargetBillingEvent().getSubscriptionId()));
                        } else {
                            log.warn("Ignoring unit type {} for subscription {} (not defined in the catalog effective Date {})", unitType, curTransition.getTargetBillingEvent().getSubscriptionId(), curTransition.getTargetBillingEvent().getCatalogEffectiveDate());
                            // Make sure to remove the associated tracking ids
                            final Iterator<TrackingRecordId> itr = trackingIds.iterator();
                            while (itr.hasNext()) {
                                final TrackingRecordId t = itr.next();
                                if (unitType.equals(t.getUnitType())) {
                                    itr.remove();
                                }
                            }
                        }
                    } else if (unitTypes.contains(unitType)) {
                        // Other usage type not for us -- safely ignore
                        rolledUpUnits.add(new DefaultRolledUpUnit(unitType, entry.getValue()));
                    }
                }
                result.add(new DefaultRolledUpUsageWithMetadata(getSubscriptionId(), prevDate, curDate, rolledUpUnits, prevCatalogEffectiveDate));
            }
        }
        prevDate = curDate;
        prevCatalogEffectiveDate = curTransition.getTargetBillingEvent().getCatalogEffectiveDate();
    }
    return new RolledUpUnitsWithTracking(result, trackingIds);
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) LocalDate(org.joda.time.LocalDate) DateTime(org.joda.time.DateTime) RawUsageRecord(org.killbill.billing.usage.api.RawUsageRecord) InvoiceApiException(org.killbill.billing.invoice.api.InvoiceApiException) RolledUpUnit(org.killbill.billing.usage.api.RolledUpUnit) HashSet(java.util.HashSet) TrackingRecordId(org.killbill.billing.invoice.generator.InvoiceWithMetadata.TrackingRecordId) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 13 with RawUsageRecord

use of org.killbill.billing.usage.api.RawUsageRecord in project killbill by killbill.

the class TestContiguousIntervalConsumableInArrear method testComputeMissingItemsAggregateModeAllTier_AGGREGATE.

@Test(groups = "fast")
public void testComputeMissingItemsAggregateModeAllTier_AGGREGATE() throws Exception {
    // Case 1
    List<RawUsageRecord> rawUsageRecords = new ArrayList<RawUsageRecord>();
    rawUsageRecords.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 5L, "tracking-1"));
    rawUsageRecords.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 99L, "tracking-1"));
    List<InvoiceItem> result = produceInvoiceItems(rawUsageRecords, TierBlockPolicy.ALL_TIERS, UsageDetailMode.AGGREGATE, ImmutableList.<InvoiceItem>of());
    assertEquals(result.size(), 1);
    assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("203")), 0);
    UsageConsumableInArrearAggregate usageDetail = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<UsageConsumableInArrearAggregate>() {
    });
    List<UsageConsumableInArrearTierUnitAggregate> itemDetails = usageDetail.getTierDetails();
    // BAR: 99 * 2 = 198
    assertEquals(itemDetails.get(0).getTierUnit(), "BAR");
    assertEquals(itemDetails.get(0).getTier(), 1);
    assertEquals(itemDetails.get(0).getAmount().compareTo(new BigDecimal("198")), 0);
    assertEquals(itemDetails.get(0).getQuantity().intValue(), 99);
    assertEquals(itemDetails.get(0).getTierPrice().compareTo(new BigDecimal("2.0")), 0);
    // FOO: 5 * 1 = 5
    assertEquals(itemDetails.get(1).getTierUnit(), "FOO");
    assertEquals(itemDetails.get(1).getTier(), 1);
    assertEquals(itemDetails.get(1).getAmount().compareTo(new BigDecimal("5")), 0);
    assertEquals(itemDetails.get(1).getQuantity().intValue(), 5);
    assertEquals(itemDetails.get(1).getTierPrice().compareTo(BigDecimal.ONE), 0);
    // Case 2
    rawUsageRecords = new ArrayList<RawUsageRecord>();
    rawUsageRecords.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 5L, "tracking-2"));
    rawUsageRecords.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 101L, "tracking-2"));
    result = produceInvoiceItems(rawUsageRecords, TierBlockPolicy.ALL_TIERS, UsageDetailMode.AGGREGATE, ImmutableList.<InvoiceItem>of());
    assertEquals(result.size(), 1);
    assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("225")), 0);
    usageDetail = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<UsageConsumableInArrearAggregate>() {
    });
    itemDetails = usageDetail.getTierDetails();
    // BAR: 100 * 2 = 200
    assertEquals(itemDetails.get(0).getTierUnit(), "BAR");
    assertEquals(itemDetails.get(0).getTier(), 1);
    assertEquals(itemDetails.get(0).getAmount().compareTo(new BigDecimal("200.0")), 0);
    assertEquals(itemDetails.get(0).getQuantity().intValue(), 100);
    assertEquals(itemDetails.get(0).getTierPrice().compareTo(new BigDecimal("2.0")), 0);
    // BAR: 1 * 20 = 20
    assertEquals(itemDetails.get(1).getTierUnit(), "BAR");
    assertEquals(itemDetails.get(1).getTier(), 2);
    assertEquals(itemDetails.get(1).getAmount().compareTo(new BigDecimal("20.0")), 0);
    assertEquals(itemDetails.get(1).getQuantity().intValue(), 1);
    assertEquals(itemDetails.get(1).getTierPrice().compareTo(new BigDecimal("20.0")), 0);
    // FOO: 5 * 1 = 5
    assertEquals(itemDetails.get(2).getTierUnit(), "FOO");
    assertEquals(itemDetails.get(2).getTier(), 1);
    assertEquals(itemDetails.get(2).getAmount().compareTo(new BigDecimal("5")), 0);
    assertEquals(itemDetails.get(2).getQuantity().intValue(), 5);
    assertEquals(itemDetails.get(2).getTierPrice().compareTo(BigDecimal.ONE), 0);
    // Case 3
    rawUsageRecords = new ArrayList<RawUsageRecord>();
    rawUsageRecords.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 75L, "tracking-3"));
    rawUsageRecords.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 101L, "tracking-4"));
    result = produceInvoiceItems(rawUsageRecords, TierBlockPolicy.ALL_TIERS, UsageDetailMode.AGGREGATE, ImmutableList.<InvoiceItem>of());
    assertEquals(result.size(), 1);
    assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("2230")), 0);
    usageDetail = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<UsageConsumableInArrearAggregate>() {
    });
    itemDetails = usageDetail.getTierDetails();
    // BAR: 100 * 2 = 200
    assertEquals(itemDetails.get(0).getTierUnit(), "BAR");
    assertEquals(itemDetails.get(0).getTier(), 1);
    assertEquals(itemDetails.get(0).getAmount().compareTo(new BigDecimal("200.0")), 0);
    assertEquals(itemDetails.get(0).getQuantity().intValue(), 100);
    assertEquals(itemDetails.get(0).getTierPrice().compareTo(new BigDecimal("2.0")), 0);
    // BAR: 1 * 20 = 20
    assertEquals(itemDetails.get(1).getTierUnit(), "BAR");
    assertEquals(itemDetails.get(1).getTier(), 2);
    assertEquals(itemDetails.get(1).getAmount().compareTo(new BigDecimal("20.0")), 0);
    assertEquals(itemDetails.get(1).getQuantity().intValue(), 1);
    assertEquals(itemDetails.get(1).getTierPrice().compareTo(new BigDecimal("20.0")), 0);
    // FOO: 10 * 1 = 10
    assertEquals(itemDetails.get(2).getTierUnit(), "FOO");
    assertEquals(itemDetails.get(2).getTier(), 1);
    assertEquals(itemDetails.get(2).getAmount().compareTo(BigDecimal.TEN), 0);
    assertEquals(itemDetails.get(2).getQuantity().intValue(), 10);
    assertEquals(itemDetails.get(2).getTierPrice().compareTo(BigDecimal.ONE), 0);
    // FOO: 50 * 10 = 500
    assertEquals(itemDetails.get(3).getTierUnit(), "FOO");
    assertEquals(itemDetails.get(3).getTier(), 2);
    assertEquals(itemDetails.get(3).getAmount().compareTo(new BigDecimal("500")), 0);
    assertEquals(itemDetails.get(3).getQuantity().intValue(), 50);
    assertEquals(itemDetails.get(3).getTierPrice().compareTo(BigDecimal.TEN), 0);
    // FOO: 15 * 100 = 1500
    assertEquals(itemDetails.get(4).getTierUnit(), "FOO");
    assertEquals(itemDetails.get(4).getTier(), 3);
    assertEquals(itemDetails.get(4).getAmount().compareTo(new BigDecimal("1500")), 0);
    assertEquals(itemDetails.get(4).getQuantity().intValue(), 15);
    assertEquals(itemDetails.get(4).getTierPrice().compareTo(new BigDecimal("100.0")), 0);
}
Also used : UsageConsumableInArrearAggregate(org.killbill.billing.invoice.usage.details.UsageConsumableInArrearAggregate) FixedPriceInvoiceItem(org.killbill.billing.invoice.model.FixedPriceInvoiceItem) UsageInvoiceItem(org.killbill.billing.invoice.model.UsageInvoiceItem) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) ArrayList(java.util.ArrayList) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal) RawUsageRecord(org.killbill.billing.usage.api.RawUsageRecord) UsageConsumableInArrearTierUnitAggregate(org.killbill.billing.invoice.usage.details.UsageConsumableInArrearTierUnitAggregate) DefaultRawUsage(org.killbill.billing.usage.api.svcs.DefaultRawUsage) TypeReference(com.fasterxml.jackson.core.type.TypeReference) Test(org.testng.annotations.Test)

Example 14 with RawUsageRecord

use of org.killbill.billing.usage.api.RawUsageRecord in project killbill by killbill.

the class TestContiguousIntervalConsumableInArrear method testComputeMissingItems.

@Test(groups = "fast")
public void testComputeMissingItems() throws Exception {
    final LocalDate startDate = new LocalDate(2014, 03, 20);
    final LocalDate firstBCDDate = new LocalDate(2014, 04, 15);
    final LocalDate endDate = new LocalDate(2014, 05, 15);
    // 2 items for startDate - firstBCDDate
    final List<RawUsageRecord> rawUsageRecords = new ArrayList<RawUsageRecord>();
    rawUsageRecords.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "unit", 130L, "tracking-1"));
    rawUsageRecords.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "unit", 271L, "tracking-1"));
    // 1 items for firstBCDDate - endDate
    rawUsageRecords.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 04, 15), "unit", 199L, "tracking-2"));
    final DefaultTieredBlock block = createDefaultTieredBlock("unit", 100, 10, BigDecimal.ONE);
    final DefaultTier tier = createDefaultTierWithBlocks(block);
    final DefaultUsage usage = createConsumableInArrearUsage(usageName, BillingPeriod.MONTHLY, TierBlockPolicy.ALL_TIERS, tier);
    final LocalDate targetDate = endDate;
    final BillingEvent event1 = createMockBillingEvent(startDate.toDateTimeAtStartOfDay(DateTimeZone.UTC), BillingPeriod.MONTHLY, Collections.<Usage>emptyList(), catalogEffectiveDate);
    final BillingEvent event2 = createMockBillingEvent(endDate.toDateTimeAtStartOfDay(DateTimeZone.UTC), BillingPeriod.MONTHLY, Collections.<Usage>emptyList(), catalogEffectiveDate);
    final ContiguousIntervalUsageInArrear intervalConsumableInArrear = createContiguousIntervalConsumableInArrear(usage, rawUsageRecords, targetDate, true, event1, event2);
    final List<InvoiceItem> invoiceItems = new ArrayList<InvoiceItem>();
    final InvoiceItem ii1 = new UsageInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, productName, planName, phaseName, usage.getName(), null, startDate, firstBCDDate, BigDecimal.ONE, currency);
    invoiceItems.add(ii1);
    final InvoiceItem ii2 = new UsageInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, productName, planName, phaseName, usage.getName(), null, firstBCDDate, endDate, BigDecimal.ONE, currency);
    invoiceItems.add(ii2);
    final UsageInArrearItemsAndNextNotificationDate usageResult = intervalConsumableInArrear.computeMissingItemsAndNextNotificationDate(invoiceItems);
    checkTrackingIds(rawUsageRecords, usageResult.getTrackingIds());
    final List<InvoiceItem> result = usageResult.getInvoiceItems();
    assertEquals(result.size(), 2);
    // Invoiced for 1 USD and used 130 + 271 = 401 => 5 blocks => 5 USD so remaining piece should be 4 USD
    assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("4.0")), 0, String.format("%s != 4.0", result.get(0).getAmount()));
    assertEquals(result.get(0).getCurrency(), Currency.USD);
    assertEquals(result.get(0).getAccountId(), accountId);
    assertEquals(result.get(0).getBundleId(), bundleId);
    assertEquals(result.get(0).getSubscriptionId(), subscriptionId);
    assertEquals(result.get(0).getPlanName(), planName);
    assertEquals(result.get(0).getPhaseName(), phaseName);
    assertEquals(result.get(0).getUsageName(), usage.getName());
    assertTrue(result.get(0).getStartDate().compareTo(startDate) == 0);
    assertTrue(result.get(0).getEndDate().compareTo(firstBCDDate) == 0);
    assertNotNull(result.get(0).getItemDetails());
    UsageConsumableInArrearAggregate usageDetail = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<UsageConsumableInArrearAggregate>() {
    });
    List<UsageConsumableInArrearTierUnitAggregate> itemDetails = usageDetail.getTierDetails();
    assertEquals(itemDetails.size(), 1);
    // Because we did not have the details before, the new details don't take into account the
    assertEquals(itemDetails.get(0).getAmount().compareTo(new BigDecimal("5.0")), 0);
    // Invoiced for 1 USD and used 199  => 2 blocks => 2 USD so remaining piece should be 1 USD
    assertEquals(result.get(1).getAmount().compareTo(new BigDecimal("1.0")), 0, String.format("%s != 1.0", result.get(0).getAmount()));
    assertEquals(result.get(1).getCurrency(), Currency.USD);
    assertEquals(result.get(1).getAccountId(), accountId);
    assertEquals(result.get(1).getBundleId(), bundleId);
    assertEquals(result.get(1).getSubscriptionId(), subscriptionId);
    assertEquals(result.get(1).getPlanName(), planName);
    assertEquals(result.get(1).getPhaseName(), phaseName);
    assertEquals(result.get(1).getUsageName(), usage.getName());
    assertTrue(result.get(1).getStartDate().compareTo(firstBCDDate) == 0);
    assertTrue(result.get(1).getEndDate().compareTo(endDate) == 0);
    assertNotNull(result.get(1).getItemDetails());
    usageDetail = objectMapper.readValue(result.get(1).getItemDetails(), new TypeReference<UsageConsumableInArrearAggregate>() {
    });
    itemDetails = usageDetail.getTierDetails();
    assertEquals(itemDetails.size(), 1);
    assertEquals(itemDetails.get(0).getAmount().compareTo(new BigDecimal("2.0")), 0);
}
Also used : UsageConsumableInArrearAggregate(org.killbill.billing.invoice.usage.details.UsageConsumableInArrearAggregate) FixedPriceInvoiceItem(org.killbill.billing.invoice.model.FixedPriceInvoiceItem) UsageInvoiceItem(org.killbill.billing.invoice.model.UsageInvoiceItem) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) UsageInvoiceItem(org.killbill.billing.invoice.model.UsageInvoiceItem) ArrayList(java.util.ArrayList) DefaultTieredBlock(org.killbill.billing.catalog.DefaultTieredBlock) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal) RawUsageRecord(org.killbill.billing.usage.api.RawUsageRecord) UsageConsumableInArrearTierUnitAggregate(org.killbill.billing.invoice.usage.details.UsageConsumableInArrearTierUnitAggregate) UsageInArrearItemsAndNextNotificationDate(org.killbill.billing.invoice.usage.ContiguousIntervalUsageInArrear.UsageInArrearItemsAndNextNotificationDate) DefaultRawUsage(org.killbill.billing.usage.api.svcs.DefaultRawUsage) DefaultUsage(org.killbill.billing.catalog.DefaultUsage) BillingEvent(org.killbill.billing.junction.BillingEvent) TypeReference(com.fasterxml.jackson.core.type.TypeReference) DefaultTier(org.killbill.billing.catalog.DefaultTier) Test(org.testng.annotations.Test)

Example 15 with RawUsageRecord

use of org.killbill.billing.usage.api.RawUsageRecord in project killbill by killbill.

the class TestContiguousIntervalConsumableInArrear method testGetRolledUpUsageOnlyUsageBeforeTransitionTime.

@Test(groups = "fast")
public void testGetRolledUpUsageOnlyUsageBeforeTransitionTime() throws Exception {
    final DefaultTieredBlock tieredBlock1 = createDefaultTieredBlock("unit", 100, 1000, BigDecimal.ONE);
    final DefaultTieredBlock tieredBlock2 = createDefaultTieredBlock("unit2", 10, 1000, BigDecimal.ONE);
    final DefaultTier tier = createDefaultTierWithBlocks(tieredBlock1, tieredBlock2);
    final DefaultUsage usage = createConsumableInArrearUsage(usageName, BillingPeriod.MONTHLY, TierBlockPolicy.ALL_TIERS, tier);
    final LocalDate t0 = new LocalDate(2015, 03, BCD);
    final BillingEvent eventT0 = createMockBillingEvent(t0.toDateTimeAtStartOfDay(DateTimeZone.UTC), BillingPeriod.MONTHLY, Collections.<Usage>emptyList(), catalogEffectiveDate);
    final LocalDate t1 = new LocalDate(2015, 04, BCD);
    final BillingEvent eventT1 = createMockBillingEvent(t1.toDateTimeAtStartOfDay(DateTimeZone.UTC), BillingPeriod.MONTHLY, Collections.<Usage>emptyList(), catalogEffectiveDate);
    final LocalDate targetDate = t1;
    // Prev t0
    final RawUsageRecord raw1 = new DefaultRawUsage(subscriptionId, new LocalDate(2015, 03, 01), "unit", 12L, "tracking-1");
    final List<RawUsageRecord> rawUsageRecord = ImmutableList.of(raw1);
    final ContiguousIntervalUsageInArrear intervalConsumableInArrear = createContiguousIntervalConsumableInArrear(usage, rawUsageRecord, targetDate, true, eventT0, eventT1);
    final List<RolledUpUsageWithMetadata> unsortedRolledUpUsage = intervalConsumableInArrear.getRolledUpUsage().getUsage();
    assertEquals(unsortedRolledUpUsage.size(), 2);
    assertEquals(unsortedRolledUpUsage.get(0).getRolledUpUnits().size(), 1);
    assertEquals(unsortedRolledUpUsage.get(0).getRolledUpUnits().get(0).getAmount().longValue(), 0L);
    assertEquals(unsortedRolledUpUsage.get(1).getRolledUpUnits().size(), 1);
    assertEquals(unsortedRolledUpUsage.get(1).getRolledUpUnits().get(0).getAmount().longValue(), 0L);
}
Also used : RawUsageRecord(org.killbill.billing.usage.api.RawUsageRecord) DefaultUsage(org.killbill.billing.catalog.DefaultUsage) BillingEvent(org.killbill.billing.junction.BillingEvent) DefaultRawUsage(org.killbill.billing.usage.api.svcs.DefaultRawUsage) DefaultTieredBlock(org.killbill.billing.catalog.DefaultTieredBlock) DefaultTier(org.killbill.billing.catalog.DefaultTier) LocalDate(org.joda.time.LocalDate) Test(org.testng.annotations.Test)

Aggregations

RawUsageRecord (org.killbill.billing.usage.api.RawUsageRecord)23 LocalDate (org.joda.time.LocalDate)19 ArrayList (java.util.ArrayList)16 DefaultRawUsage (org.killbill.billing.usage.api.svcs.DefaultRawUsage)16 Test (org.testng.annotations.Test)15 BigDecimal (java.math.BigDecimal)11 InvoiceItem (org.killbill.billing.invoice.api.InvoiceItem)11 FixedPriceInvoiceItem (org.killbill.billing.invoice.model.FixedPriceInvoiceItem)11 UsageInvoiceItem (org.killbill.billing.invoice.model.UsageInvoiceItem)11 DefaultTier (org.killbill.billing.catalog.DefaultTier)8 DefaultUsage (org.killbill.billing.catalog.DefaultUsage)8 BillingEvent (org.killbill.billing.junction.BillingEvent)8 DefaultTieredBlock (org.killbill.billing.catalog.DefaultTieredBlock)7 UsageConsumableInArrearTierUnitAggregate (org.killbill.billing.invoice.usage.details.UsageConsumableInArrearTierUnitAggregate)5 TypeReference (com.fasterxml.jackson.core.type.TypeReference)4 TrackingRecordId (org.killbill.billing.invoice.generator.InvoiceWithMetadata.TrackingRecordId)4 UsageConsumableInArrearAggregate (org.killbill.billing.invoice.usage.details.UsageConsumableInArrearAggregate)4 RolledUpUnit (org.killbill.billing.usage.api.RolledUpUnit)4 HashMap (java.util.HashMap)3 InternalTenantContext (org.killbill.billing.callcontext.InternalTenantContext)3