private void calculatePriceActual(final I_C_InvoiceLine invoiceLine, final int precision) {
    final BigDecimal discount = invoiceLine.getDiscount();
    final BigDecimal priceEntered = invoiceLine.getPriceEntered();

    BigDecimal priceActual;
    if (priceEntered.signum() == 0) {
      priceActual = priceEntered;
    } else {
      final int precisionToUse;
      if (precision >= 0) {
        precisionToUse = precision;
      } else {
        final I_C_Invoice invoice = invoiceLine.getC_Invoice();

        precisionToUse = invoice.getM_PriceList().getPricePrecision();
      }

      priceActual = subtractDiscount(priceEntered, discount, precisionToUse);
    }

    invoiceLine.setPriceActual(priceActual);
  }
  @Override
  public int getC_TaxCategory_ID(final org.compiere.model.I_C_InvoiceLine invoiceLine) {
    // FIXME: we need to retrieve the C_TaxCategory_ID by using Pricing Engine

    if (invoiceLine.getC_Charge_ID() > 0) {
      return invoiceLine.getC_Charge().getC_TaxCategory_ID();
    }

    final I_C_Invoice invoice = invoiceLine.getC_Invoice();

    final IPriceListDAO priceListDAO = Services.get(IPriceListDAO.class);
    final Boolean processedPLVFiltering =
        null; // task 09533: the user doesn't know about PLV's processed flag, so we can't filter by
              // it

    if (invoice.getM_PriceList_ID() != 100) // FIXME use PriceList_None constant
    {
      final I_M_PriceList priceList = invoice.getM_PriceList();

      final I_M_PriceList_Version priceListVersion =
          priceListDAO.retrievePriceListVersionOrNull(
              priceList, invoice.getDateInvoiced(), processedPLVFiltering);
      Check.errorIf(
          priceListVersion == null, "Missing PLV for M_PriceList and DateInvoiced of {}", invoice);

      final int m_Product_ID = invoiceLine.getM_Product_ID();
      Check.assume(m_Product_ID > 0, "M_Product_ID > 0 for {}", invoiceLine);

      final I_M_ProductPrice productPrice =
          priceListDAO.retrieveProductPrice(priceListVersion, m_Product_ID);

      return productPrice.getC_TaxCategory_ID();
    }

    // Fallback: try getting from Order Line
    if (invoiceLine.getC_OrderLine_ID() > 0) {
      return invoiceLine.getC_OrderLine().getC_TaxCategory_ID();
    }

    // Fallback: try getting from Invoice -> Order
    if (invoiceLine.getC_Invoice().getC_Order_ID() > 0) {
      final Properties ctx = InterfaceWrapperHelper.getCtx(invoiceLine);
      final String trxName = InterfaceWrapperHelper.getTrxName(invoiceLine);

      final I_C_Order order =
          InterfaceWrapperHelper.create(
              ctx, invoiceLine.getC_Invoice().getC_Order_ID(), I_C_Order.class, trxName);

      final I_M_PriceList priceList = order.getM_PriceList();

      final I_M_PriceList_Version priceListVersion =
          priceListDAO.retrievePriceListVersionOrNull(
              priceList, invoice.getDateInvoiced(), processedPLVFiltering);
      Check.errorIf(
          priceListVersion == null, "Missing PLV for M_PriceList and DateInvoiced of {}", invoice);

      final int m_Product_ID = invoiceLine.getM_Product_ID();
      Check.assume(m_Product_ID > 0, "M_Product_ID > 0 for {}", invoiceLine);

      final I_M_ProductPrice productPrice =
          priceListDAO.retrieveProductPrice(priceListVersion, m_Product_ID);

      return productPrice.getC_TaxCategory_ID();
    }

    throw new AdempiereException(
        "@NotFound@ @C_TaxCategory_ID@ (" + "@C_InvoiceLine_ID@:" + invoiceLine + ")");
  }