Search in sources :

Example 6 with Tag

use of org.killbill.billing.util.tag.Tag in project killbill by killbill.

the class TestAccountDao method testTags.

@Test(groups = "slow", description = "Test Account DAO: tags")
public void testTags() throws TagApiException, TagDefinitionApiException {
    final AccountModelDao account = createTestAccount();
    final TagDefinitionModelDao tagDefinition = tagDefinitionDao.create(UUID.randomUUID().toString().substring(0, 4), UUID.randomUUID().toString(), internalCallContext);
    final Tag tag = new DescriptiveTag(tagDefinition.getId(), ObjectType.ACCOUNT, account.getId(), internalCallContext.getCreatedDate());
    tagDao.create(new TagModelDao(tag), internalCallContext);
    final List<TagModelDao> tags = tagDao.getTagsForObject(account.getId(), ObjectType.ACCOUNT, false, internalCallContext);
    Assert.assertEquals(tags.size(), 1);
    Assert.assertEquals(tags.get(0).getTagDefinitionId(), tagDefinition.getId());
    Assert.assertEquals(tags.get(0).getObjectId(), account.getId());
    Assert.assertEquals(tags.get(0).getObjectType(), ObjectType.ACCOUNT);
}
Also used : TagModelDao(org.killbill.billing.util.tag.dao.TagModelDao) TagDefinitionModelDao(org.killbill.billing.util.tag.dao.TagDefinitionModelDao) DescriptiveTag(org.killbill.billing.util.tag.DescriptiveTag) Tag(org.killbill.billing.util.tag.Tag) DescriptiveTag(org.killbill.billing.util.tag.DescriptiveTag) Test(org.testng.annotations.Test)

Example 7 with Tag

use of org.killbill.billing.util.tag.Tag in project killbill by killbill.

the class AccountResource method getAllTags.

@TimedResource
@GET
@Path("/{accountId:" + UUID_PATTERN + "}/" + ALL_TAGS)
@Produces(APPLICATION_JSON)
@ApiOperation(value = "Retrieve account tags", response = TagJson.class, responseContainer = "List")
@ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid account id supplied"), @ApiResponse(code = 404, message = "Account not found") })
public Response getAllTags(@PathParam(ID_PARAM_NAME) final String accountIdString, @QueryParam(QUERY_OBJECT_TYPE) final ObjectType objectType, @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode, @QueryParam(QUERY_INCLUDED_DELETED) @DefaultValue("false") final Boolean includedDeleted, @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException {
    final UUID accountId = UUID.fromString(accountIdString);
    final TenantContext tenantContext = context.createContext(request);
    final List<Tag> tags = objectType != null ? tagUserApi.getTagsForAccountType(accountId, objectType, includedDeleted, tenantContext) : tagUserApi.getTagsForAccount(accountId, includedDeleted, tenantContext);
    return createTagResponse(accountId, tags, auditMode, tenantContext);
}
Also used : TenantContext(org.killbill.billing.util.callcontext.TenantContext) Tag(org.killbill.billing.util.tag.Tag) MetricTag(org.killbill.commons.metrics.MetricTag) UUID(java.util.UUID) Path(javax.ws.rs.Path) TimedResource(org.killbill.commons.metrics.TimedResource) Produces(javax.ws.rs.Produces) GET(javax.ws.rs.GET) ApiOperation(io.swagger.annotations.ApiOperation) ApiResponses(io.swagger.annotations.ApiResponses)

Example 8 with Tag

use of org.killbill.billing.util.tag.Tag in project killbill by killbill.

the class AdminResource method triggerInvoiceGenerationForParkedAccounts.

@POST
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
@Path("/invoices")
@ApiOperation(value = "Trigger an invoice generation for all parked accounts")
@ApiResponses(value = {})
public Response triggerInvoiceGenerationForParkedAccounts(@QueryParam(QUERY_SEARCH_OFFSET) @DefaultValue("0") final Long offset, @QueryParam(QUERY_SEARCH_LIMIT) @DefaultValue("100") final Long limit, @HeaderParam(HDR_CREATED_BY) final String createdBy, @HeaderParam(HDR_REASON) final String reason, @HeaderParam(HDR_COMMENT) final String comment, @javax.ws.rs.core.Context final HttpServletRequest request) {
    final CallContext callContext = context.createContext(createdBy, reason, comment, request);
    // TODO Consider adding a real invoice API post 0.18.x
    final Pagination<Tag> tags = tagUserApi.searchTags(SystemTags.PARK_TAG_DEFINITION_NAME, offset, limit, callContext);
    final Iterator<Tag> iterator = tags.iterator();
    final StreamingOutput json = new StreamingOutput() {

        @Override
        public void write(final OutputStream output) throws IOException, WebApplicationException {
            try {
                final JsonGenerator generator = mapper.getFactory().createGenerator(output);
                generator.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
                generator.writeStartObject();
                while (iterator.hasNext()) {
                    final Tag tag = iterator.next();
                    final UUID accountId = tag.getObjectId();
                    try {
                        invoiceUserApi.triggerInvoiceGeneration(accountId, clock.getUTCToday(), null, callContext);
                        generator.writeStringField(accountId.toString(), OK);
                    } catch (final InvoiceApiException e) {
                        if (e.getCode() != ErrorCode.INVOICE_NOTHING_TO_DO.getCode()) {
                            log.warn("Unable to trigger invoice generation for accountId='{}'", accountId);
                        }
                        generator.writeStringField(accountId.toString(), ErrorCode.fromCode(e.getCode()).toString());
                    }
                }
                generator.writeEndObject();
                generator.close();
            } finally {
                // In case the client goes away (IOException), make sure to close the underlying DB connection
                while (iterator.hasNext()) {
                    iterator.next();
                }
            }
        }
    };
    final URI nextPageUri = uriBuilder.nextPage(AdminResource.class, "triggerInvoiceGenerationForParkedAccounts", tags.getNextOffset(), limit, ImmutableMap.<String, String>of());
    return Response.status(Status.OK).entity(json).header(HDR_PAGINATION_CURRENT_OFFSET, tags.getCurrentOffset()).header(HDR_PAGINATION_NEXT_OFFSET, tags.getNextOffset()).header(HDR_PAGINATION_TOTAL_NB_RECORDS, tags.getTotalNbRecords()).header(HDR_PAGINATION_MAX_NB_RECORDS, tags.getMaxNbRecords()).header(HDR_PAGINATION_NEXT_PAGE_URI, nextPageUri).build();
}
Also used : InvoiceApiException(org.killbill.billing.invoice.api.InvoiceApiException) OutputStream(java.io.OutputStream) JsonGenerator(com.fasterxml.jackson.core.JsonGenerator) StreamingOutput(javax.ws.rs.core.StreamingOutput) Tag(org.killbill.billing.util.tag.Tag) UUID(java.util.UUID) CallContext(org.killbill.billing.util.callcontext.CallContext) URI(java.net.URI) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces) ApiOperation(io.swagger.annotations.ApiOperation) ApiResponses(io.swagger.annotations.ApiResponses)

Example 9 with Tag

use of org.killbill.billing.util.tag.Tag in project killbill by killbill.

the class DefaultInvoiceDao method deleteCBA.

@Override
public void deleteCBA(final UUID accountId, final UUID invoiceId, final UUID invoiceItemId, final InternalCallContext context) throws InvoiceApiException {
    final List<Tag> invoicesTags = getInvoicesTags(context);
    transactionalSqlDao.execute(InvoiceApiException.class, new EntitySqlDaoTransactionWrapper<Void>() {

        @Override
        public Void inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
            final InvoiceSqlDao transactional = entitySqlDaoWrapperFactory.become(InvoiceSqlDao.class);
            // Retrieve the invoice and make sure it belongs to the right account
            final InvoiceModelDao invoice = transactional.getById(invoiceId.toString(), context);
            if (invoice == null || !invoice.getAccountId().equals(accountId)) {
                throw new InvoiceApiException(ErrorCode.INVOICE_NOT_FOUND, invoiceId);
            }
            // Retrieve the invoice item and make sure it belongs to the right invoice
            final InvoiceItemSqlDao invoiceItemSqlDao = entitySqlDaoWrapperFactory.become(InvoiceItemSqlDao.class);
            final InvoiceItemModelDao cbaItem = invoiceItemSqlDao.getById(invoiceItemId.toString(), context);
            if (cbaItem == null || !cbaItem.getInvoiceId().equals(invoice.getId())) {
                throw new InvoiceApiException(ErrorCode.INVOICE_ITEM_NOT_FOUND, invoiceItemId);
            }
            // First, adjust the same invoice with the CBA amount to "delete"
            final InvoiceItemModelDao cbaAdjItem = new InvoiceItemModelDao(context.getCreatedDate(), InvoiceItemType.CBA_ADJ, invoice.getId(), invoice.getAccountId(), null, null, null, null, null, null, context.getCreatedDate().toLocalDate(), null, cbaItem.getAmount().negate(), null, cbaItem.getCurrency(), cbaItem.getId());
            createInvoiceItemFromTransaction(invoiceItemSqlDao, cbaAdjItem, context);
            // Verify the final invoice balance is not negative
            invoiceDaoHelper.populateChildren(invoice, invoicesTags, entitySqlDaoWrapperFactory, context);
            if (InvoiceModelDaoHelper.getBalance(invoice).compareTo(BigDecimal.ZERO) < 0) {
                throw new InvoiceApiException(ErrorCode.INVOICE_WOULD_BE_NEGATIVE);
            }
            // If there is more account credit than CBA we adjusted, we're done.
            // Otherwise, we need to find further invoices on which this credit was consumed
            final BigDecimal accountCBA = cbaDao.getAccountCBAFromTransaction(entitySqlDaoWrapperFactory, context);
            if (accountCBA.compareTo(BigDecimal.ZERO) < 0) {
                if (accountCBA.compareTo(cbaItem.getAmount().negate()) < 0) {
                    throw new IllegalStateException("The account balance can't be lower than the amount adjusted");
                }
                final List<InvoiceModelDao> invoicesFollowing = getAllNonMigratedInvoicesByAccountAfterDate(transactional, invoice.getInvoiceDate(), context);
                invoiceDaoHelper.populateChildren(invoicesFollowing, invoicesTags, entitySqlDaoWrapperFactory, context);
                // The remaining amount to adjust (i.e. the amount of credits used on following invoices)
                // is the current account CBA balance (minus the sign)
                BigDecimal positiveRemainderToAdjust = accountCBA.negate();
                for (final InvoiceModelDao invoiceFollowing : invoicesFollowing) {
                    if (invoiceFollowing.getId().equals(invoice.getId())) {
                        continue;
                    }
                    // Add a single adjustment per invoice
                    BigDecimal positiveCBAAdjItemAmount = BigDecimal.ZERO;
                    for (final InvoiceItemModelDao cbaUsed : invoiceFollowing.getInvoiceItems()) {
                        // Ignore non CBA items or credits (CBA >= 0)
                        if (!InvoiceItemType.CBA_ADJ.equals(cbaUsed.getType()) || cbaUsed.getAmount().compareTo(BigDecimal.ZERO) >= 0) {
                            continue;
                        }
                        final BigDecimal positiveCBAUsedAmount = cbaUsed.getAmount().negate();
                        final BigDecimal positiveNextCBAAdjItemAmount;
                        if (positiveCBAUsedAmount.compareTo(positiveRemainderToAdjust) < 0) {
                            positiveNextCBAAdjItemAmount = positiveCBAUsedAmount;
                            positiveRemainderToAdjust = positiveRemainderToAdjust.subtract(positiveNextCBAAdjItemAmount);
                        } else {
                            positiveNextCBAAdjItemAmount = positiveRemainderToAdjust;
                            positiveRemainderToAdjust = BigDecimal.ZERO;
                        }
                        positiveCBAAdjItemAmount = positiveCBAAdjItemAmount.add(positiveNextCBAAdjItemAmount);
                        if (positiveRemainderToAdjust.compareTo(BigDecimal.ZERO) == 0) {
                            break;
                        }
                    }
                    // Add the adjustment on that invoice
                    final InvoiceItemModelDao nextCBAAdjItem = new InvoiceItemModelDao(context.getCreatedDate(), InvoiceItemType.CBA_ADJ, invoiceFollowing.getId(), invoice.getAccountId(), null, null, null, null, null, null, context.getCreatedDate().toLocalDate(), null, positiveCBAAdjItemAmount, null, cbaItem.getCurrency(), cbaItem.getId());
                    createInvoiceItemFromTransaction(invoiceItemSqlDao, nextCBAAdjItem, context);
                    if (positiveRemainderToAdjust.compareTo(BigDecimal.ZERO) == 0) {
                        break;
                    }
                }
            }
            return null;
        }
    });
}
Also used : InvoiceApiException(org.killbill.billing.invoice.api.InvoiceApiException) EventBusException(org.killbill.bus.api.PersistentBus.EventBusException) EntityPersistenceException(org.killbill.billing.entity.EntityPersistenceException) BigDecimal(java.math.BigDecimal) InvoiceApiException(org.killbill.billing.invoice.api.InvoiceApiException) EntitySqlDaoWrapperFactory(org.killbill.billing.util.entity.dao.EntitySqlDaoWrapperFactory) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) LinkedList(java.util.LinkedList) Tag(org.killbill.billing.util.tag.Tag)

Example 10 with Tag

use of org.killbill.billing.util.tag.Tag in project killbill by killbill.

the class DefaultInternalBillingApi method getBillingEventsForAccountAndUpdateAccountBCD.

@Override
public BillingEventSet getBillingEventsForAccountAndUpdateAccountBCD(final UUID accountId, final DryRunArguments dryRunArguments, final InternalCallContext context) throws CatalogApiException, AccountApiException, SubscriptionBaseApiException {
    final StaticCatalog currentCatalog = catalogService.getCurrentCatalog(true, true, context);
    // Check to see if billing is off for the account
    final List<Tag> accountTags = tagApi.getTags(accountId, ObjectType.ACCOUNT, context);
    final boolean found_AUTO_INVOICING_OFF = is_AUTO_INVOICING_OFF(accountTags);
    final Set<UUID> skippedSubscriptions = new HashSet<UUID>();
    final DefaultBillingEventSet result;
    if (found_AUTO_INVOICING_OFF) {
        // billing is off, we are done
        result = new DefaultBillingEventSet(true, currentCatalog.getRecurringBillingMode());
    } else {
        final List<SubscriptionBaseBundle> bundles = subscriptionApi.getBundlesForAccount(accountId, context);
        final ImmutableAccountData account = accountApi.getImmutableAccountDataById(accountId, context);
        result = new DefaultBillingEventSet(false, currentCatalog.getRecurringBillingMode());
        addBillingEventsForBundles(bundles, account, dryRunArguments, context, result, skippedSubscriptions);
    }
    if (result.isEmpty()) {
        log.info("No billing event for accountId='{}'", accountId);
        return result;
    }
    // Pretty-print the events, before and after the blocking calculator does its magic
    final StringBuilder logStringBuilder = new StringBuilder("Computed billing events for accountId='").append(accountId).append("'");
    eventsToString(logStringBuilder, result);
    if (blockCalculator.insertBlockingEvents(result, skippedSubscriptions, context)) {
        logStringBuilder.append("\nBilling Events After Blocking");
        eventsToString(logStringBuilder, result);
    }
    log.info(logStringBuilder.toString());
    return result;
}
Also used : ImmutableAccountData(org.killbill.billing.account.api.ImmutableAccountData) SubscriptionBaseBundle(org.killbill.billing.subscription.api.user.SubscriptionBaseBundle) Tag(org.killbill.billing.util.tag.Tag) UUID(java.util.UUID) StaticCatalog(org.killbill.billing.catalog.api.StaticCatalog) HashSet(java.util.HashSet)

Aggregations

Tag (org.killbill.billing.util.tag.Tag)24 UUID (java.util.UUID)16 InvoiceApiException (org.killbill.billing.invoice.api.InvoiceApiException)8 Invoice (org.killbill.billing.invoice.api.Invoice)7 Test (org.testng.annotations.Test)6 List (java.util.List)5 ApiOperation (io.swagger.annotations.ApiOperation)4 ApiResponses (io.swagger.annotations.ApiResponses)4 BigDecimal (java.math.BigDecimal)4 HashMap (java.util.HashMap)4 Path (javax.ws.rs.Path)4 Produces (javax.ws.rs.Produces)4 DescriptiveTag (org.killbill.billing.util.tag.DescriptiveTag)4 ImmutableList (com.google.common.collect.ImmutableList)3 URI (java.net.URI)3 LinkedList (java.util.LinkedList)3 GET (javax.ws.rs.GET)3 LocalDate (org.joda.time.LocalDate)3 InternalTenantContext (org.killbill.billing.callcontext.InternalTenantContext)3 EntityPersistenceException (org.killbill.billing.entity.EntityPersistenceException)3