@Test(groups = "fast")
  public void testInvoiceAdjustment() throws Exception {
    final UUID invoiceId = UUID.randomUUID();

    Assert.assertFalse(
        BusinessInvoiceUtils.isInvoiceAdjustmentItem(
            createInvoiceItem(invoiceId, InvoiceItemType.RECURRING),
            ImmutableList.<InvoiceItem>of()));

    final InvoiceItem creditAdj = createInvoiceItem(invoiceId, InvoiceItemType.CREDIT_ADJ);

    // Account credit
    Assert.assertFalse(
        BusinessInvoiceUtils.isInvoiceAdjustmentItem(
            creditAdj,
            ImmutableList.<InvoiceItem>of(
                createInvoiceItem(
                    invoiceId, InvoiceItemType.CBA_ADJ, creditAdj.getAmount().negate()))));

    Assert.assertTrue(
        BusinessInvoiceUtils.isInvoiceAdjustmentItem(
            creditAdj,
            ImmutableList.<InvoiceItem>of(
                createInvoiceItem(
                    invoiceId,
                    InvoiceItemType.CBA_ADJ,
                    creditAdj.getAmount().negate().add(BigDecimal.ONE)))));
    Assert.assertTrue(
        BusinessInvoiceUtils.isInvoiceAdjustmentItem(
            creditAdj,
            ImmutableList.<InvoiceItem>of(
                createInvoiceItem(invoiceId, InvoiceItemType.RECURRING),
                createInvoiceItem(
                    invoiceId, InvoiceItemType.CBA_ADJ, creditAdj.getAmount().negate()))));
  }
  private void checkForTaxCodesInCustomFields(
      final Invoice invoice,
      final Collection<PluginProperty> properties,
      final TenantContext context) {
    final List<CustomField> customFields =
        killbillAPI
            .getCustomFieldUserApi()
            .getCustomFieldsForAccountType(
                invoice.getAccountId(), ObjectType.INVOICE_ITEM, context);
    if (customFields.isEmpty()) {
      return;
    }

    final Collection<UUID> invoiceItemIds = new HashSet<UUID>();
    for (final InvoiceItem invoiceItem : invoice.getInvoiceItems()) {
      invoiceItemIds.add(invoiceItem.getId());
    }

    final Iterable<CustomField> taxCodeCustomFieldsForInvoiceItems =
        Iterables.<CustomField>filter(
            customFields,
            new Predicate<CustomField>() {
              @Override
              public boolean apply(final CustomField customField) {
                return AvaTaxTaxCalculator.TAX_CODE.equals(customField.getFieldName())
                    && invoiceItemIds.contains(customField.getObjectId());
              }
            });
    for (final CustomField customField : taxCodeCustomFieldsForInvoiceItems) {
      final UUID invoiceItemId = customField.getObjectId();
      final String taxCode = customField.getFieldValue();
      addTaxCodeToInvoiceItem(invoiceItemId, taxCode, properties);
    }
  }
 protected Plan getPlanFromInvoiceItem(final InvoiceItem invoiceItem, final TenantContext context)
     throws AnalyticsRefreshException {
   try {
     final Catalog catalog = getCatalog(context);
     return catalog.findPlan(
         invoiceItem.getPlanName(), invoiceItem.getStartDate().toDateTimeAtStartOfDay());
   } catch (CatalogApiException e) {
     logService.log(
         LogService.LOG_INFO,
         "Unable to retrieve plan for invoice item " + invoiceItem.getId(),
         e);
     return null;
   }
 }
  private void checkForTaxCodesOnProducts(
      final Invoice invoice,
      final Collection<PluginProperty> properties,
      final TenantContext context) {
    final Map<String, String> planToProductCache = new HashMap<String, String>();
    final Map<String, String> productToTaxCodeCache = new HashMap<String, String>();

    for (final InvoiceItem invoiceItem : invoice.getInvoiceItems()) {
      final String planName = invoiceItem.getPlanName();
      if (planName == null) {
        continue;
      }

      if (planToProductCache.get(planName) == null) {
        try {
          final StaticCatalog catalog =
              killbillAPI.getCatalogUserApi().getCurrentCatalog(null, context);
          final Plan plan = catalog.findCurrentPlan(planName);
          planToProductCache.put(planName, plan.getProduct().getName());
        } catch (final CatalogApiException e) {
          continue;
        }
      }
      final String productName = planToProductCache.get(planName);
      if (productName == null) {
        continue;
      }

      if (productToTaxCodeCache.get(productName) == null) {
        try {
          final String taxCode = dao.getTaxCode(productName, context.getTenantId());
          productToTaxCodeCache.put(productName, taxCode);
        } catch (final SQLException e) {
          continue;
        }
      }

      final String taxCode = productToTaxCodeCache.get(productName);
      if (taxCode != null) {
        addTaxCodeToInvoiceItem(
            invoiceItem.getId(), productToTaxCodeCache.get(productName), properties);
      }
    }
  }
  private Map<UUID, List<InvoiceItem>> extractPerSubscriptionExistingConsumableInArrearUsageItems(
      final Map<String, Usage> knownUsage, @Nullable final List<Invoice> existingInvoices) {

    if (existingInvoices == null || existingInvoices.isEmpty()) {
      return ImmutableMap.of();
    }

    final Map<UUID, List<InvoiceItem>> result = new HashMap<UUID, List<InvoiceItem>>();
    final Iterable<InvoiceItem> usageConsumableInArrearItems =
        Iterables.concat(
            Iterables.transform(
                existingInvoices,
                new Function<Invoice, Iterable<InvoiceItem>>() {
                  @Override
                  public Iterable<InvoiceItem> apply(final Invoice input) {

                    return Iterables.filter(
                        input.getInvoiceItems(),
                        new Predicate<InvoiceItem>() {
                          @Override
                          public boolean apply(final InvoiceItem input) {
                            if (input.getInvoiceItemType() == InvoiceItemType.USAGE) {
                              final Usage usage = knownUsage.get(input.getUsageName());
                              return usage.getUsageType() == UsageType.CONSUMABLE
                                  && usage.getBillingMode() == BillingMode.IN_ARREAR;
                            }
                            return false;
                          }
                        });
                  }
                }));

    for (InvoiceItem cur : usageConsumableInArrearItems) {
      List<InvoiceItem> perSubscriptionUsageItems = result.get(cur.getSubscriptionId());
      if (perSubscriptionUsageItems == null) {
        perSubscriptionUsageItems = new LinkedList<InvoiceItem>();
        result.put(cur.getSubscriptionId(), perSubscriptionUsageItems);
      }
      perSubscriptionUsageItems.add(cur);
    }
    return result;
  }
 protected PlanPhase getPlanPhaseFromInvoiceItem(
     final InvoiceItem invoiceItem,
     final LocalDate subscriptionStartDate,
     final TenantContext context)
     throws AnalyticsRefreshException {
   try {
     final Catalog catalog = getCatalog(context);
     // TODO - Inaccurate timing
     return catalog.findPhase(
         invoiceItem.getPhaseName(),
         invoiceItem.getStartDate().toDateTimeAtStartOfDay(),
         subscriptionStartDate.toDateTimeAtStartOfDay());
   } catch (CatalogApiException e) {
     logService.log(
         LogService.LOG_INFO,
         "Unable to retrieve phase for invoice item " + invoiceItem.getId(),
         e);
     return null;
   }
 }
 @Override
 public Comparable apply(final InvoiceItem invoiceItem) {
   return invoiceItem.getEndDate();
 }
Esempio n. 8
0
  @Test(groups = "slow")
  public void testCreateSuccessRefundPaymentControlWithItemAdjustments()
      throws PaymentApiException, InvoiceApiException, EventBusException {

    final BigDecimal requestedAmount = BigDecimal.TEN;
    final UUID subscriptionId = UUID.randomUUID();
    final UUID bundleId = UUID.randomUUID();
    final LocalDate now = clock.getUTCToday();

    final Invoice invoice = testHelper.createTestInvoice(account, now, Currency.USD);

    final String paymentExternalKey = invoice.getId().toString();
    final String transactionExternalKey = "craboom";
    final String transactionExternalKey2 = "qwerty";

    final InvoiceItem invoiceItem =
        new MockRecurringInvoiceItem(
            invoice.getId(),
            account.getId(),
            subscriptionId,
            bundleId,
            "test plan",
            "test phase",
            null,
            now,
            now.plusMonths(1),
            requestedAmount,
            new BigDecimal("1.0"),
            Currency.USD);
    invoice.addInvoiceItem(invoiceItem);

    final Payment payment =
        paymentApi.createPurchaseWithPaymentControl(
            account,
            account.getPaymentMethodId(),
            null,
            requestedAmount,
            Currency.USD,
            paymentExternalKey,
            transactionExternalKey,
            createPropertiesForInvoice(invoice),
            INVOICE_PAYMENT,
            callContext);

    final List<PluginProperty> refundProperties = new ArrayList<PluginProperty>();
    final HashMap<UUID, BigDecimal> uuidBigDecimalHashMap = new HashMap<UUID, BigDecimal>();
    uuidBigDecimalHashMap.put(invoiceItem.getId(), new BigDecimal("1.0"));
    final PluginProperty refundIdsProp =
        new PluginProperty(
            InvoicePaymentRoutingPluginApi.PROP_IPCD_REFUND_IDS_WITH_AMOUNT_KEY,
            uuidBigDecimalHashMap,
            false);
    refundProperties.add(refundIdsProp);

    final Payment payment2 =
        paymentApi.createRefundWithPaymentControl(
            account,
            payment.getId(),
            null,
            Currency.USD,
            transactionExternalKey2,
            refundProperties,
            INVOICE_PAYMENT,
            callContext);

    assertEquals(payment2.getTransactions().size(), 2);
    PaymentTransaction refundTransaction = payment2.getTransactions().get(1);
    assertEquals(refundTransaction.getTransactionType(), TransactionType.REFUND);

    final List<PaymentAttemptModelDao> attempts =
        paymentDao.getPaymentAttempts(paymentExternalKey, internalCallContext);
    assertEquals(attempts.size(), 2);

    final PaymentAttemptModelDao refundAttempt = attempts.get(1);
    assertEquals(refundAttempt.getTransactionType(), TransactionType.REFUND);

    // Ok now the fun part starts... we modify the attempt state to be 'INIT' and wait the the
    // Janitor to do its job.
    paymentDao.updatePaymentAttempt(
        refundAttempt.getId(), refundAttempt.getTransactionId(), "INIT", internalCallContext);
    final PaymentAttemptModelDao attempt2 =
        paymentDao.getPaymentAttempt(refundAttempt.getId(), internalCallContext);
    assertEquals(attempt2.getStateName(), "INIT");

    clock.addDays(1);
    try {
      Thread.sleep(1500);
    } catch (InterruptedException e) {
    }

    final PaymentAttemptModelDao attempt3 =
        paymentDao.getPaymentAttempt(refundAttempt.getId(), internalCallContext);
    assertEquals(attempt3.getStateName(), "SUCCESS");
  }