ruckus / quickbooks-ruby

Quickbooks Online REST API V3 - Ruby
MIT License
374 stars 302 forks source link

Estimate & Invoice creation error - Invalid Reference Id : TaxRate #268

Closed phildionne closed 9 years ago

phildionne commented 9 years ago

I'm trying to create an Estimate for a french Canadian company and it seems like I can't get it to work. Here's how I build the estimate:

Quickbooks::Model::Estimate.new.tap do |estimate|
      item = Quickbooks::Model::InvoiceLineItem.new.tap do |item|
        item.amount = total

        item.sales_item! do |detail|
          detail.unit_price   = total
          detail.quantity     = 1
          detail.item_id      = 1
          detail.tax_code_ref = Quickbooks::Model::TaxCode.new(id: 11)
        end
      end

      # GST @ 5%
      gst_tax_line = Quickbooks::Model::TaxLine.new.tap do |tax_line|
        tax_line.amount      = 0.05 * total
        tax_line.detail_type = "TaxLineDetail"

        tax_line.tax_line_detail = Quickbooks::Model::TaxLineDetail.new.tap do |detail|
          detail.percent_based      = true
          detail.net_amount_taxable = total
          detail.tax_percent        = 0.05
          detail.tax_rate_ref       = Quickbooks::Model::TaxRate.new(id: 6 )
        end
      end

      # QST @ 9.975%
      qst_tax_line = Quickbooks::Model::TaxLine.new.tap do |tax_line|
        tax_line.amount      = 0.09975 * total
        tax_line.detail_type = "TaxLineDetail"

        tax_line.tax_line_detail = Quickbooks::Model::TaxLineDetail.new.tap do |detail|
          detail.percent_based      = true
          detail.net_amount_taxable = total
          detail.tax_percent        = 0.09975
          detail.tax_rate_ref       = Quickbooks::Model::TaxRate.new(id: 25)
        end
      end

      estimate.customer_id            = customer_id
      estimate.global_tax_calculation = GlobalTaxCalculation::TAX_EXCLUDED
      estimate.txn_tax_detail         = Quickbooks::Model::TransactionTaxDetail.new(total_tax: (0.05 * total) + (0.09975 * total))
      estimate.txn_tax_detail.lines   = [gst_tax_line, qst_tax_line]
      estimate.line_items             << item
    end
  end

The request body generated is:

<?xml version=\"1.0\" encoding=\"utf-8\"?>
<Estimate xmlns=\"http://schema.intuit.com/finance/v3\" sparse=\"false\">
  <GlobalTaxCalculation>TaxExcluded</GlobalTaxCalculation>
  <Line>
    <Amount>10.0</Amount>
    <DetailType>SalesItemLineDetail</DetailType>
    <SalesItemLineDetail>
      <ItemRef>1</ItemRef>
      <UnitPrice>10.0</UnitPrice>
      <Qty>1.0</Qty>
      <TaxCodeRef>
        <Id>11</Id>
      </TaxCodeRef>
    </SalesItemLineDetail>
  </Line>
  <TxnTaxDetail>
    <TotalTax>1.4975</TotalTax>
    <TaxLine>
      <Amount>0.5</Amount>
      <DetailType>TaxLineDetail</DetailType>
      <TaxLineDetail>
        <PercentBased>true</PercentBased>
        <NetAmountTaxable>10.0</NetAmountTaxable>
        <TaxInclusiveAmount>0.0</TaxInclusiveAmount>
        <OverrideDeltaAmount>0.0</OverrideDeltaAmount>
        <TaxPercent>0.05</TaxPercent>
        <TaxRateRef>
          <Id>6</Id>
          <RateValue>0.0</RateValue>
        </TaxRateRef>
      </TaxLineDetail>
    </TaxLine>
    <TaxLine>
      <Amount>0.9975</Amount>
      <DetailType>TaxLineDetail</DetailType>
      <TaxLineDetail>
        <PercentBased>true</PercentBased>
        <NetAmountTaxable>10.0</NetAmountTaxable>
        <TaxInclusiveAmount>0.0</TaxInclusiveAmount>
        <OverrideDeltaAmount>0.0</OverrideDeltaAmount>
        <TaxPercent>0.09975</TaxPercent>
        <TaxRateRef>
          <Id>25</Id>
          <RateValue>0.0</RateValue>
        </TaxRateRef>
      </TaxLineDetail>
    </TaxLine>
  </TxnTaxDetail>
  <CustomerRef>200</CustomerRef>
</Estimate>

I'm not quite sure but it seems like the generated XML is not quite what it should be. Does anyone has a solution in mind?

ruckus commented 9 years ago

Try rounding your floats to 2 decimal places - I've encountered issues with arbitrary precision numbers and QB not liking it.

I actually use these two helper methods - one for prices and one for quantities:

      def float_to_qb_amount(quantity)
        "%.2f" % quantity
      end

      def float_to_qb_quantity(quantity)
        quantity.round(5)
      end
phildionne commented 9 years ago

Thanks for your suggestion, tried it but the same error happens. Anything else in mind?

ruckus commented 9 years ago

What is the error you are getting?

phildionne commented 9 years ago

The exact error is: Invalid Reference Id: Invalid Reference Id : TaxRate. The request is: Net::HTTPBadRequest 400 Bad Request.

ruckus commented 9 years ago

I bet its having issues with these calls:

detail.tax_rate_ref       = Quickbooks::Model::TaxRate.new(id: 25)

Which is getting expanded to:

<TaxRateRef>
  <Id>25</Id>
  <RateValue>0.0</RateValue>
 </TaxRateRef>

Any Ref attribute value should really be just a reference itself and not a more "complex" object, for lack of a better term.

Try this instead:

detail.tax_rate_id = 25

You have this same pattern in a couple of places, so ensure that all are updated appropriately.

phildionne commented 9 years ago

Thanks for the help, I finally got it by using BaseReference:

def build_quickbooks_model(customer_id)
    Quickbooks::Model::Estimate.new.tap do |estimate|
      item = Quickbooks::Model::InvoiceLineItem.new.tap do |item|
        item.amount = qb_float_format(total)

        item.sales_item! do |detail|
          detail.unit_price   = qb_float_format(total)
          detail.quantity     = 1
          detail.item_id      = 1
          detail.tax_code_ref = Quickbooks::Model::BaseReference.new(11)
        end
      end

      # GST @ 5%
      gst_tax_line = Quickbooks::Model::TaxLine.new.tap do |tax_line|
        tax_line.amount      = qb_float_format(0.05 * total)
        tax_line.detail_type = "TaxLineDetail"

        tax_line.tax_line_detail = Quickbooks::Model::TaxLineDetail.new.tap do |detail|
          detail.percent_based      = true
          detail.net_amount_taxable = total
          detail.tax_percent        = 0.05
          detail.tax_rate_ref       = Quickbooks::Model::BaseReference.new(6)
        end
      end

      # QST @ 9.975%
      qst_tax_line = Quickbooks::Model::TaxLine.new.tap do |tax_line|
        tax_line.amount      = qb_float_format(0.09975 * total)
        tax_line.detail_type = "TaxLineDetail"

        tax_line.tax_line_detail = Quickbooks::Model::TaxLineDetail.new.tap do |detail|
          detail.percent_based      = true
          detail.net_amount_taxable = qb_float_format(total)
          detail.tax_percent        = 0.09975
          detail.tax_rate_ref       = Quickbooks::Model::BaseReference.new(25)
        end
      end

      estimate.customer_id            = customer_id
      estimate.global_tax_calculation = GlobalTaxCalculation::TAX_EXCLUDED
      estimate.txn_tax_detail         = Quickbooks::Model::TransactionTaxDetail.new(total_tax: qb_float_format((0.05 * total) + (0.09975 * total)))
      estimate.txn_tax_detail.lines   = [gst_tax_line, qst_tax_line]
      estimate.line_items             << item
    end
  end