quickbooks-ruby 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/{quickbooks.rb → quickbooks-ruby.rb} +26 -4
  3. data/lib/quickbooks/model/account.rb +91 -0
  4. data/lib/quickbooks/model/account_based_expense_line_detail.rb +15 -0
  5. data/lib/quickbooks/model/base_model.rb +21 -0
  6. data/lib/quickbooks/model/{customer_ref.rb → base_reference.rb} +1 -1
  7. data/lib/quickbooks/model/bill.rb +36 -0
  8. data/lib/quickbooks/model/bill_line_item.rb +23 -0
  9. data/lib/quickbooks/model/bill_payment.rb +34 -0
  10. data/lib/quickbooks/model/bill_payment_check.rb +12 -0
  11. data/lib/quickbooks/model/bill_payment_credit_card.rb +10 -0
  12. data/lib/quickbooks/model/bill_payment_line_item.rb +21 -0
  13. data/lib/quickbooks/model/check_payment.rb +11 -0
  14. data/lib/quickbooks/model/credit_card_payment.rb +17 -0
  15. data/lib/quickbooks/model/credit_memo.rb +38 -0
  16. data/lib/quickbooks/model/customer.rb +18 -15
  17. data/lib/quickbooks/model/discount_override.rb +5 -3
  18. data/lib/quickbooks/model/invoice.rb +41 -19
  19. data/lib/quickbooks/model/invoice_line_item.rb +6 -6
  20. data/lib/quickbooks/model/item.rb +24 -17
  21. data/lib/quickbooks/model/line.rb +28 -0
  22. data/lib/quickbooks/model/payment_line_detail.rb +6 -4
  23. data/lib/quickbooks/model/payment_method.rb +14 -0
  24. data/lib/quickbooks/model/physical_address.rb +18 -2
  25. data/lib/quickbooks/model/sales_item_line_detail.rb +9 -7
  26. data/lib/quickbooks/model/sales_receipt.rb +44 -0
  27. data/lib/quickbooks/model/sub_total_line_detail.rb +7 -5
  28. data/lib/quickbooks/service/account.rb +22 -0
  29. data/lib/quickbooks/service/base_service.rb +45 -60
  30. data/lib/quickbooks/service/bill.rb +15 -0
  31. data/lib/quickbooks/service/bill_payment.rb +15 -0
  32. data/lib/quickbooks/service/credit_memo.rb +15 -0
  33. data/lib/quickbooks/service/payment_method.rb +23 -0
  34. data/lib/quickbooks/service/sales_receipt.rb +15 -0
  35. data/lib/quickbooks/service/service_crud.rb +4 -8
  36. data/lib/quickbooks/util/class_util.rb +14 -0
  37. data/lib/quickbooks/{http_encoding_helper.rb → util/http_encoding_helper.rb} +16 -11
  38. data/lib/quickbooks/version.rb +1 -1
  39. metadata +26 -6
  40. data/lib/quickbooks/model/invoice_item_ref.rb +0 -21
@@ -1,10 +1,12 @@
1
1
  module Quickbooks
2
2
  module Model
3
3
  class DiscountOverride < BaseModel
4
- xml_accessor :discount_ref, :from => 'DiscountRef', :as => Integer
4
+ xml_accessor :discount_ref, :from => 'DiscountRef', :as => BaseReference
5
5
  xml_accessor :percent_based, :from => 'PercentBased'
6
- xml_accessor :discount_percent, :from => 'DiscountPercent', :as => Float
7
- xml_accessor :discount_account_ref, :from => 'DiscountAccountRef', :as => Integer
6
+ xml_accessor :discount_percent, :from => 'DiscountPercent', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
7
+ xml_accessor :discount_account_ref, :from => 'DiscountAccountRef', :as => BaseReference
8
+
9
+ reference_setters :discount_ref, :discount_account_ref
8
10
 
9
11
  def percent_based?
10
12
  percent_based.to_s == 'true'
@@ -13,49 +13,75 @@ module Quickbooks
13
13
  REST_RESOURCE = 'invoice'
14
14
  XML_COLLECTION_NODE = "Invoice"
15
15
  XML_NODE = "Invoice"
16
+ EMAIL_STATUS_NEED_TO_SEND = 'NeedToSend'
16
17
 
17
18
  xml_accessor :id, :from => 'Id', :as => Integer
18
19
  xml_accessor :sync_token, :from => 'SyncToken', :as => Integer
19
- xml_accessor :meta_data, :from => 'MetaData', :as => Quickbooks::Model::MetaData
20
- xml_accessor :custom_fields, :from => 'CustomField', :as => [Quickbooks::Model::CustomField]
20
+ xml_accessor :meta_data, :from => 'MetaData', :as => MetaData
21
+ xml_accessor :custom_fields, :from => 'CustomField', :as => [CustomField]
21
22
  xml_accessor :doc_number, :from => 'DocNumber'
22
23
  xml_accessor :txn_date, :from => 'TxnDate', :as => Date
23
24
  xml_accessor :private_note, :from => 'PrivateNote'
24
- xml_accessor :linked_transactions, :from => 'LinkedTxn', :as => [Quickbooks::Model::LinkedTransaction]
25
- xml_accessor :line_items, :from => 'Line', :as => [Quickbooks::Model::InvoiceLineItem]
25
+ xml_accessor :linked_transactions, :from => 'LinkedTxn', :as => [LinkedTransaction]
26
+ xml_accessor :line_items, :from => 'Line', :as => [InvoiceLineItem]
26
27
  xml_accessor :txn_tax_detail, :from => 'TxnTaxDetail'
27
- xml_accessor :customer_ref, :from => 'CustomerRef', :as => Quickbooks::Model::CustomerRef
28
+ xml_accessor :customer_ref, :from => 'CustomerRef', :as => BaseReference
28
29
  xml_accessor :customer_memo, :from => 'CustomerMemo'
29
- xml_accessor :billing_address, :from => 'BillAddr', :as => Quickbooks::Model::PhysicalAddress
30
- xml_accessor :shipping_address, :from => 'ShipAddr', :as => Quickbooks::Model::PhysicalAddress
31
- xml_accessor :class_ref, :from => 'ClassRef'
32
- xml_accessor :sales_term_ref, :from => 'SalesTermRef', :as => Integer
30
+ xml_accessor :billing_address, :from => 'BillAddr', :as => PhysicalAddress
31
+ xml_accessor :shipping_address, :from => 'ShipAddr', :as => PhysicalAddress
32
+ xml_accessor :class_ref, :from => 'ClassRef', :as => BaseReference
33
+ xml_accessor :sales_term_ref, :from => 'SalesTermRef', :as => BaseReference
33
34
  xml_accessor :due_date, :from => 'DueDate', :as => Date
34
- xml_accessor :ship_method_ref, :from => 'ShipMethodRef'
35
+ xml_accessor :ship_method_ref, :from => 'ShipMethodRef', :as => BaseReference
35
36
  xml_accessor :ship_date, :from => 'ShipDate', :as => Date
36
37
  xml_accessor :tracking_num, :from => 'TrackingNum'
37
- xml_accessor :ar_account_ref, :from => 'ARAccountRef', :as => Integer
38
- xml_accessor :total_amount, :from => 'TotalAmt', :as => Float
38
+ xml_accessor :ar_account_ref, :from => 'ARAccountRef', :as => BaseReference
39
+ xml_accessor :total_amount, :from => 'TotalAmt', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
39
40
  xml_accessor :apply_tax_after_discount, :from => 'ApplyTaxAfterDiscount'
40
41
  xml_accessor :print_status, :from => 'PrintStatus'
41
42
  xml_accessor :email_status, :from => 'EmailStatus'
42
- xml_accessor :balance, :from => 'Balance', :as => Float
43
- xml_accessor :deposit, :from => 'Deposit', :as => Float
44
- xml_accessor :department_ref, :from => 'DepartmentRef'
43
+ xml_accessor :balance, :from => 'Balance', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
44
+ xml_accessor :deposit, :from => 'Deposit', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
45
+ xml_accessor :department_ref, :from => 'DepartmentRef', :as => BaseReference
45
46
  xml_accessor :allow_ipn_payment, :from => 'AllowIPNPayment'
47
+ xml_accessor :bill_email, :from => 'BillEmail', :as => EmailAddress
46
48
  xml_accessor :allow_online_payment, :from => 'AllowOnlinePayment'
47
49
  xml_accessor :allow_online_credit_card_payment, :from => 'AllowOnlineCreditCardPayment'
48
50
  xml_accessor :allow_online_ach_payment, :from => 'AllowOnlineACHPayment'
49
51
 
52
+ reference_setters :customer_ref, :class_ref, :sales_term_ref, :ship_method_ref
53
+ reference_setters :ar_account_ref, :department_ref
54
+
50
55
  #== Validations
51
56
  validates_length_of :line_items, :minimum => 1
52
57
  validate :existence_of_customer_ref
58
+ validate :required_bill_email_if_email_delivery
53
59
 
54
60
  def initialize
55
61
  ensure_line_items_initialization
56
62
  super
57
63
  end
58
64
 
65
+ def required_bill_email_if_email_delivery
66
+ return unless email_status_for_delivery?
67
+
68
+ if bill_email.nil?
69
+ errors.add(:bill_email, "BillEmail is required if EmailStatus=NeedToSend")
70
+ end
71
+ end
72
+
73
+ def billing_email_address=(email_address_string)
74
+ self.bill_email = EmailAddress.new(email_address_string)
75
+ end
76
+
77
+ def wants_billing_email_sent!
78
+ self.email_status = EMAIL_STATUS_NEED_TO_SEND
79
+ end
80
+
81
+ def email_status_for_delivery?
82
+ email_status == EMAIL_STATUS_NEED_TO_SEND
83
+ end
84
+
59
85
  def apply_tax_after_discount?
60
86
  apply_tax_after_discount.to_s == 'true'
61
87
  end
@@ -76,10 +102,6 @@ module Quickbooks
76
102
  allow_online_ach_payment.to_s == 'true'
77
103
  end
78
104
 
79
- def customer_id=(customer_id)
80
- self.customer_ref = Quickbooks::Model::CustomerRef.new(customer_id)
81
- end
82
-
83
105
  private
84
106
 
85
107
  def existence_of_customer_ref
@@ -10,13 +10,13 @@ module Quickbooks
10
10
  xml_accessor :id, :from => 'Id', :as => Integer
11
11
  xml_accessor :line_num, :from => 'LineNum', :as => Integer
12
12
  xml_accessor :description, :from => 'Description'
13
- xml_accessor :amount, :from => 'Amount', :as => Float
13
+ xml_accessor :amount, :from => 'Amount', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
14
14
  xml_accessor :detail_type, :from => 'DetailType'
15
15
 
16
16
  #== Various detail types
17
- xml_accessor :sales_line_item_detail, :from => 'SalesItemLineDetail', :as => Quickbooks::Model::SalesItemLineDetail
18
- xml_accessor :sub_total_line_detail, :from => 'SubTotalLineDetail', :as => Quickbooks::Model::SubTotalLineDetail
19
- xml_accessor :payment_line_detail, :from => 'PaymentLineDetail', :as => Quickbooks::Model::PaymentLineDetail
17
+ xml_accessor :sales_line_item_detail, :from => 'SalesItemLineDetail', :as => SalesItemLineDetail
18
+ xml_accessor :sub_total_line_detail, :from => 'SubTotalLineDetail', :as => SubTotalLineDetail
19
+ xml_accessor :payment_line_detail, :from => 'PaymentLineDetail', :as => PaymentLineDetail
20
20
 
21
21
  def sales_item?
22
22
  detail_type.to_s == SALES_LINE_ITEM_DETAIL
@@ -28,14 +28,14 @@ module Quickbooks
28
28
 
29
29
  def sales_item!
30
30
  self.detail_type = SALES_LINE_ITEM_DETAIL
31
- self.sales_line_item_detail = Quickbooks::Model::SalesItemLineDetail.new
31
+ self.sales_line_item_detail = SalesItemLineDetail.new
32
32
 
33
33
  yield self.sales_line_item_detail if block_given?
34
34
  end
35
35
 
36
36
  def payment_item!
37
37
  self.detail_type = PAYMENT_LINE_DETAIL
38
- self.payment_line_detail = Quickbooks::Model::PaymentLineDetail.new
38
+ self.payment_line_detail = PaymentLineDetail.new
39
39
 
40
40
  yield self.payment_line_detail if block_given?
41
41
  end
@@ -19,31 +19,38 @@ module Quickbooks
19
19
  xml_name 'Item'
20
20
  xml_accessor :id, :from => 'Id', :as => Integer
21
21
  xml_accessor :sync_token, :from => 'SyncToken', :as => Integer
22
- xml_accessor :meta_data, :from => 'MetaData', :as => Quickbooks::Model::MetaData
23
- xml_accessor :attachable_ref, :from => 'AttachableRef', :as => Integer
22
+ xml_accessor :meta_data, :from => 'MetaData', :as => MetaData
24
23
  xml_accessor :name, :from => 'Name'
25
24
  xml_accessor :description, :from => 'Description'
26
25
  xml_accessor :active, :from => 'Active'
27
- xml_accessor :parent_ref, :from => 'ParentRef', :as => Integer
28
26
  xml_accessor :sub_item, :from => 'SubItem'
29
- xml_accessor :unit_price, :from => 'UnitPrice', :as => Float
30
- xml_accessor :rate_percent, :from => 'RatePercent', :as => Float
31
- xml_accessor :type, :from => 'Type'
32
- xml_accessor :taxable, :from => 'Taxable'
33
- xml_accessor :asset_account_ref, :from => 'AssetAccountRef', :as => Integer
34
- xml_accessor :income_account_ref, :from => 'IncomeAccountRef', :as => Integer
35
- xml_accessor :purchase_desc, :from => 'PurchaseDesc'
36
- xml_accessor :purchase_cost, :from => 'PurchaseCost', :as => Float
37
- xml_accessor :expense_account_ref, :from => 'ExpenseAccountRef', :as => Integer
38
- xml_accessor :quantity_on_hand, :from => 'QtyOnHand', :as => Float
39
- xml_accessor :sales_tax_code_ref, :from => 'SalesTaxCodeRef', :as => Integer
40
- xml_accessor :purchase_tax_code_ref, :from => 'PurchaseTaxCodeRef', :as => Integer
41
- xml_accessor :track_quantity_on_hand, :from => 'TrackQtyOnHand'
42
- xml_accessor :asset_account, :from => 'AssetAccount', :as => Integer
27
+ xml_accessor :parent_ref, :from => 'ParentRef', :as => Integer
43
28
  xml_accessor :level, :from => 'Level', :as => Integer
29
+
30
+ # read-only
31
+ xml_accessor :fully_qualified_name, :from => 'FullyQualifiedName'
32
+
33
+ xml_accessor :taxable, :from => 'Taxable'
44
34
  xml_accessor :sales_tax_included, :from => 'SalesTaxIncluded'
35
+ xml_accessor :unit_price, :from => 'UnitPrice', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
36
+ xml_accessor :rate_percent, :from => 'RatePercent', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
37
+ xml_accessor :type, :from => 'Type'
38
+ xml_accessor :income_account_ref, :from => 'IncomeAccountRef', :as => BaseReference
39
+ xml_accessor :purchase_desc, :from => 'PurchaseDesc'
45
40
  xml_accessor :purchase_tax_included, :from => 'PurchaseTaxIncluded'
41
+ xml_accessor :purchase_cost, :from => 'PurchaseCost', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
42
+ xml_accessor :expense_account_ref, :from => 'ExpenseAccountRef', :as => BaseReference
43
+ xml_accessor :asset_account_ref, :from => 'AssetAccountRef', :as => BaseReference
44
+ xml_accessor :track_quantity_on_hand, :from => 'TrackQtyOnHand'
45
+ xml_accessor :quantity_on_hand, :from => 'QtyOnHand', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
46
+ xml_accessor :sales_tax_code_ref, :from => 'SalesTaxCodeRef', :as => BaseReference
47
+ xml_accessor :purchase_tax_code_ref, :from => 'PurchaseTaxCodeRef', :as => BaseReference
48
+ xml_accessor :inv_start_date, :from => 'InvStartDate', :as => Date
49
+
50
+ reference_setters :parent_ref, :income_account_ref, :expense_account_ref
51
+ reference_setters :asset_account_ref, :sales_tax_code_ref, :purchase_tax_code_ref
46
52
 
53
+ #== Validations
47
54
  validates_length_of :name, :minimum => 1
48
55
  validates_inclusion_of :type, :in => ITEM_TYPES
49
56
 
@@ -0,0 +1,28 @@
1
+ module Quickbooks
2
+ module Model
3
+ class Line < BaseModel
4
+ #== Constants
5
+ SALES_LINE_ITEM_DETAIL = 'SalesItemLineDetail'
6
+ SUB_TOTAL_LINE_DETAIL = 'SubTotalLineDetail'
7
+ PAYMENT_LINE_DETAIL = 'PaymentLineDetail'
8
+
9
+ xml_accessor :id, :from => 'Id', :as => Integer
10
+ xml_accessor :line_num, :from => 'LineNum', :as => Integer
11
+ xml_accessor :description, :from => 'Description'
12
+ xml_accessor :amount, :from => 'Amount', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
13
+ xml_accessor :detail_type, :from => 'DetailType'
14
+
15
+ #== Various detail types
16
+ xml_accessor :sales_item_line_detail, :from => 'SalesItemLineDetail', :as => SalesItemLineDetail
17
+ xml_accessor :sub_total_line_detail, :from => 'SubTotalLineDetail', :as => SubTotalLineDetail
18
+ xml_accessor :payment_line_detail, :from => 'PaymentLineDetail', :as => PaymentLineDetail
19
+
20
+ def sales_item!
21
+ self.detail_type = SALES_LINE_ITEM_DETAIL
22
+ self.sales_item_line_detail = SalesItemLineDetail.new
23
+
24
+ yield self.sales_item_line_detail if block_given?
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,10 +1,12 @@
1
1
  module Quickbooks
2
2
  module Model
3
3
  class PaymentLineDetail < BaseModel
4
- xml_accessor :item_ref, :from => 'ItemRef', :as => Integer
5
- xml_accessor :class_ref, :from => 'ClassRef', :as => Integer
6
- xml_accessor :balance, :from => 'Balance', :as => Float
7
- xml_accessor :discount, :from => 'Discount', :as => Quickbooks::Model::DiscountOverride
4
+ xml_accessor :item_ref, :from => 'ItemRef', :as => BaseReference
5
+ xml_accessor :class_ref, :from => 'ClassRef', :as => BaseReference
6
+ xml_accessor :balance, :from => 'Balance', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
7
+ xml_accessor :discount, :from => 'Discount', :as => DiscountOverride
8
+
9
+ reference_setters :item_ref, :class_ref
8
10
  end
9
11
  end
10
12
  end
@@ -0,0 +1,14 @@
1
+ module Quickbooks
2
+ module Model
3
+ class PaymentMethod < BaseModel
4
+ REST_RESOURCE = 'payment_method'
5
+ XML_COLLECTION_NODE = "PaymentMethod"
6
+ XML_NODE = "PaymentMethod"
7
+
8
+ xml_accessor :id, :from => 'Id', :as => Integer
9
+ xml_accessor :name, :from => 'Name'
10
+ xml_accessor :active, :from => 'Active'
11
+ xml_accessor :amount, :from => 'Amount', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
12
+ end
13
+ end
14
+ end
@@ -12,13 +12,29 @@ module Quickbooks
12
12
  xml_accessor :country_sub_division_code, :from => 'CountrySubDivisionCode'
13
13
  xml_accessor :postal_code, :from => 'PostalCode'
14
14
  xml_accessor :note, :from => 'Note'
15
- xml_accessor :lat, :from => 'Lat', :as => Float
16
- xml_accessor :lon, :from => 'Long', :as => Float
15
+ xml_accessor :lat, :from => 'Lat'
16
+ xml_accessor :lon, :from => 'Long'
17
17
 
18
18
  def zip
19
19
  postal_code
20
20
  end
21
21
 
22
+ def lat_to_f
23
+ BigDecimal.new(lat)
24
+ end
25
+
26
+ def lon_to_f
27
+ BigDecimal.new(lon)
28
+ end
29
+
30
+ def have_lat?
31
+ lat.to_s != "INVALID"
32
+ end
33
+
34
+ def have_lon?
35
+ lon.to_s != "INVALID"
36
+ end
37
+
22
38
  end
23
39
  end
24
40
  end
@@ -1,14 +1,16 @@
1
1
  module Quickbooks
2
2
  module Model
3
3
  class SalesItemLineDetail < BaseModel
4
- xml_accessor :item_ref, :from => 'ItemRef', :as => Integer
5
- xml_accessor :class_ref, :from => 'ClassRef', :as => Integer
6
- xml_accessor :unit_price, :from => 'UnitPrice', :as => Float
7
- xml_accessor :rate_percent, :from => 'RatePercent', :as => Float
8
- xml_accessor :price_level_ref, :from => 'PriceLevelRef', :as => Integer
9
- xml_accessor :quantity, :from => 'Qty', :as => Float
10
- xml_accessor :tax_code_ref, :from => 'TaxCodeRef'
4
+ xml_accessor :item_ref, :from => 'ItemRef', :as => BaseReference
5
+ xml_accessor :class_ref, :from => 'ClassRef', :as => BaseReference
6
+ xml_accessor :unit_price, :from => 'UnitPrice', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
7
+ xml_accessor :rate_percent, :from => 'RatePercent', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
8
+ xml_accessor :price_level_ref, :from => 'PriceLevelRef', :as => BaseReference
9
+ xml_accessor :quantity, :from => 'Qty', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
10
+ xml_accessor :tax_code_ref, :from => 'TaxCodeRef', :as => BaseReference
11
11
  xml_accessor :service_date, :from => 'ServiceDate', :as => Date
12
+
13
+ reference_setters :item_ref, :class_ref, :price_level_ref, :tax_code_ref
12
14
  end
13
15
  end
14
16
  end
@@ -0,0 +1,44 @@
1
+ module Quickbooks
2
+ module Model
3
+ class SalesReceipt < BaseModel
4
+ XML_COLLECTION_NODE = "SalesReceipt"
5
+ XML_NODE = "SalesReceipt"
6
+ REST_RESOURCE = 'salesreceipt'
7
+
8
+ xml_accessor :id, :from => 'Id', :as => Integer
9
+ xml_accessor :sync_token, :from => 'SyncToken', :as => Integer
10
+ xml_accessor :meta_data, :from => 'MetaData', :as => MetaData
11
+ xml_accessor :doc_number, :from => 'DocNumber'
12
+ xml_accessor :placed_on, :from => 'TxnDate', :as => Time
13
+
14
+ xml_accessor :line_items, :from => 'Line', :as => [Line]
15
+ xml_accessor :customer_ref, :from => 'CustomerRef', :as => BaseReference
16
+ xml_accessor :bill_email, :from => 'BillEmail', :as => EmailAddress
17
+ xml_accessor :bill_address, :from => 'BillAddr', :as => PhysicalAddress
18
+ xml_accessor :ship_address, :from => 'ShipAddr', :as => PhysicalAddress
19
+
20
+ xml_accessor :po_number, :from => 'PONumber'
21
+
22
+ xml_accessor :ship_method_ref, :from => 'ShipMethodRef', :as => BaseReference
23
+ xml_accessor :ship_date, :from => 'ShipDate', :as => Time
24
+ xml_accessor :tracking_num, :from => 'TrackingNum'
25
+
26
+ xml_accessor :payment_method_ref, :from => 'PaymentMethodRef', :as => BaseReference
27
+ xml_accessor :payment_ref_number, :from => 'PaymentRefNum'
28
+
29
+ xml_accessor :deposit_to_account_ref, :from => 'DepositToAccountRef', :as => BaseReference
30
+
31
+ # readonly
32
+ xml_accessor :total, :from => 'TotalAmt', :as => BigDecimal
33
+
34
+ reference_setters :customer_ref, :ship_method_ref, :payment_method_ref, :deposit_to_account_ref
35
+
36
+ validates_length_of :line_items, :minimum => 1
37
+
38
+ def email=(email)
39
+ self.bill_email = EmailAddress.new(email)
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -1,11 +1,13 @@
1
1
  module Quickbooks
2
2
  module Model
3
3
  class SubTotalLineDetail < BaseModel
4
- xml_accessor :item_ref, :from => 'ItemRef', :as => Integer
5
- xml_accessor :class_ref, :from => 'ClassRef'
6
- xml_accessor :unit_price, :from => 'UnitPrice', :as => Float
7
- xml_accessor :quantity, :from => 'Qty', :as => Float
8
- xml_accessor :tax_code_ref, :from => 'TaxCodeRef'
4
+ xml_accessor :item_ref, :from => 'ItemRef', :as => BaseReference
5
+ xml_accessor :class_ref, :from => 'ClassRef', :as => BaseReference
6
+ xml_accessor :unit_price, :from => 'UnitPrice', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
7
+ xml_accessor :quantity, :from => 'Qty', :as => BigDecimal, :to_xml => Proc.new { |val| val.to_f }
8
+ xml_accessor :tax_code_ref, :from => 'TaxCodeRef', :as => BaseReference
9
+
10
+ reference_setters :item_ref, :class_ref, :tax_code_ref
9
11
  end
10
12
  end
11
13
  end
@@ -0,0 +1,22 @@
1
+ module Quickbooks
2
+ module Service
3
+ class Account < BaseService
4
+ include ServiceCrud
5
+
6
+ def delete(account)
7
+ account.active = false
8
+ update(account, :sparse => true)
9
+ end
10
+
11
+ private
12
+
13
+ def default_model_query
14
+ "SELECT * FROM ACCOUNT"
15
+ end
16
+
17
+ def model
18
+ Quickbooks::Model::Account
19
+ end
20
+ end
21
+ end
22
+ end
@@ -2,14 +2,19 @@
2
2
  require 'uri'
3
3
  require 'cgi'
4
4
 
5
- class IntuitRequestException < StandardError
6
- attr_accessor :message, :code, :detail, :type
7
- def initialize(msg)
8
- self.message = msg
9
- super(msg)
5
+ unless Quickbooks::Util::ClassUtil.defined?("InvalidModelException")
6
+ class IntuitRequestException < StandardError
7
+ attr_accessor :message, :code, :detail, :type
8
+ def initialize(msg)
9
+ self.message = msg
10
+ super(msg)
11
+ end
10
12
  end
11
13
  end
12
- class AuthorizationFailure < StandardError; end
14
+
15
+ unless Quickbooks::Util::ClassUtil.defined?("InvalidModelException")
16
+ class AuthorizationFailure < StandardError; end
17
+ end
13
18
 
14
19
  module Quickbooks
15
20
  module Service
@@ -25,6 +30,7 @@ module Quickbooks
25
30
  XML_NS = %{xmlns="http://schema.intuit.com/finance/v3"}
26
31
  HTTP_CONTENT_TYPE = 'application/xml'
27
32
  HTTP_ACCEPT = 'application/xml'
33
+ HTTP_ACCEPT_ENCODING = 'gzip, deflate'
28
34
 
29
35
  def initialize()
30
36
  @base_uri = 'https://qb.sbfinance.intuit.com/v3/company'
@@ -51,19 +57,17 @@ module Quickbooks
51
57
  "#{@base_uri}/#{@company_id}"
52
58
  end
53
59
 
54
- def url_for_query(query = "")
55
- "#{url_for_base}/query?query=#{URI.encode(query)}"
60
+ def url_for_query(query = nil, start_position = 1, max_results = 20)
61
+ query ||= default_model_query
62
+ query = "#{query} STARTPOSITION #{start_position} MAXRESULTS #{max_results}"
63
+
64
+ "#{url_for_base}/query?query=#{URI.encode_www_form_component(query)}"
56
65
  end
57
66
 
58
67
  private
59
68
 
60
69
  def parse_xml(xml)
61
- @last_response_xml =
62
- begin
63
- x = Nokogiri::XML(xml)
64
- #x.document.remove_namespaces!
65
- x
66
- end
70
+ @last_response_xml = Nokogiri::XML(xml)
67
71
  end
68
72
 
69
73
  def valid_xml_document(xml)
@@ -94,43 +98,11 @@ module Quickbooks
94
98
  end
95
99
 
96
100
  max_results = (page * per_page)
97
-
98
- query = "#{query} STARTPOSITION #{start_position} MAXRESULTS #{max_results}"
99
- response = do_http_get(url_for_query(query))
101
+ response = do_http_get(url_for_query(query, start_position, max_results))
100
102
 
101
103
  parse_collection(response, model)
102
104
  end
103
105
 
104
- #
105
- # def fetch_collection2(model, custom_field_query = nil, filters = [], page = 1, per_page = 20, sort = nil, options ={})
106
- # raise ArgumentError, "missing model to instantiate" if model.nil?
107
- #
108
- # post_body_tags = []
109
- #
110
- # # pagination parameters must come first
111
- # post_body_tags << "<StartPage>#{page}</StartPage>"
112
- # post_body_tags << "<ChunkSize>#{per_page}</ChunkSize>"
113
- #
114
- # # ... followed by any filters
115
- # if filters.is_a?(Array) && filters.length > 0
116
- # filters = enforce_filter_order(filters).compact
117
- # post_body_tags << filters.collect { |f| f.to_xml }
118
- # post_body_tags.flatten!
119
- # end
120
- #
121
- # if sort
122
- # post_body_tags << sort.to_xml
123
- # end
124
- #
125
- # post_body_tags << custom_field_query
126
- #
127
- # xml_query_tag = "#{model::XML_NODE}Query"
128
- # body = %Q{<?xml version="1.0" encoding="utf-8"?>\n<#{xml_query_tag} xmlns="http://www.intuit.com/sb/cdm/v2">#{post_body_tags.join}</#{xml_query_tag}>}
129
- #
130
- # response = do_http_post(url_for_resource(model::REST_RESOURCE), body, {}, {'Content-Type' => 'text/xml'})
131
- # parse_collection(response, model)
132
- # end
133
-
134
106
  def parse_collection(response, model)
135
107
  if response
136
108
  collection = Quickbooks::Collection.new
@@ -205,13 +177,14 @@ module Quickbooks
205
177
  unless headers.has_key?('Content-Type')
206
178
  headers['Content-Type'] = 'text/xml'
207
179
  end
180
+
208
181
  response = do_http_post(url, body.strip, params, headers)
209
182
 
210
183
  result = nil
211
184
  if response
212
185
  case response.code.to_i
213
186
  when 200
214
- result = Quickbooks::Model::RestResponse.from_xml(response.body)
187
+ result = Quickbooks::Model::RestResponse.from_xml(response.plain_body)
215
188
  when 401
216
189
  raise IntuitRequestException.new("Authorization failure: token timed out?")
217
190
  when 404
@@ -235,14 +208,28 @@ module Quickbooks
235
208
  raise "OAuth client has not been initialized. Initialize with setter access_token="
236
209
  end
237
210
  unless headers.has_key?('Content-Type')
238
- headers.merge!({'Content-Type' => HTTP_CONTENT_TYPE})
211
+ headers['Content-Type'] = HTTP_CONTENT_TYPE
212
+ end
213
+ unless headers.has_key?('Accept')
214
+ headers['Accept'] = HTTP_ACCEPT
215
+ end
216
+ unless headers.has_key?('Accept-Encoding')
217
+ headers['Accept-Encoding'] = HTTP_ACCEPT_ENCODING
239
218
  end
240
- # log "------ New Request ------"
241
- # log "METHOD = #{method}"
242
- # log "RESOURCE = #{url}"
243
- # log "BODY(#{body.class}) = #{body == nil ? "<NIL>" : body.inspect}"
244
- # log "HEADERS = #{headers.inspect}"
245
- response = @oauth.request(method, url, body, headers)
219
+
220
+ #log "METHOD = #{method}"
221
+ #log "RESOURCE = #{url}"
222
+ #log "BODY(#{body.class}) = #{body == nil ? "<NIL>" : body.inspect}"
223
+ #log "HEADERS = #{headers.inspect}"
224
+
225
+ response = case method
226
+ when :get
227
+ @oauth.get(url, headers)
228
+ when :post
229
+ @oauth.post(url, body, headers)
230
+ else
231
+ raise "Dont know how to perform that HTTP operation"
232
+ end
246
233
  check_response(response)
247
234
  end
248
235
 
@@ -255,9 +242,7 @@ module Quickbooks
255
242
  end
256
243
 
257
244
  def check_response(response)
258
- # puts "RESPONSE CODE = #{response.code}"
259
- # puts "RESPONSE BODY = #{response.body}"
260
- parse_xml(response.body)
245
+ parse_xml(response.plain_body)
261
246
  status = response.code.to_i
262
247
  case status
263
248
  when 200
@@ -274,13 +259,13 @@ module Quickbooks
274
259
  when 400, 500
275
260
  parse_and_raise_exception
276
261
  else
277
- raise "HTTP Error Code: #{status}, Msg: #{response.body}"
262
+ raise "HTTP Error Code: #{status}, Msg: #{response.plain_body}"
278
263
  end
279
264
  end
280
265
 
281
266
  def parse_and_raise_exception
282
267
  err = parse_intuit_error
283
- ex = IntuitRequestException.new(err[:message])
268
+ ex = IntuitRequestException.new("#{err[:message]}:\n\t#{err[:detail]}")
284
269
  ex.code = err[:code]
285
270
  ex.detail = err[:detail]
286
271
  ex.type = err[:type]