Search in sources :

Example 1 with UsageInArrearAggregate

use of org.killbill.billing.invoice.usage.details.UsageInArrearAggregate in project killbill by killbill.

the class ContiguousIntervalConsumableUsageInArrear method getToBeBilledUsageDetails.

@Override
protected UsageInArrearAggregate getToBeBilledUsageDetails(final LocalDate startDate, final LocalDate endDate, final List<RolledUpUnit> rolledUpUnits, final Iterable<InvoiceItem> billedItems, final boolean areAllBilledItemsWithDetails) throws CatalogApiException {
    final Map<String, List<UsageConsumableInArrearTierUnitAggregate>> previousUnitsUsage;
    if (usageDetailMode == UsageDetailMode.DETAIL || areAllBilledItemsWithDetails) {
        previousUnitsUsage = new HashMap<String, List<UsageConsumableInArrearTierUnitAggregate>>();
        for (RolledUpUnit cur : rolledUpUnits) {
            final List<UsageConsumableInArrearTierUnitAggregate> usageInArrearDetailForUnitType = getBilledDetailsForUnitType(billedItems, cur.getUnitType());
            previousUnitsUsage.put(cur.getUnitType(), usageInArrearDetailForUnitType);
        }
    } else {
        previousUnitsUsage = ImmutableMap.of();
    }
    final List<UsageConsumableInArrearTierUnitAggregate> usageConsumableInArrearTierUnitAggregates = new ArrayList<UsageConsumableInArrearTierUnitAggregate>();
    for (final RolledUpUnit cur : rolledUpUnits) {
        if (!unitTypes.contains(cur.getUnitType())) {
            log.warn("ContiguousIntervalConsumableInArrear is skipping unitType " + cur.getUnitType());
            continue;
        }
        final List<UsageConsumableInArrearTierUnitAggregate> previousUsage = previousUnitsUsage.containsKey(cur.getUnitType()) ? previousUnitsUsage.get(cur.getUnitType()) : ImmutableList.<UsageConsumableInArrearTierUnitAggregate>of();
        final List<UsageConsumableInArrearTierUnitAggregate> toBeBilledConsumableInArrear = computeToBeBilledConsumableInArrear(startDate, endDate, cur, previousUsage);
        usageConsumableInArrearTierUnitAggregates.addAll(toBeBilledConsumableInArrear);
    }
    final UsageInArrearAggregate toBeBilledUsageDetails = new UsageConsumableInArrearAggregate(usageConsumableInArrearTierUnitAggregates);
    return toBeBilledUsageDetails;
}
Also used : UsageConsumableInArrearAggregate(org.killbill.billing.invoice.usage.details.UsageConsumableInArrearAggregate) RolledUpUnit(org.killbill.billing.usage.api.RolledUpUnit) UsageInArrearAggregate(org.killbill.billing.invoice.usage.details.UsageInArrearAggregate) UsageConsumableInArrearTierUnitAggregate(org.killbill.billing.invoice.usage.details.UsageConsumableInArrearTierUnitAggregate) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List)

Example 2 with UsageInArrearAggregate

use of org.killbill.billing.invoice.usage.details.UsageInArrearAggregate in project killbill by killbill.

the class ContiguousIntervalUsageInArrear method computeMissingItemsAndNextNotificationDate.

/**
 * Compute the missing usage invoice items based on what should be billed and what has been billed ($ amount comparison).
 *
 * @param existingUsage existing on disk usage items for the subscription
 * @throws CatalogApiException
 */
public UsageInArrearItemsAndNextNotificationDate computeMissingItemsAndNextNotificationDate(final List<InvoiceItem> existingUsage) throws CatalogApiException, InvoiceApiException {
    Preconditions.checkState(isBuilt.get());
    if (transitionTimes.size() < 2) {
        return new UsageInArrearItemsAndNextNotificationDate(ImmutableList.<InvoiceItem>of(), ImmutableSet.of(), computeNextNotificationDate());
    }
    final List<InvoiceItem> result = Lists.newLinkedList();
    final RolledUpUnitsWithTracking allUsageWithTracking = getRolledUpUsage();
    final List<RolledUpUsageWithMetadata> allUsage = allUsageWithTracking.getUsage();
    final Set<TrackingRecordId> allTrackingIds = allUsageWithTracking.getTrackingIds();
    final Set<TrackingRecordId> existingTrackingIds = extractTrackingIds(allExistingTrackingIds);
    final Set<TrackingRecordId> newTrackingIds = Sets.filter(allTrackingIds, new Predicate<TrackingRecordId>() {

        @Override
        public boolean apply(final TrackingRecordId allRecord) {
            return !Iterables.any(existingTrackingIds, new Predicate<TrackingRecordId>() {

                @Override
                public boolean apply(final TrackingRecordId existingRecord) {
                    return existingRecord.isSimilarRecord(allRecord);
                }
            });
        }
    });
    // Each RolledUpUsage 'ru' is for a specific time period and across all units
    for (final RolledUpUsageWithMetadata ru : allUsage) {
        final InvoiceItem existingOverlappingItem = isContainedIntoExistingUsage(ru.getStart(), ru.getEnd(), existingUsage);
        if (existingOverlappingItem != null) {
            // In case of blocking situations, when re-running the invoicing code, already billed usage maybe have another start and end date
            // because of blocking events. We need to skip these to avoid double billing (see gotchas in testWithPartialBlockBilling).
            log.warn("Ignoring usage {} between start={} and end={} as it has already been invoiced by invoiceItemId={}", usage.getName(), ru.getStart(), ru.getEnd(), existingOverlappingItem.getId());
            continue;
        }
        // 
        // Previously billed items:
        // 
        // 1. Retrieves current price amount billed for that period of time (and usage section)
        final Iterable<InvoiceItem> billedItems = getBilledItems(ru.getStart(), ru.getEnd(), existingUsage);
        // 2. Verify whether previously built items have the item_details section
        final boolean areAllBilledItemsWithDetails = areAllBilledItemsWithDetails(billedItems);
        // 3. verify if we already billed that period - use to decide whether we should include $0 items when there is nothing to bill for.
        final boolean isPeriodPreviouslyBilled = !Iterables.isEmpty(billedItems);
        // 4. Computes total billed usage amount
        final BigDecimal billedUsage = computeBilledUsage(billedItems);
        final List<RolledUpUnit> rolledUpUnits = ru.getRolledUpUnits();
        final UsageInArrearAggregate toBeBilledUsageDetails = getToBeBilledUsageDetails(ru.getStart(), ru.getEnd(), rolledUpUnits, billedItems, areAllBilledItemsWithDetails);
        final BigDecimal toBeBilledUsageUnrounded = toBeBilledUsageDetails.getAmount();
        // See https://github.com/killbill/killbill/issues/1124
        final BigDecimal toBeBilledUsage = KillBillMoney.of(toBeBilledUsageUnrounded, getCurrency());
        populateResults(ru.getStart(), ru.getEnd(), ru.getCatalogEffectiveDate(), billedUsage, toBeBilledUsage, toBeBilledUsageDetails, areAllBilledItemsWithDetails, isPeriodPreviouslyBilled, result);
    }
    final LocalDate nextNotificationDate = computeNextNotificationDate();
    return new UsageInArrearItemsAndNextNotificationDate(result, newTrackingIds, nextNotificationDate);
}
Also used : TrackingRecordId(org.killbill.billing.invoice.generator.InvoiceWithMetadata.TrackingRecordId) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) UsageInvoiceItem(org.killbill.billing.invoice.model.UsageInvoiceItem) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal) RolledUpUnit(org.killbill.billing.usage.api.RolledUpUnit) UsageInArrearAggregate(org.killbill.billing.invoice.usage.details.UsageInArrearAggregate)

Aggregations

UsageInArrearAggregate (org.killbill.billing.invoice.usage.details.UsageInArrearAggregate)2 RolledUpUnit (org.killbill.billing.usage.api.RolledUpUnit)2 ImmutableList (com.google.common.collect.ImmutableList)1 BigDecimal (java.math.BigDecimal)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 LocalDate (org.joda.time.LocalDate)1 InvoiceItem (org.killbill.billing.invoice.api.InvoiceItem)1 TrackingRecordId (org.killbill.billing.invoice.generator.InvoiceWithMetadata.TrackingRecordId)1 UsageInvoiceItem (org.killbill.billing.invoice.model.UsageInvoiceItem)1 UsageConsumableInArrearAggregate (org.killbill.billing.invoice.usage.details.UsageConsumableInArrearAggregate)1 UsageConsumableInArrearTierUnitAggregate (org.killbill.billing.invoice.usage.details.UsageConsumableInArrearTierUnitAggregate)1