Search in sources :

Example 41 with InternalCallContext

use of org.killbill.billing.callcontext.InternalCallContext in project killbill by killbill.

the class InvoiceDispatcher method processParentInvoiceForInvoiceGenerationWithLock.

private void processParentInvoiceForInvoiceGenerationWithLock(final Account childAccount, final UUID childInvoiceId, final InternalCallContext context) throws InvoiceApiException {
    log.info("Processing parent invoice for parentAccountId='{}', childInvoiceId='{}'", childAccount.getParentAccountId(), childInvoiceId);
    final InvoiceModelDao childInvoiceModelDao = invoiceDao.getById(childInvoiceId, context);
    final Invoice childInvoice = new DefaultInvoice(childInvoiceModelDao);
    final Long parentAccountRecordId = internalCallContextFactory.getRecordIdFromObject(childAccount.getParentAccountId(), ObjectType.ACCOUNT, buildTenantContext(context));
    final InternalCallContext parentContext = internalCallContextFactory.createInternalCallContext(parentAccountRecordId, context);
    BigDecimal childInvoiceAmount = InvoiceCalculatorUtils.computeChildInvoiceAmount(childInvoice.getCurrency(), childInvoice.getInvoiceItems());
    InvoiceModelDao draftParentInvoice = invoiceDao.getParentDraftInvoice(childAccount.getParentAccountId(), parentContext);
    final String description = childAccount.getExternalKey().concat(" summary");
    if (draftParentInvoice != null) {
        for (InvoiceItemModelDao item : draftParentInvoice.getInvoiceItems()) {
            if ((item.getChildAccountId() != null) && item.getChildAccountId().equals(childInvoice.getAccountId())) {
                // update child item amount for existing parent invoice item
                BigDecimal newChildInvoiceAmount = childInvoiceAmount.add(item.getAmount());
                log.info("Updating existing itemId='{}', oldAmount='{}', newAmount='{}' on existing DRAFT invoiceId='{}'", item.getId(), item.getAmount(), newChildInvoiceAmount, draftParentInvoice.getId());
                invoiceDao.updateInvoiceItemAmount(item.getId(), newChildInvoiceAmount, parentContext);
                return;
            }
        }
        // new item when the parent invoices does not have this child item yet
        final ParentInvoiceItem newParentInvoiceItem = new ParentInvoiceItem(UUID.randomUUID(), context.getCreatedDate(), draftParentInvoice.getId(), childAccount.getParentAccountId(), childAccount.getId(), childInvoiceAmount, childAccount.getCurrency(), description);
        final InvoiceItemModelDao parentInvoiceItem = new InvoiceItemModelDao(newParentInvoiceItem);
        draftParentInvoice.addInvoiceItem(parentInvoiceItem);
        List<InvoiceModelDao> invoices = new ArrayList<InvoiceModelDao>();
        invoices.add(draftParentInvoice);
        log.info("Adding new itemId='{}', amount='{}' on existing DRAFT invoiceId='{}'", parentInvoiceItem.getId(), childInvoiceAmount, draftParentInvoice.getId());
        invoiceDao.createInvoices(invoices, parentContext);
    } else {
        if (shouldIgnoreChildInvoice(childInvoice, childInvoiceAmount)) {
            return;
        }
        final LocalDate invoiceDate = context.toLocalDate(context.getCreatedDate());
        draftParentInvoice = new InvoiceModelDao(childAccount.getParentAccountId(), invoiceDate, childAccount.getCurrency(), InvoiceStatus.DRAFT, true);
        final InvoiceItem parentInvoiceItem = new ParentInvoiceItem(UUID.randomUUID(), context.getCreatedDate(), draftParentInvoice.getId(), childAccount.getParentAccountId(), childAccount.getId(), childInvoiceAmount, childAccount.getCurrency(), description);
        draftParentInvoice.addInvoiceItem(new InvoiceItemModelDao(parentInvoiceItem));
        log.info("Adding new itemId='{}', amount='{}' on new DRAFT invoiceId='{}'", parentInvoiceItem.getId(), childInvoiceAmount, draftParentInvoice.getId());
        invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(draftParentInvoice), parentContext);
    }
    // save parent child invoice relation
    final InvoiceParentChildModelDao invoiceRelation = new InvoiceParentChildModelDao(draftParentInvoice.getId(), childInvoiceId, childAccount.getId());
    invoiceDao.createParentChildInvoiceRelation(invoiceRelation, parentContext);
}
Also used : DefaultInvoice(org.killbill.billing.invoice.model.DefaultInvoice) Invoice(org.killbill.billing.invoice.api.Invoice) RecurringInvoiceItem(org.killbill.billing.invoice.model.RecurringInvoiceItem) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) ItemAdjInvoiceItem(org.killbill.billing.invoice.model.ItemAdjInvoiceItem) FixedPriceInvoiceItem(org.killbill.billing.invoice.model.FixedPriceInvoiceItem) ParentInvoiceItem(org.killbill.billing.invoice.model.ParentInvoiceItem) InvoiceModelDao(org.killbill.billing.invoice.dao.InvoiceModelDao) ArrayList(java.util.ArrayList) ParentInvoiceItem(org.killbill.billing.invoice.model.ParentInvoiceItem) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal) InvoiceItemModelDao(org.killbill.billing.invoice.dao.InvoiceItemModelDao) InvoiceParentChildModelDao(org.killbill.billing.invoice.dao.InvoiceParentChildModelDao) DefaultInvoice(org.killbill.billing.invoice.model.DefaultInvoice)

Example 42 with InternalCallContext

use of org.killbill.billing.callcontext.InternalCallContext in project killbill by killbill.

the class InvoiceDispatcher method processParentInvoiceForAdjustmentsWithLock.

public void processParentInvoiceForAdjustmentsWithLock(final Account account, final UUID childInvoiceId, final InternalCallContext context) throws InvoiceApiException {
    final InvoiceModelDao childInvoiceModelDao = invoiceDao.getById(childInvoiceId, context);
    final InvoiceModelDao parentInvoiceModelDao = childInvoiceModelDao.getParentInvoice();
    if (parentInvoiceModelDao == null) {
        throw new InvoiceApiException(ErrorCode.INVOICE_MISSING_PARENT_INVOICE, childInvoiceModelDao.getId());
    } else if (InvoiceModelDaoHelper.getBalance(parentInvoiceModelDao).compareTo(BigDecimal.ZERO) == 0) {
        // ignore item adjustments for paid invoices.
        return;
    }
    final Long parentAccountRecordId = internalCallContextFactory.getRecordIdFromObject(account.getParentAccountId(), ObjectType.ACCOUNT, buildTenantContext(context));
    final InternalCallContext parentContext = internalCallContextFactory.createInternalCallContext(parentAccountRecordId, context);
    final String description = "Adjustment for account ".concat(account.getExternalKey());
    // find PARENT_SUMMARY invoice item for this child account
    final InvoiceItemModelDao parentSummaryInvoiceItem = Iterables.find(parentInvoiceModelDao.getInvoiceItems(), new Predicate<InvoiceItemModelDao>() {

        @Override
        public boolean apply(@Nullable final InvoiceItemModelDao input) {
            return input.getType().equals(InvoiceItemType.PARENT_SUMMARY) && input.getChildAccountId().equals(childInvoiceModelDao.getAccountId());
        }
    });
    final Iterable<InvoiceItemModelDao> childAdjustments = Iterables.filter(childInvoiceModelDao.getInvoiceItems(), new Predicate<InvoiceItemModelDao>() {

        @Override
        public boolean apply(@Nullable final InvoiceItemModelDao input) {
            return input.getType().equals(InvoiceItemType.ITEM_ADJ);
        }
    });
    // find last ITEM_ADJ invoice added in child invoice
    final InvoiceItemModelDao lastChildInvoiceItemAdjustment = Collections.max(Lists.newArrayList(childAdjustments), new Comparator<InvoiceItemModelDao>() {

        @Override
        public int compare(InvoiceItemModelDao o1, InvoiceItemModelDao o2) {
            return o1.getCreatedDate().compareTo(o2.getCreatedDate());
        }
    });
    final BigDecimal childInvoiceAdjustmentAmount = lastChildInvoiceItemAdjustment.getAmount();
    if (parentInvoiceModelDao.getStatus().equals(InvoiceStatus.COMMITTED)) {
        ItemAdjInvoiceItem adj = new ItemAdjInvoiceItem(UUIDs.randomUUID(), lastChildInvoiceItemAdjustment.getCreatedDate(), parentSummaryInvoiceItem.getInvoiceId(), parentSummaryInvoiceItem.getAccountId(), lastChildInvoiceItemAdjustment.getStartDate(), description, childInvoiceAdjustmentAmount, parentInvoiceModelDao.getCurrency(), parentSummaryInvoiceItem.getId());
        parentInvoiceModelDao.addInvoiceItem(new InvoiceItemModelDao(adj));
        invoiceDao.createInvoices(ImmutableList.<InvoiceModelDao>of(parentInvoiceModelDao), parentContext);
        return;
    }
    // update item amount
    final BigDecimal newParentInvoiceItemAmount = childInvoiceAdjustmentAmount.add(parentSummaryInvoiceItem.getAmount());
    invoiceDao.updateInvoiceItemAmount(parentSummaryInvoiceItem.getId(), newParentInvoiceItemAmount, parentContext);
}
Also used : InvoiceApiException(org.killbill.billing.invoice.api.InvoiceApiException) InvoiceItemModelDao(org.killbill.billing.invoice.dao.InvoiceItemModelDao) InvoiceModelDao(org.killbill.billing.invoice.dao.InvoiceModelDao) ItemAdjInvoiceItem(org.killbill.billing.invoice.model.ItemAdjInvoiceItem) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) PlanPhasePriceOverride(org.killbill.billing.catalog.api.PlanPhasePriceOverride) BigDecimal(java.math.BigDecimal)

Example 43 with InternalCallContext

use of org.killbill.billing.callcontext.InternalCallContext in project killbill by killbill.

the class DefaultInvoiceUserApi method tagInvoiceAsWrittenOff.

@Override
public void tagInvoiceAsWrittenOff(final UUID invoiceId, final CallContext context) throws TagApiException, InvoiceApiException {
    // Note: the tagApi is audited
    final InternalCallContext internalContext = internalCallContextFactory.createInternalCallContext(invoiceId, ObjectType.INVOICE, context);
    tagApi.addTag(invoiceId, ObjectType.INVOICE, ControlTagType.WRITTEN_OFF.getId(), internalContext);
    // Retrieve the invoice for the account id
    final Invoice invoice = new DefaultInvoice(dao.getById(invoiceId, internalContext));
    // This is for overdue
    notifyBusOfInvoiceAdjustment(invoiceId, invoice.getAccountId(), internalContext);
}
Also used : Invoice(org.killbill.billing.invoice.api.Invoice) HtmlInvoice(org.killbill.billing.invoice.template.HtmlInvoice) DefaultInvoice(org.killbill.billing.invoice.model.DefaultInvoice) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) DefaultInvoice(org.killbill.billing.invoice.model.DefaultInvoice)

Example 44 with InternalCallContext

use of org.killbill.billing.callcontext.InternalCallContext in project killbill by killbill.

the class DefaultInvoiceUserApi method triggerInvoiceGeneration.

@Override
public Invoice triggerInvoiceGeneration(final UUID accountId, @Nullable final LocalDate targetDate, final DryRunArguments dryRunArguments, final CallContext context) throws InvoiceApiException {
    final InternalCallContext internalContext = internalCallContextFactory.createInternalCallContext(accountId, context);
    final Invoice result = dispatcher.processAccount(true, accountId, targetDate, dryRunArguments, internalContext);
    if (result == null) {
        throw new InvoiceApiException(ErrorCode.INVOICE_NOTHING_TO_DO, accountId, targetDate != null ? targetDate : "null");
    } else {
        return result;
    }
}
Also used : InvoiceApiException(org.killbill.billing.invoice.api.InvoiceApiException) Invoice(org.killbill.billing.invoice.api.Invoice) HtmlInvoice(org.killbill.billing.invoice.template.HtmlInvoice) DefaultInvoice(org.killbill.billing.invoice.model.DefaultInvoice) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext)

Example 45 with InternalCallContext

use of org.killbill.billing.callcontext.InternalCallContext in project killbill by killbill.

the class DefaultInvoiceUserApi method createMigrationInvoice.

@Override
public UUID createMigrationInvoice(final UUID accountId, final LocalDate targetDate, final Iterable<InvoiceItem> items, final CallContext context) {
    final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(accountId, context);
    final LocalDate invoiceDate = internalCallContext.toLocalDate(internalCallContext.getCreatedDate());
    final InvoiceModelDao migrationInvoice = new InvoiceModelDao(accountId, invoiceDate, targetDate, items.iterator().next().getCurrency(), true);
    final List<InvoiceItemModelDao> itemModelDaos = ImmutableList.copyOf(Iterables.transform(items, new Function<InvoiceItem, InvoiceItemModelDao>() {

        @Override
        public InvoiceItemModelDao apply(final InvoiceItem input) {
            return new InvoiceItemModelDao(internalCallContext.getCreatedDate(), input.getInvoiceItemType(), migrationInvoice.getId(), accountId, input.getBundleId(), input.getSubscriptionId(), input.getDescription(), input.getPlanName(), input.getPhaseName(), input.getUsageName(), input.getStartDate(), input.getEndDate(), input.getAmount(), input.getRate(), input.getCurrency(), input.getLinkedItemId());
        }
    }));
    migrationInvoice.addInvoiceItems(itemModelDaos);
    dao.createInvoices(ImmutableList.<InvoiceModelDao>of(migrationInvoice), internalCallContext);
    return migrationInvoice.getId();
}
Also used : Function(com.google.common.base.Function) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) ExternalChargeInvoiceItem(org.killbill.billing.invoice.model.ExternalChargeInvoiceItem) CreditAdjInvoiceItem(org.killbill.billing.invoice.model.CreditAdjInvoiceItem) InvoiceItemModelDao(org.killbill.billing.invoice.dao.InvoiceItemModelDao) InvoiceModelDao(org.killbill.billing.invoice.dao.InvoiceModelDao) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) LocalDate(org.joda.time.LocalDate)

Aggregations

InternalCallContext (org.killbill.billing.callcontext.InternalCallContext)110 PlanPhasePriceOverride (org.killbill.billing.catalog.api.PlanPhasePriceOverride)26 DateTime (org.joda.time.DateTime)25 UUID (java.util.UUID)24 ArrayList (java.util.ArrayList)21 SubscriptionBaseApiException (org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)17 InvoiceApiException (org.killbill.billing.invoice.api.InvoiceApiException)14 CallContext (org.killbill.billing.util.callcontext.CallContext)14 CatalogApiException (org.killbill.billing.catalog.api.CatalogApiException)13 WithEntitlementPlugin (org.killbill.billing.entitlement.api.EntitlementPluginExecution.WithEntitlementPlugin)13 EntitlementContext (org.killbill.billing.entitlement.plugin.api.EntitlementContext)13 AccountApiException (org.killbill.billing.account.api.AccountApiException)12 DefaultBlockingState (org.killbill.billing.junction.DefaultBlockingState)12 NotificationEvent (org.killbill.notificationq.api.NotificationEvent)9 BigDecimal (java.math.BigDecimal)8 LinkedList (java.util.LinkedList)8 InternalTenantContext (org.killbill.billing.callcontext.InternalTenantContext)8 Invoice (org.killbill.billing.invoice.api.Invoice)8 AllowConcurrentEvents (com.google.common.eventbus.AllowConcurrentEvents)7 Subscribe (com.google.common.eventbus.Subscribe)7