/**
   * Create and return an OrderTotal object for the tax amount.
   *
   * @param order
   * @param dispPriceWithTax
   * @param locale
   * @return Returns an OrderTotal object for this module
   * @throws Exception
   */
  public OrderTotal getOrderTotal(Order order, boolean dispPriceWithTax, Locale locale)
      throws Exception {
    OrderTotal ot;
    StaticData sd = staticDataHM.get(getStoreId());

    // Get the resource bundle
    ResourceBundle rb = getResourceBundle(mutex, bundleName, resourceBundleMap, locale);
    if (rb == null) {
      throw new KKException(
          "A resource file cannot be found for the country " + locale.getCountry());
    }
    ot = new OrderTotal();
    ot.setSortOrder(sd.getSortOrder());
    ot.setClassName(code);

    // Call the TaxCloud service
    callTaxCloud(sd, order, ot);

    // Set the title of the order total
    StringBuffer title = new StringBuffer();
    title.append(rb.getString(MODULE_ORDER_TOTAL_TAX_CLOUD_TITLE));
    title.append(":");
    ot.setTitle(title.toString());

    return ot;
  }
Exemple #2
0
  /**
   * Create and return an OrderTotal object for the shipping cost.
   *
   * @param order
   * @param dispPriceWithTax
   * @param locale
   * @return Returns an OrderTotal object for this module
   * @throws Exception
   */
  public OrderTotal getOrderTotal(Order order, boolean dispPriceWithTax, Locale locale)
      throws Exception {
    OrderTotal ot;
    StaticData sd = staticDataHM.get(getStoreId());

    // Get the resource bundle
    ResourceBundle rb = getResourceBundle(mutex, bundleName, resourceBundleMap, locale);
    if (rb == null) {
      throw new KKException(
          "A resource file cannot be found for the country " + locale.getCountry());
    }

    ot = new OrderTotal();
    ot.setSortOrder(sd.getSortOrder());
    ot.setClassName(code);
    if (order.getShippingQuote() == null) {
      ot.setTitle(rb.getString(MODULE_ORDER_TOTAL_SHIPPING_TITLE) + ":");
      ot.setValue(new BigDecimal(0));
      ot.setText(getCurrMgr().formatPrice(new BigDecimal(0), order.getCurrencyCode()));
    } else {
      ot.setTitle(
          order.getShippingQuote().getTitle()
              + " ("
              + order.getShippingQuote().getResponseText()
              + "):");
      BigDecimal cost;
      if (dispPriceWithTax) {
        cost = order.getShippingQuote().getTotalIncTax();
      } else {
        cost = order.getShippingQuote().getTotalExTax();
      }
      ot.setValue(cost);
      ot.setText(getCurrMgr().formatPrice(cost, order.getCurrencyCode()));
    }

    return ot;
  }
  /**
   * Call the TaxCloud tax service which calculates the total tax for the order (including shipping)
   * and populates the Order Total and Order objects with the tax information.
   *
   * @param sd
   * @param order
   * @param ot
   * @throws Exception
   * @throws DataSetException
   * @throws TorqueException
   */
  private void callTaxCloud(StaticData sd, Order order, OrderTotal ot)
      throws TorqueException, DataSetException, Exception {

    // Look up tax rates from TaxCloud
    LookupService lookupService = new LookupService();

    String apiLoginID = sd.getLoginId();
    String apiKey = sd.getLoginKey();
    String customerId = String.valueOf(order.getCustomerId());
    String cartId = order.getLifecycleId();

    // Figure out whether there is a shipping charge
    boolean isShipping = false;
    ShippingQuoteIf shippingQuote = order.getShippingQuote();
    if (shippingQuote != null
        && shippingQuote.getTotalExTax() != null
        && shippingQuote.getTotalExTax().compareTo(new BigDecimal(0)) == 1) {
      isShipping = true;
    }

    /*
     * Create an array of cart items to send to TaxCloud. Every item needs a TIC (Taxability
     * Information Code) which is contained in each order product object in the TaxCode
     * attribute. If we need to calculate tax for shipping we make the CartItem array longer by
     * one.
     */
    int arrayLength =
        (isShipping) ? order.getOrderProducts().length + 1 : order.getOrderProducts().length;
    CartItem[] cartItems = new CartItem[arrayLength];
    int cartIndex = 0;
    for (int i = 0; i < order.getOrderProducts().length; i++) {
      OrderProductIf orderProduct = order.getOrderProducts()[i];
      CartItem cartItem = new CartItem();
      cartItem.setIndex(cartIndex);
      cartItem.setItemID(String.valueOf(orderProduct.getProductId()));
      if (orderProduct.getTaxCode() == null || orderProduct.getTaxCode().length() == 0) {
        throw new KKException(
            "The TaxClass object for the product with id = "
                + orderProduct.getProductId()
                + " does not have a TIC (Taxability Information Code) set.");
      }
      int ticID;
      try {
        ticID = Integer.parseInt(orderProduct.getTaxCode());
      } catch (Exception e) {
        throw new KKException(
            "The TaxClass object for the product with id = "
                + orderProduct.getProductId()
                + " does not have a numeric TIC (Taxability Information Code) set. The value found = "
                + orderProduct.getTaxCode()
                + " is invalid.");
      }
      cartItem.setTIC(ticID);

      // Must call TaxCloud with final price of a single product
      int scale = getTaxMgr().getTaxScale();
      BigDecimal singleProdPrice =
          (orderProduct.getFinalPriceExTax())
              .divide(new BigDecimal(orderProduct.getQuantity()), scale, BigDecimal.ROUND_HALF_UP);
      cartItem.setPrice(singleProdPrice.floatValue());
      cartItem.setQty(orderProduct.getQuantity());
      cartItems[cartIndex] = cartItem;
      cartIndex++;
    }

    if (isShipping) {
      // Add shipping charges to the cart (shipping charges are taxable)
      CartItem cartItem = new CartItem();
      cartItem.setIndex(cartIndex);
      cartItem.setItemID(SHIPPING_TIC_STR);
      cartItem.setTIC(SHIPPING_TIC);
      cartItem.setPrice(shippingQuote.getTotalExTax().floatValue());
      cartItem.setQty(1);
      cartItems[cartIndex] = cartItem;
    }

    net.taxcloud.Address destination = new net.taxcloud.Address();
    destination.setAddress1(order.getDeliveryStreetAddress());
    destination.setAddress2("");
    destination.setCity(order.getDeliveryCity());
    destination.setState(order.getDeliveryState());
    destination.setZip5(order.getDeliveryPostcode());
    net.taxcloud.Address destinationVerified = verifyAddress(sd, destination);
    if (destinationVerified == null) {
      throw new KKException(
          "The destination address could not be verified using the USPS verification service probably due to a communications problem.");
    }
    validateAddress(destination, destinationVerified);

    // Now set the verified address back into the Order
    order.setDeliveryStreetAddress(destinationVerified.getAddress1());
    order.setDeliveryCity(destinationVerified.getCity());
    order.setDeliveryState(destinationVerified.getState());
    order.setDeliveryPostcode(destinationVerified.getZip5() + "-" + destinationVerified.getZip4());

    boolean deliveredBySeller = true;
    ExemptionCertificate exemptionCertificate = null;

    CartItemResponse[] cartItemsResponse = null;
    try {
      if (log.isDebugEnabled()) {
        StringBuffer sb = new StringBuffer();
        sb.append("Calling tax cloud tax service with the following data:\n");
        sb.append("apiLoginID =  ").append(apiLoginID).append("\n");
        sb.append("apiKey =      ").append(apiKey).append("\n");
        sb.append("customerId =  ").append(customerId).append("\n");
        sb.append("cartId =      ").append(cartId).append("\n");
        sb.append("Store Address:\n");
        sb.append("Address1 =    ").append(sd.getOriginAddr().getAddress1()).append("\n");
        sb.append("Address2 =    ").append(sd.getOriginAddr().getAddress2()).append("\n");
        sb.append("City =        ").append(sd.getOriginAddr().getCity()).append("\n");
        sb.append("State =       ").append(sd.getOriginAddr().getState()).append("\n");
        sb.append("Zip4 =        ").append(sd.getOriginAddr().getZip4()).append("\n");
        sb.append("Zip5 =        ").append(sd.getOriginAddr().getZip5()).append("\n");
        sb.append("Delivery Address:\n");
        sb.append("Address1 =    ").append(destinationVerified.getAddress1()).append("\n");
        sb.append("Address2 =    ").append(destinationVerified.getAddress2()).append("\n");
        sb.append("City =        ").append(destinationVerified.getCity()).append("\n");
        sb.append("State =       ").append(destinationVerified.getState()).append("\n");
        sb.append("Zip4 =        ").append(destinationVerified.getZip4()).append("\n");
        sb.append("Zip5 =        ").append(destinationVerified.getZip5()).append("\n");
        sb.append("CartItems:\n");
        for (int i = 0; i < cartItems.length; i++) {
          CartItem item = cartItems[i];
          sb.append("ItemID =        ").append(item.getItemID()).append("\n");
          sb.append("TIC =           ").append(item.getTIC()).append("\n");
          sb.append("Qty =           ").append(item.getQty()).append("\n");
          sb.append("Price =         ").append(item.getPrice()).append("\n");
        }
        log.debug(sb);
      }
      // Call TaxCloud to look up tax rates
      cartItemsResponse =
          lookupService.lookup(
              apiLoginID,
              apiKey,
              customerId,
              cartId,
              cartItems,
              sd.getOriginAddr(),
              destinationVerified,
              deliveredBySeller,
              exemptionCertificate);
    } catch (Exception e) {
      log.error("Problem calling TaxCloud: ", e);
    }
    if (cartItemsResponse == null || cartItemsResponse.length == 0) {
      throw new KKException(
          "TaxCloud returned an empty response from the lookupService.lookup() API call.");
    }

    if (log.isDebugEnabled()) {
      log.debug("Response from TaxCloud lookup:");
      for (int i = 0; i < cartItemsResponse.length; i++) {
        CartItemResponse r = cartItemsResponse[i];
        log.debug("CartItem [index=" + r.getCartItemIndex() + ", tax=" + r.getTaxAmount() + "]");
      }
    }

    float taxAmount = 0;
    for (int i = 0; i < cartItemsResponse.length - 1; i++) {
      CartItemResponse cartItemResponse = cartItemsResponse[i];
      taxAmount = taxAmount + cartItemResponse.getTaxAmount();
    }

    // Now get the tax amount for the shipping charges
    CartItemResponse cartItemResponse = cartItemsResponse[cartItemsResponse.length - 1];
    taxAmount = taxAmount + cartItemResponse.getTaxAmount();

    // Set the Order Total with the total tax amount
    BigDecimal taxAmountBD = new BigDecimal(taxAmount);
    ot.setValue(taxAmountBD);
    ot.setText(getCurrMgr().formatPrice(taxAmountBD, order.getCurrencyCode()));

    // Set the order with tax information
    order.setTax(taxAmountBD);
    order.setTotalIncTax(order.getTotalExTax().add(taxAmountBD));
  }