ruckus / quickbooks-ruby

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

Add Custom Tax Rates on Invoices #541

Closed Moiz1524 closed 3 years ago

Moiz1524 commented 3 years ago

Hey there! Its been a great experience by far using this library. Now I have come into a situation where the user in my app can add a custom tax rate on the invoice. As my invoice creation process is synced with Quickbooks, I must have to create the tax rate on Quickbooks' end. The official API docs of Intuit state that you can create a TaxRate by creating a TaxService but the support is for json only. I've browsed through closed issues as following but nothing helped me in this regard.

165 #262

So far I've written this code. But the TaxRateDetails always remain empty, therefore Tax rate details must have at least one item validation plays its role. Any help will be much appreciated!

@service_5 = Quickbooks::Service::TaxService.new power_up_service_5! // for refreshing access tokens and stuff tax_service = Quickbooks::Model::TaxService.new tax_service.tax_rate_details do |detail| detail.rate_value = 8 detail.tax_agency_id = 1 detail.tax_rate_name = 'MyCustomTaxName' end tax_service.tax_code = 'TAX' @service_5.create(tax_service)

ruckus commented 3 years ago

Hi @Moiz1524 yeah the tax thing is kinda wonky. I handle taxes on invoices and line-items with this kind of pseudo-code (its pretty close to the real code, but slightly abbreviated).

class Foo

      def line_item_tax_code_ref
        'TAX'
      end

      def invoice_transaction_tax_code_rate_ref
        55
      end

      def invoice_transaction_tax_detail_rate_ref
        184
      end

      def create_invoice(supplier_order, line_item, intuit_invoice)

        invoice = Quickbooks::Model::Invoice.new
        invoice.customer_id = intuit_invoice.customer_id
        invoice.due_date = intuit_invoice.order_due_date.strftime('%F')
        invoice.ship_date = intuit_invoice.order_delivery_date.strftime('%F')
        invoice.txn_date = intuit_invoice.order_delivery_date.strftime('%F')
        invoice.doc_number = intuit_invoice.invoice_number

        item.sales_item! do |detail|
          detail.item_id = line_item.item_id
          detail.unit_price = line_item.unit_price.round(2)
          detail.quantity = line_item.quantity

          # taxable?
          if line_item.tax.to_f > 0
            detail.tax_code_ref = Quickbooks::Model::BaseReference.new(line_item_tax_code_ref)
          end

          #amount = line_item.amount
          amount = detail.unit_price * detail.quantity
        end
        invoice.line_items << item

        if supplier_order.total_tax_cents.to_i > 0
          tax_detail = Quickbooks::Model::TransactionTaxDetail.new
          tax_detail.txn_tax_code_ref = Quickbooks::Model::BaseReference.new(invoice_transaction_tax_code_rate_ref)
          tax_detail.total_tax = supplier_order.total_tax

          tax_line = Quickbooks::Model::TaxLine.new
          tax_line.amount = tax_detail.total_tax
          tax_line.detail_type = 'TaxLineDetail'

          tax_line_detail = Quickbooks::Model::TaxLineDetail.new
          tax_line_detail.percent_based = true
          tax_line_detail.net_amount_taxable = supplier_order.total_excluding_taxes_cents
          tax_line_detail.tax_percent = supplier_order.tax_percent_rate.to_f
          tax_line_detail.tax_rate_ref = Quickbooks::Model::BaseReference.new(invoice_transaction_tax_detail_rate_ref)
          tax_line.tax_line_detail = tax_line_detail

          tax_detail.lines = [tax_line]
          invoice.txn_tax_detail = tax_detail
        end

        service.create(invoice)      
      end

end

The hard-coded methods at the top are specific to my customer (they'd probably be stored in the database) and I get once programmatically during my customer on-boarding (aside: I found it most useful to physically create an Invoice in the Quickbooks Web UI fully populated as required then pull down the invoice programmatically and reverse-engineer it in code).

Moiz1524 commented 3 years ago

@ruckus Great Thanks !! It helped me a lot. Also the reverse engineering tip seems very simple and powerful. Will use it for sure :)