xeroizer-float 2.15.3.1

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 (337) hide show
  1. data/.bundle/config +2 -0
  2. data/.gitattributes +22 -0
  3. data/Gemfile +19 -0
  4. data/Gemfile.lock +57 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +529 -0
  7. data/Rakefile +55 -0
  8. data/VERSION +1 -0
  9. data/lib/big_decimal_to_s.rb +9 -0
  10. data/lib/class_level_inheritable_attributes.rb +25 -0
  11. data/lib/xeroizer.rb +64 -0
  12. data/lib/xeroizer/application_http_proxy.rb +30 -0
  13. data/lib/xeroizer/ca-certificates.crt +2642 -0
  14. data/lib/xeroizer/configuration.rb +19 -0
  15. data/lib/xeroizer/exceptions.rb +129 -0
  16. data/lib/xeroizer/generic_application.rb +54 -0
  17. data/lib/xeroizer/http.rb +167 -0
  18. data/lib/xeroizer/http_encoding_helper.rb +49 -0
  19. data/lib/xeroizer/logging.rb +8 -0
  20. data/lib/xeroizer/models/account.rb +67 -0
  21. data/lib/xeroizer/models/address.rb +32 -0
  22. data/lib/xeroizer/models/bank_account.rb +12 -0
  23. data/lib/xeroizer/models/bank_transaction.rb +75 -0
  24. data/lib/xeroizer/models/branding_theme.rb +22 -0
  25. data/lib/xeroizer/models/contact.rb +49 -0
  26. data/lib/xeroizer/models/contact_group.rb +16 -0
  27. data/lib/xeroizer/models/credit_note.rb +130 -0
  28. data/lib/xeroizer/models/currency.rb +18 -0
  29. data/lib/xeroizer/models/employee.rb +28 -0
  30. data/lib/xeroizer/models/external_link.rb +16 -0
  31. data/lib/xeroizer/models/invoice.rb +192 -0
  32. data/lib/xeroizer/models/item.rb +27 -0
  33. data/lib/xeroizer/models/item_purchase_details.rb +19 -0
  34. data/lib/xeroizer/models/item_sales_details.rb +19 -0
  35. data/lib/xeroizer/models/journal.rb +25 -0
  36. data/lib/xeroizer/models/journal_line.rb +28 -0
  37. data/lib/xeroizer/models/journal_line_tracking_category.rb +20 -0
  38. data/lib/xeroizer/models/line_amount_type.rb +11 -0
  39. data/lib/xeroizer/models/line_item.rb +40 -0
  40. data/lib/xeroizer/models/line_item_sum.rb +21 -0
  41. data/lib/xeroizer/models/manual_journal.rb +42 -0
  42. data/lib/xeroizer/models/manual_journal_line.rb +27 -0
  43. data/lib/xeroizer/models/option.rb +18 -0
  44. data/lib/xeroizer/models/organisation.rb +34 -0
  45. data/lib/xeroizer/models/payment.rb +42 -0
  46. data/lib/xeroizer/models/phone.rb +25 -0
  47. data/lib/xeroizer/models/tax_rate.rb +25 -0
  48. data/lib/xeroizer/models/tracking_category.rb +23 -0
  49. data/lib/xeroizer/models/tracking_category_child.rb +20 -0
  50. data/lib/xeroizer/oauth.rb +130 -0
  51. data/lib/xeroizer/partner_application.rb +46 -0
  52. data/lib/xeroizer/private_application.rb +27 -0
  53. data/lib/xeroizer/public_application.rb +21 -0
  54. data/lib/xeroizer/record/application_helper.rb +32 -0
  55. data/lib/xeroizer/record/base.rb +155 -0
  56. data/lib/xeroizer/record/base_model.rb +144 -0
  57. data/lib/xeroizer/record/base_model_http_proxy.rb +117 -0
  58. data/lib/xeroizer/record/model_definition_helper.rb +99 -0
  59. data/lib/xeroizer/record/record_association_helper.rb +140 -0
  60. data/lib/xeroizer/record/validation_helper.rb +71 -0
  61. data/lib/xeroizer/record/validators/associated_validator.rb +33 -0
  62. data/lib/xeroizer/record/validators/block_validator.rb +22 -0
  63. data/lib/xeroizer/record/validators/inclusion_of_validator.rb +22 -0
  64. data/lib/xeroizer/record/validators/presence_of_validator.rb +19 -0
  65. data/lib/xeroizer/record/validators/validator.rb +33 -0
  66. data/lib/xeroizer/record/xml_helper.rb +133 -0
  67. data/lib/xeroizer/report/aged_receivables_by_contact.rb +43 -0
  68. data/lib/xeroizer/report/base.rb +43 -0
  69. data/lib/xeroizer/report/cell.rb +32 -0
  70. data/lib/xeroizer/report/cell_xml_helper.rb +74 -0
  71. data/lib/xeroizer/report/factory.rb +53 -0
  72. data/lib/xeroizer/report/row/header.rb +12 -0
  73. data/lib/xeroizer/report/row/row.rb +48 -0
  74. data/lib/xeroizer/report/row/section.rb +10 -0
  75. data/lib/xeroizer/report/row/summary.rb +9 -0
  76. data/lib/xeroizer/report/row/xml_helper.rb +77 -0
  77. data/lib/xeroizer/report/xml_helper.rb +58 -0
  78. data/lib/xeroizer/response.rb +55 -0
  79. data/test/acceptance/about_creating_bank_transactions_test.rb +162 -0
  80. data/test/acceptance/about_fetching_bank_transactions_test.rb +56 -0
  81. data/test/acceptance/acceptance_test.rb +53 -0
  82. data/test/acceptance/bank_transaction_reference_data.rb +31 -0
  83. data/test/stub_responses/accounts.xml +589 -0
  84. data/test/stub_responses/api_exception.xml +153 -0
  85. data/test/stub_responses/bogus_oauth_error +1 -0
  86. data/test/stub_responses/branding_themes.xml +20 -0
  87. data/test/stub_responses/contact.xml +40 -0
  88. data/test/stub_responses/contacts.xml +0 -0
  89. data/test/stub_responses/create_credit_note.xml +104 -0
  90. data/test/stub_responses/create_invoice.xml +64 -0
  91. data/test/stub_responses/credit_note.xml +75 -0
  92. data/test/stub_responses/credit_note_not_found_error.xml +1 -0
  93. data/test/stub_responses/credit_notes.xml +169 -0
  94. data/test/stub_responses/currencies.xml +12 -0
  95. data/test/stub_responses/employees.xml +29 -0
  96. data/test/stub_responses/invalid_api_key_error.xml +1 -0
  97. data/test/stub_responses/invalid_consumer_key +1 -0
  98. data/test/stub_responses/invalid_request_token +1 -0
  99. data/test/stub_responses/invoice.xml +84 -0
  100. data/test/stub_responses/invoice_not_found_error.xml +1 -0
  101. data/test/stub_responses/invoices.xml +1899 -0
  102. data/test/stub_responses/items.xml +112 -0
  103. data/test/stub_responses/manual_journal.xml +45 -0
  104. data/test/stub_responses/manual_journals.xml +40 -0
  105. data/test/stub_responses/organisation.xml +25 -0
  106. data/test/stub_responses/organisations.xml +25 -0
  107. data/test/stub_responses/payments.xml +1121 -0
  108. data/test/stub_responses/rate_limit_exceeded +1 -0
  109. data/test/stub_responses/records/contact-043892a1-aef1-4c18-88d8-b8ccb6d31466.xml +38 -0
  110. data/test/stub_responses/records/contact-09664078-efe2-4a88-89a5-67eac9b0047b.xml +40 -0
  111. data/test/stub_responses/records/contact-0a4cf37b-a1a8-4753-9ee2-f9207f63a8ff.xml +48 -0
  112. data/test/stub_responses/records/contact-0e74f929-11b9-4255-a035-1fdfe573e676.xml +40 -0
  113. data/test/stub_responses/records/contact-0f471ca5-15c9-405e-a1b9-7cc35194b673.xml +38 -0
  114. data/test/stub_responses/records/contact-13cd4c47-baa6-4f07-93f6-6442310df4bf.xml +47 -0
  115. data/test/stub_responses/records/contact-158a2667-82ee-43bf-8f33-a6cc9524092d.xml +38 -0
  116. data/test/stub_responses/records/contact-17465072-6fa3-40bf-bc42-97765d9e1bea.xml +38 -0
  117. data/test/stub_responses/records/contact-1975b0ed-b7ba-4c61-bae8-2aa6d78b0dee.xml +39 -0
  118. data/test/stub_responses/records/contact-1b2be6e9-8d58-4da9-aaf8-4fe5471b653c.xml +53 -0
  119. data/test/stub_responses/records/contact-1c40da58-fe1d-4e97-b729-b2abdae94d9e.xml +38 -0
  120. data/test/stub_responses/records/contact-258176a5-c622-4394-9c94-6f88c3ea12e5.xml +40 -0
  121. data/test/stub_responses/records/contact-299dd3a0-a417-4a37-8a04-2f55e91963e5.xml +40 -0
  122. data/test/stub_responses/records/contact-2be39278-5154-4ed1-8eb0-676f25acfc66.xml +40 -0
  123. data/test/stub_responses/records/contact-2e58cff6-488c-4a32-884b-baf848010229.xml +40 -0
  124. data/test/stub_responses/records/contact-2faccd41-935e-40aa-b74e-e2fc28ac34c3.xml +38 -0
  125. data/test/stub_responses/records/contact-31af01e7-2ca7-45b9-a500-b02db996568e.xml +38 -0
  126. data/test/stub_responses/records/contact-344f1113-a25b-4344-b82e-bedeacc17c8e.xml +40 -0
  127. data/test/stub_responses/records/contact-3e776c4b-ea9e-4bb1-96be-6b0c7a71a37f.xml +39 -0
  128. data/test/stub_responses/records/contact-3fc1fc6c-e5ff-4e40-b6f3-7eb535637d87.xml +38 -0
  129. data/test/stub_responses/records/contact-416ab20c-5357-4beb-a740-e8d175d71efb.xml +38 -0
  130. data/test/stub_responses/records/contact-41a42865-f15a-4fa1-b643-47877608f557.xml +54 -0
  131. data/test/stub_responses/records/contact-42771b60-19a7-4692-af81-dd9f9b9362d4.xml +43 -0
  132. data/test/stub_responses/records/contact-451ceb28-9610-44c9-8f35-3225482f2413.xml +40 -0
  133. data/test/stub_responses/records/contact-4ab343ad-1ebb-4afe-9d48-1814a93c2081.xml +38 -0
  134. data/test/stub_responses/records/contact-4bb77692-42d4-4565-85a0-8849eb85e039.xml +39 -0
  135. data/test/stub_responses/records/contact-4dec292f-3ab7-46a8-83e4-5fb5eac42c7f.xml +40 -0
  136. data/test/stub_responses/records/contact-4e2f192e-8397-4d4d-97ca-a4fc5ac531bf.xml +38 -0
  137. data/test/stub_responses/records/contact-5188c17c-7786-4436-ad6e-9da2997386d0.xml +40 -0
  138. data/test/stub_responses/records/contact-52442753-b1c4-40b7-9b79-c33997de5837.xml +40 -0
  139. data/test/stub_responses/records/contact-565acaa9-e7f3-4fbf-80c3-16b081ddae10.xml +38 -0
  140. data/test/stub_responses/records/contact-571a2414-81ff-4f8f-8498-d91d83793131.xml +44 -0
  141. data/test/stub_responses/records/contact-58697449-85ef-46ae-83fc-6a9446f037fb.xml +40 -0
  142. data/test/stub_responses/records/contact-58bf2ae3-5144-4628-8de2-e165ac2bcdc6.xml +40 -0
  143. data/test/stub_responses/records/contact-5d41dafd-eb7e-42c1-bd5a-ba3be1da0960.xml +38 -0
  144. data/test/stub_responses/records/contact-5f005a09-5ce4-4fb4-8096-e69c18be636e.xml +38 -0
  145. data/test/stub_responses/records/contact-60d578d9-3e10-4aef-b5dc-9d9fd60a3633.xml +47 -0
  146. data/test/stub_responses/records/contact-62392126-dba4-4a75-b907-5875ebf75259.xml +40 -0
  147. data/test/stub_responses/records/contact-642c7fb5-e8e5-48e1-a710-39a18c6c3217.xml +40 -0
  148. data/test/stub_responses/records/contact-64aebf9c-bb89-4b38-b99b-405bd1ece6fd.xml +40 -0
  149. data/test/stub_responses/records/contact-64eedbc9-1fa0-485a-837f-705f23188161.xml +38 -0
  150. data/test/stub_responses/records/contact-65e96c9f-1595-4653-9a8a-2a36d49223c2.xml +40 -0
  151. data/test/stub_responses/records/contact-67d26b93-ccb4-4890-9bf1-284b70ea755d.xml +38 -0
  152. data/test/stub_responses/records/contact-69d3e538-44b3-4e00-a5f6-7dddcb6e0656.xml +40 -0
  153. data/test/stub_responses/records/contact-6a8450bc-f81a-4bb0-a8f6-aa4afe9497c7.xml +40 -0
  154. data/test/stub_responses/records/contact-6c70e424-41d6-4b9b-af3e-b3a9f3589106.xml +40 -0
  155. data/test/stub_responses/records/contact-6de0b0cf-560c-4503-aab3-e1543c329deb.xml +54 -0
  156. data/test/stub_responses/records/contact-72dd6a02-396e-42a2-a4d6-cc3fa75dfece.xml +41 -0
  157. data/test/stub_responses/records/contact-755f1475-d255-43a8-bedc-5ea7fd26c71f.xml +51 -0
  158. data/test/stub_responses/records/contact-78a9d0a0-3d8c-4f84-af3e-f260bf4a9dc0.xml +38 -0
  159. data/test/stub_responses/records/contact-79aa39ca-22b0-42c2-9026-78757a29d665.xml +42 -0
  160. data/test/stub_responses/records/contact-804f4140-5978-48fe-ba20-b56e5b834b18.xml +40 -0
  161. data/test/stub_responses/records/contact-812d4f28-1681-4241-8e34-d15c5520ba35.xml +38 -0
  162. data/test/stub_responses/records/contact-860b99a9-0958-4c8d-a98f-bb1f092b16bb.xml +60 -0
  163. data/test/stub_responses/records/contact-87c8da45-97cc-46be-b170-398da0eacfb8.xml +40 -0
  164. data/test/stub_responses/records/contact-8a154a19-6c6c-404b-bbc9-6deae2d18251.xml +38 -0
  165. data/test/stub_responses/records/contact-8bb6931d-2865-44e9-9a23-ed1fb9c7a46c.xml +40 -0
  166. data/test/stub_responses/records/contact-936c9759-01da-4063-b472-424ab9f48212.xml +38 -0
  167. data/test/stub_responses/records/contact-9d12a994-9640-4b75-95cc-3de1e9d0ef09.xml +38 -0
  168. data/test/stub_responses/records/contact-9fe59245-1fbb-4157-93c3-dc97388f3746.xml +40 -0
  169. data/test/stub_responses/records/contact-a06a7225-6f8a-4522-8400-c534dd43a16e.xml +40 -0
  170. data/test/stub_responses/records/contact-a76a85fe-73a2-46fa-aba7-791f36103cdb.xml +40 -0
  171. data/test/stub_responses/records/contact-a93b5f40-0346-4d21-9181-431e129911c0.xml +40 -0
  172. data/test/stub_responses/records/contact-abf272dd-6b1d-4829-af88-c57bf55855e3.xml +38 -0
  173. data/test/stub_responses/records/contact-ad24c33b-256b-4157-ad56-cbcf0e8db7b1.xml +47 -0
  174. data/test/stub_responses/records/contact-b107129d-f4c9-438e-9573-64b778527f4a.xml +40 -0
  175. data/test/stub_responses/records/contact-b233288a-aa26-4b26-9fc7-779d797dd56f.xml +40 -0
  176. data/test/stub_responses/records/contact-b2b5333a-2546-4975-891f-d71a8a640d23.xml +38 -0
  177. data/test/stub_responses/records/contact-b4d149bf-1823-4bd2-96da-9032388c9686.xml +40 -0
  178. data/test/stub_responses/records/contact-b78d4fd1-4306-4d83-a0b9-61458d1c53a2.xml +40 -0
  179. data/test/stub_responses/records/contact-b7d108a8-d5f7-4f16-a7c9-26eaed98e8de.xml +40 -0
  180. data/test/stub_responses/records/contact-baeed0f3-7989-4874-99b3-59f23032cb73.xml +38 -0
  181. data/test/stub_responses/records/contact-bc51a3a1-b7f6-46ca-ac9e-19b87e6ca100.xml +40 -0
  182. data/test/stub_responses/records/contact-be9f3aab-52f5-4d9c-94b4-87f7d9e5ee8b.xml +38 -0
  183. data/test/stub_responses/records/contact-c135f994-01e4-427b-9e15-acfe8a477c16.xml +49 -0
  184. data/test/stub_responses/records/contact-c14edf75-15e4-4a9c-86e4-f52e2fe7cfa4.xml +40 -0
  185. data/test/stub_responses/records/contact-ca9b9abc-c2dc-4221-8101-31f464d314cc.xml +44 -0
  186. data/test/stub_responses/records/contact-cc4db604-9ed8-4eef-8a29-51b5b70496a0.xml +38 -0
  187. data/test/stub_responses/records/contact-cce9b044-be4a-43b3-9dc7-c027d8dd35b2.xml +38 -0
  188. data/test/stub_responses/records/contact-d0cd2c4f-18a0-4f7c-a32a-2db00f29d298.xml +43 -0
  189. data/test/stub_responses/records/contact-d6851dc2-9ed9-4515-bc0b-810b09c06a6a.xml +38 -0
  190. data/test/stub_responses/records/contact-d6a384fb-f46f-41a3-8ac7-b7bc9e0b5efa.xml +46 -0
  191. data/test/stub_responses/records/contact-d74e61cf-2ad0-4f0d-b9d1-6a808e3f70cf.xml +40 -0
  192. data/test/stub_responses/records/contact-d9ab0f61-3b56-4e2b-be39-f33c11bd99e3.xml +40 -0
  193. data/test/stub_responses/records/contact-dbb1f0b5-a71b-4458-8462-104acd0fec6b.xml +38 -0
  194. data/test/stub_responses/records/contact-dd981bd6-40dd-496d-a282-bf7d3391b8b9.xml +40 -0
  195. data/test/stub_responses/records/contact-e1826204-cc0a-42a5-a6d0-4b352d9d5953.xml +40 -0
  196. data/test/stub_responses/records/contact-e2d955db-f366-42dd-87f7-fbdb4da2306f.xml +40 -0
  197. data/test/stub_responses/records/contact-e32e2130-3d27-443a-8313-48fffa03cf53.xml +40 -0
  198. data/test/stub_responses/records/contact-e3a68332-d322-4816-8678-73a537c8cd33.xml +38 -0
  199. data/test/stub_responses/records/contact-e6ac76a3-ca32-4fa1-8ef9-6a4bf8b0ec2a.xml +40 -0
  200. data/test/stub_responses/records/contact-e6ca965d-7c48-480e-be39-e847307f474a.xml +38 -0
  201. data/test/stub_responses/records/contact-e77d1f20-2e8e-46ec-9a10-50335a216724.xml +40 -0
  202. data/test/stub_responses/records/contact-e8b98c13-a424-41d2-ba0e-7b7621411e7a.xml +38 -0
  203. data/test/stub_responses/records/contact-e8e9a2c2-3e7e-48ed-8528-c3d61b28f276.xml +39 -0
  204. data/test/stub_responses/records/contact-eb43fcc6-87ec-4a0a-b243-d718bee4e2cb.xml +38 -0
  205. data/test/stub_responses/records/contact-ef6f54c1-eb45-4956-b8cd-1be82ad665f2.xml +43 -0
  206. data/test/stub_responses/records/contact-efdb3600-f233-42e2-8f18-ce7e2a95e4b1.xml +38 -0
  207. data/test/stub_responses/records/contact-f7eca431-5c97-4d24-93fd-004bb8a6c644.xml +40 -0
  208. data/test/stub_responses/records/contact-fb078879-5d6d-474f-825f-61dc90689349.xml +38 -0
  209. data/test/stub_responses/records/contact-fc39b273-4aa2-4785-99ca-24672f6c0000.xml +38 -0
  210. data/test/stub_responses/records/contact-fc9ec3a6-a2fe-4300-a8cb-ca8a0b3662e0.xml +40 -0
  211. data/test/stub_responses/records/contact-fdf96102-7491-44b6-bf4d-7a77ff25f890.xml +40 -0
  212. data/test/stub_responses/records/contact-fe61ead1-8afc-4f0b-beda-066620227aad.xml +38 -0
  213. data/test/stub_responses/records/credit_note-371cd138-1e5c-4ec1-a8c6-a1c10e8bdab1.xml +73 -0
  214. data/test/stub_responses/records/credit_note-3bffc09b-79f2-490d-b91b-c59b700b43a4.xml +95 -0
  215. data/test/stub_responses/records/credit_note-43c678ee-f357-48e2-b192-b6e3634762f9.xml +94 -0
  216. data/test/stub_responses/records/credit_note-482c018b-d329-4e05-9b4f-7a4cfc695aa0.xml +77 -0
  217. data/test/stub_responses/records/credit_note-4f67130a-749a-4ee6-98b2-743adbc11245.xml +62 -0
  218. data/test/stub_responses/records/credit_note-50e98404-2fba-4031-af67-8ba4bb227c44.xml +77 -0
  219. data/test/stub_responses/records/credit_note-7df8949c-b71f-40c0-bbcf-39f2f450f286.xml +75 -0
  220. data/test/stub_responses/records/credit_note-b356e488-2678-4be4-ad4b-d294df2d48d6.xml +78 -0
  221. data/test/stub_responses/records/invoice-0032f627-3156-4d30-9b1c-4d3b994dc921.xml +84 -0
  222. data/test/stub_responses/records/invoice-00c9511b-24b9-4190-a90a-8abf2fe9f4a0.xml +76 -0
  223. data/test/stub_responses/records/invoice-024d7994-a26c-4c20-9894-13934840fc31.xml +74 -0
  224. data/test/stub_responses/records/invoice-0e64a623-c2a1-446a-93ed-eb897f118cbc.xml +97 -0
  225. data/test/stub_responses/records/invoice-15e88e57-2554-4496-a18e-eb3f5c622345.xml +75 -0
  226. data/test/stub_responses/records/invoice-166f0588-d0ba-458c-b28a-8edd4c8fc463.xml +75 -0
  227. data/test/stub_responses/records/invoice-1d1ba340-afa2-4f4c-8ff7-a147bda9a47b.xml +93 -0
  228. data/test/stub_responses/records/invoice-290ef4c4-baec-492b-b4dd-c102826470ae.xml +87 -0
  229. data/test/stub_responses/records/invoice-30a87092-31b5-4a2c-831e-327486533dd2.xml +79 -0
  230. data/test/stub_responses/records/invoice-30dbd181-72a8-43df-b392-4241bf43d5fc.xml +79 -0
  231. data/test/stub_responses/records/invoice-33e4123e-7cdd-4f05-9a0a-eb8adeb2b868.xml +94 -0
  232. data/test/stub_responses/records/invoice-387db692-26ac-47e6-b6cc-015343809bda.xml +75 -0
  233. data/test/stub_responses/records/invoice-3b28bf11-ed2f-4cf4-8e9e-fcae730cc292.xml +91 -0
  234. data/test/stub_responses/records/invoice-3fcb9847-b350-412e-ab90-7d9d774ad881.xml +91 -0
  235. data/test/stub_responses/records/invoice-440613e4-4785-4eff-9ba1-c432816cf8c7.xml +78 -0
  236. data/test/stub_responses/records/invoice-4602eda6-abe9-448e-b65f-ae6bea21f0eb.xml +98 -0
  237. data/test/stub_responses/records/invoice-46441f63-873f-4cdc-a278-b8fe516f3abb.xml +94 -0
  238. data/test/stub_responses/records/invoice-4ad1ec01-f4a3-41d7-bbb4-d2ab2fec8e65.xml +74 -0
  239. data/test/stub_responses/records/invoice-4b9afceb-f7c7-4e64-8aac-7b009971fd52.xml +86 -0
  240. data/test/stub_responses/records/invoice-4edbf6d5-4e92-43af-bedd-7effc0b86833.xml +70 -0
  241. data/test/stub_responses/records/invoice-4fad1af2-b871-4ac5-a15a-3c5e32d2e2c4.xml +93 -0
  242. data/test/stub_responses/records/invoice-52ee4d67-cae4-462c-adb2-182c39017f3d.xml +83 -0
  243. data/test/stub_responses/records/invoice-54585f46-c1a0-4432-bd4f-c1fae2fba59b.xml +67 -0
  244. data/test/stub_responses/records/invoice-5613938b-9e27-472e-92ae-3b038b669d10.xml +87 -0
  245. data/test/stub_responses/records/invoice-5aa9451d-95d1-4f95-a966-bbab2573f71c.xml +75 -0
  246. data/test/stub_responses/records/invoice-5aadcd34-01a9-4b8d-a2bb-d7cc1de9fa45.xml +89 -0
  247. data/test/stub_responses/records/invoice-5f6deadf-36a2-495a-9980-ceb11e8af9a9.xml +85 -0
  248. data/test/stub_responses/records/invoice-625ffe1b-f5d8-438e-a376-981de5f5a733.xml +77 -0
  249. data/test/stub_responses/records/invoice-64cd559e-8e03-46af-b461-8555285cee71.xml +86 -0
  250. data/test/stub_responses/records/invoice-666f8dbb-bc9a-476c-8ec4-4665d7f83190.xml +63 -0
  251. data/test/stub_responses/records/invoice-66fbe37f-49b1-43fd-97ed-85114022cd2f.xml +79 -0
  252. data/test/stub_responses/records/invoice-673dd7cc-beb7-4697-83d4-0c47cb400cc2.xml +95 -0
  253. data/test/stub_responses/records/invoice-69fc971e-9b37-41c5-9c87-174330f22343.xml +66 -0
  254. data/test/stub_responses/records/invoice-70e6db69-e5a4-42c7-a397-aa3212c2945f.xml +75 -0
  255. data/test/stub_responses/records/invoice-762aa45d-4632-45b5-8087-b4f47690665e.xml +54 -0
  256. data/test/stub_responses/records/invoice-766d1289-b440-4675-a656-1a0612ecac77.xml +76 -0
  257. data/test/stub_responses/records/invoice-76bcb361-f93b-4513-b312-5a4af306d276.xml +67 -0
  258. data/test/stub_responses/records/invoice-76e3f056-479f-417c-a72b-f3d767899b87.xml +91 -0
  259. data/test/stub_responses/records/invoice-77b338ef-ecc0-4b95-a0d7-2617b0054611.xml +114 -0
  260. data/test/stub_responses/records/invoice-7be9956d-5316-4f6b-a66a-d355b3f159b2.xml +84 -0
  261. data/test/stub_responses/records/invoice-7dae876a-b424-436b-a4e6-17b3fdeec80c.xml +91 -0
  262. data/test/stub_responses/records/invoice-7e862d93-8dab-4856-8b0c-d844e09d750f.xml +68 -0
  263. data/test/stub_responses/records/invoice-803f70b0-56d9-4157-9787-41df271777a0.xml +84 -0
  264. data/test/stub_responses/records/invoice-86102312-aa3f-438c-9938-6840f4d8dda6.xml +75 -0
  265. data/test/stub_responses/records/invoice-8694c9c5-7097-4449-a708-b8c1982921a4.xml +69 -0
  266. data/test/stub_responses/records/invoice-86d6e00f-ef56-49f7-9a54-796ccd5ca057.xml +85 -0
  267. data/test/stub_responses/records/invoice-88e77f0f-54a5-4efc-a979-7e22223cc4d7.xml +66 -0
  268. data/test/stub_responses/records/invoice-8b0ccb6a-d9b7-4da5-8360-ef7fb157b5aa.xml +66 -0
  269. data/test/stub_responses/records/invoice-935fc854-8037-4111-8d91-993010c331cc.xml +74 -0
  270. data/test/stub_responses/records/invoice-95ef3000-c764-4ba9-a66a-b6e2d161f839.xml +62 -0
  271. data/test/stub_responses/records/invoice-962ef33f-c9d2-4602-9b9f-93a02bea23b3.xml +93 -0
  272. data/test/stub_responses/records/invoice-9868b472-1983-48e9-8edf-7e81ddf2c03a.xml +85 -0
  273. data/test/stub_responses/records/invoice-9a448e9b-a9fa-4a8b-98f5-6dc892a37374.xml +62 -0
  274. data/test/stub_responses/records/invoice-a1d04a14-96a8-4067-a0ff-8136990a354f.xml +91 -0
  275. data/test/stub_responses/records/invoice-a3bc62ef-f11b-4a9c-a4f9-a342bda371b5.xml +66 -0
  276. data/test/stub_responses/records/invoice-a6894ca0-60ee-4d45-9dd4-b44fcba46ec5.xml +90 -0
  277. data/test/stub_responses/records/invoice-a77268ce-74b2-483d-a2b3-70dbdc9e49d2.xml +78 -0
  278. data/test/stub_responses/records/invoice-a9f765e6-b9bc-4505-a47b-fb3ecb327e7b.xml +88 -0
  279. data/test/stub_responses/records/invoice-aa0173af-8707-4e7f-8dde-4c7a357bd312.xml +109 -0
  280. data/test/stub_responses/records/invoice-ab63738a-370a-43a5-bfa3-620d684e66d0.xml +83 -0
  281. data/test/stub_responses/records/invoice-b0344791-5a8a-40dd-a208-d99a461a6c10.xml +84 -0
  282. data/test/stub_responses/records/invoice-b1e53910-473c-46a3-b3cb-38ece571220e.xml +76 -0
  283. data/test/stub_responses/records/invoice-b2c02d0b-41a8-4d4d-97d7-014c78b3547d.xml +93 -0
  284. data/test/stub_responses/records/invoice-b75b3928-ab72-4424-8b93-9cdbbde4cd72.xml +90 -0
  285. data/test/stub_responses/records/invoice-bcd8a71f-aa31-4d0f-8a01-13ea26363ddf.xml +94 -0
  286. data/test/stub_responses/records/invoice-bfbb7c45-de02-45e7-b065-d9863ecfb0d8.xml +66 -0
  287. data/test/stub_responses/records/invoice-c12aff7e-12bf-4185-8702-460929f19674.xml +77 -0
  288. data/test/stub_responses/records/invoice-c3380b96-976d-4b3e-8b26-8d01eb6a3742.xml +87 -0
  289. data/test/stub_responses/records/invoice-c963f2b0-cbe1-4abd-9ccc-7e512c942068.xml +67 -0
  290. data/test/stub_responses/records/invoice-cba46b29-3788-4158-b668-ab10160ccbfe.xml +78 -0
  291. data/test/stub_responses/records/invoice-d62646b9-d0a9-4fdb-9561-756a8b7eba45.xml +63 -0
  292. data/test/stub_responses/records/invoice-dba2f021-f149-4191-a126-5351d587ab0e.xml +75 -0
  293. data/test/stub_responses/records/invoice-de5d9c29-21b3-4342-958b-ed72c4bd7ab0.xml +108 -0
  294. data/test/stub_responses/records/invoice-e3d96555-2876-4364-a46a-7551a4f52611.xml +123 -0
  295. data/test/stub_responses/records/invoice-e4a0afbd-aea0-450b-ae23-0ce921e84a77.xml +102 -0
  296. data/test/stub_responses/records/invoice-e9cb9ecb-58ef-43a8-bd20-69a85338142d.xml +76 -0
  297. data/test/stub_responses/records/invoice-ec9a6f67-7128-4a63-8ba3-5e516f455f9b.xml +94 -0
  298. data/test/stub_responses/records/invoice-ed0f2587-84fc-4aef-bc4b-b1a262e24484.xml +81 -0
  299. data/test/stub_responses/records/invoice-f362ca53-8ade-4047-865a-bb64bee5863d.xml +74 -0
  300. data/test/stub_responses/records/invoice-f571c38b-5be1-41e1-ad5a-ff6184284beb.xml +114 -0
  301. data/test/stub_responses/records/invoice-f5832195-5cd3-4660-ad3f-b73d9c64f263.xml +85 -0
  302. data/test/stub_responses/records/invoice-f9c857eb-64cd-4235-a078-d04b52c77ea7.xml +76 -0
  303. data/test/stub_responses/records/manual_journal-4765d07b-aa03-4e56-9166-50661958c864.xml +38 -0
  304. data/test/stub_responses/records/manual_journal-53fc5558-5b76-4ecd-ae5c-c4af3ccde87c.xml +31 -0
  305. data/test/stub_responses/records/manual_journal-bb6cfcfc-4500-4475-bd3a-93ee512428e0.xml +31 -0
  306. data/test/stub_responses/records/manual_journal-f00a355b-7374-445c-886b-0437bea4095c.xml +45 -0
  307. data/test/stub_responses/refresh_responses.rb +29 -0
  308. data/test/stub_responses/reports/trial_balance.xml +1435 -0
  309. data/test/stub_responses/tax_rates.xml +118 -0
  310. data/test/stub_responses/token_expired +1 -0
  311. data/test/stub_responses/tracking_categories.xml +27 -0
  312. data/test/stub_responses/unknown_error.xml +1 -0
  313. data/test/test_helper.rb +67 -0
  314. data/test/unit/models/bank_transaction_model_parsing_test.rb +133 -0
  315. data/test/unit/models/bank_transaction_test.rb +47 -0
  316. data/test/unit/models/bank_transaction_validation_test.rb +87 -0
  317. data/test/unit/models/contact_test.rb +26 -0
  318. data/test/unit/models/credit_note_test.rb +37 -0
  319. data/test/unit/models/invoice_test.rb +113 -0
  320. data/test/unit/models/journal_line_test.rb +22 -0
  321. data/test/unit/models/line_item_sum_test.rb +24 -0
  322. data/test/unit/models/line_item_test.rb +70 -0
  323. data/test/unit/oauth_config_test.rb +20 -0
  324. data/test/unit/oauth_test.rb +97 -0
  325. data/test/unit/private_application_test.rb +20 -0
  326. data/test/unit/record/base_model_test.rb +50 -0
  327. data/test/unit/record/base_test.rb +94 -0
  328. data/test/unit/record/block_validator_test.rb +125 -0
  329. data/test/unit/record/model_definition_test.rb +159 -0
  330. data/test/unit/record/parse_where_hash_test.rb +63 -0
  331. data/test/unit/record/record_association_test.rb +93 -0
  332. data/test/unit/record/validators_test.rb +228 -0
  333. data/test/unit/record_definition_test.rb +27 -0
  334. data/test/unit/report_definition_test.rb +26 -0
  335. data/test/unit/report_test.rb +145 -0
  336. data/xeroizer.gemspec +405 -0
  337. metadata +561 -0
data/.bundle/config ADDED
@@ -0,0 +1,2 @@
1
+ --- {}
2
+
data/.gitattributes ADDED
@@ -0,0 +1,22 @@
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
3
+
4
+ # Custom for Visual Studio
5
+ *.cs diff=csharp
6
+ *.sln merge=union
7
+ *.csproj merge=union
8
+ *.vbproj merge=union
9
+ *.fsproj merge=union
10
+ *.dbproj merge=union
11
+
12
+ # Standard to msysgit
13
+ *.doc diff=astextplain
14
+ *.DOC diff=astextplain
15
+ *.docx diff=astextplain
16
+ *.DOCX diff=astextplain
17
+ *.dot diff=astextplain
18
+ *.DOT diff=astextplain
19
+ *.pdf diff=astextplain
20
+ *.PDF diff=astextplain
21
+ *.rtf diff=astextplain
22
+ *.RTF diff=astextplain
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'builder', '>= 2.1.2'
4
+ gem 'oauth', '0.4.5'
5
+ gem 'activesupport'
6
+ gem 'nokogiri'
7
+ gem 'i18n'
8
+
9
+ group :test do
10
+ gem 'test-unit'
11
+ gem 'mocha'
12
+ gem 'shoulda'
13
+ gem "jeweler"
14
+ gem "rest-client"
15
+ gem "turn"
16
+ gem "ansi"
17
+ gem "redcarpet"
18
+ gem 'yard'
19
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,57 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (3.2.3)
5
+ i18n (~> 0.6)
6
+ multi_json (~> 1.0)
7
+ ansi (1.4.2)
8
+ builder (3.0.0)
9
+ git (1.2.5)
10
+ i18n (0.6.0)
11
+ jeweler (1.8.3)
12
+ bundler (~> 1.0)
13
+ git (>= 1.2.5)
14
+ rake
15
+ rdoc
16
+ json (1.6.6)
17
+ metaclass (0.0.1)
18
+ mime-types (1.18)
19
+ mocha (0.10.5)
20
+ metaclass (~> 0.0.1)
21
+ multi_json (1.2.0)
22
+ nokogiri (1.5.2)
23
+ oauth (0.4.5)
24
+ rake (0.9.2.2)
25
+ rdoc (3.12)
26
+ json (~> 1.4)
27
+ redcarpet (2.1.1)
28
+ rest-client (1.6.7)
29
+ mime-types (>= 1.16)
30
+ shoulda (3.0.1)
31
+ shoulda-context (~> 1.0.0)
32
+ shoulda-matchers (~> 1.0.0)
33
+ shoulda-context (1.0.0)
34
+ shoulda-matchers (1.0.0)
35
+ test-unit (2.4.8)
36
+ turn (0.9.4)
37
+ ansi
38
+ yard (0.7.5)
39
+
40
+ PLATFORMS
41
+ ruby
42
+
43
+ DEPENDENCIES
44
+ activesupport
45
+ ansi
46
+ builder (>= 2.1.2)
47
+ i18n
48
+ jeweler
49
+ mocha
50
+ nokogiri
51
+ oauth (= 0.4.5)
52
+ redcarpet
53
+ rest-client
54
+ shoulda
55
+ test-unit
56
+ turn
57
+ yard
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Wayne Robinson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,529 @@
1
+ Xeroizer API Library ![Project status](http://stillmaintained.com/waynerobinson/xeroizer.png)
2
+ ====================
3
+
4
+ **Homepage**: [http://waynerobinson.github.com/xeroizer](http://waynerobinson.github.com/xeroizer)
5
+ **Git**: [git://github.com/waynerobinson/xeroizer.git](git://github.com/waynerobinson/xeroizer.git)
6
+ **Github**: [https://github.com/waynerobinson/xeroizer](https://github.com/waynerobinson/xeroizer)
7
+ **Author**: Wayne Robinson [http://www.wayne-robinson.com](http://www.wayne-robinson.com)
8
+ **Contributors**: See Contributors section below
9
+ **Copyright**: 2007-2010
10
+ **License**: MIT License
11
+
12
+ Introduction
13
+ ------------
14
+
15
+ This library is designed to help ruby/rails based applications communicate with the publicly available API for Xero.
16
+
17
+ If you are unfamiliar with the Xero API, you should first read the documentation located at http://developer.xero.com.
18
+
19
+ Installation
20
+ ------------
21
+
22
+ gem install xeroizer
23
+
24
+ Basic Usage
25
+ -----------
26
+
27
+ ```ruby
28
+ require 'rubygems'
29
+ require 'xeroizer'
30
+
31
+ # Create client (used to communicate with the API).
32
+ client = Xeroizer::PublicApplication.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET)
33
+
34
+ # Retrieve list of contacts (note: all communication must be made through the client).
35
+ contacts = client.Contact.all(:order => 'Name')
36
+ ```
37
+
38
+ Authentication
39
+ --------------
40
+
41
+ Xero uses OAuth to authenticate API clients. The OAuth gem (with minor modification) by John Nunemaker ([http://github.com/jnunemaker/twitter](http://github.com/jnunemaker/twitter)) is used in this library. If you've used this before, things will all seem very familar.
42
+
43
+ There are three methods of authentication detailed below:
44
+
45
+ ### All: Consumer Key/Secret
46
+
47
+ All methods of authentication require your OAuth consumer key and secret. This can be found for your application
48
+ in the API management console at [http://api.xero.com](http://api.xero.com).
49
+
50
+ ### Public Applications
51
+
52
+ Public applications use a 3-legged authorisation process. A user will need to authorise your
53
+ application against each organisation that you want access to. Your application can have access
54
+ to many organisations at once by going through the authorisation process for each organisation.
55
+
56
+ The access token received will expire after 30 minutes. If you want access for longer you will need
57
+ the user to re-authorise your application.
58
+
59
+ Authentication occurs in 3 steps:
60
+
61
+ ```ruby
62
+ client = Xeroizer::PublicApplication.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET)
63
+
64
+ # 1. Get a RequestToken from Xero. :oauth_callback is the URL the user will be redirected to
65
+ # after they have authenticated your application.
66
+ #
67
+ # Note: The callback URL's domain must match that listed for your application in http://api.xero.com
68
+ # otherwise the user will not be redirected and only be shown the authentication code.
69
+ request_token = client.request_token(:oauth_callback => 'http://yourapp.com/oauth/callback')
70
+
71
+ # 2. Redirect the user to the URL specified by the RequestToken.
72
+ #
73
+ # Note: example uses redirect_to method defined in Rails controllers.
74
+ redirect_to request_token.authorize_url
75
+
76
+ # 3. Exchange RequestToken for AccessToken.
77
+ # This access token will be used for all subsequent requests but it is stored within the client
78
+ # application so you don't have to record it.
79
+ #
80
+ # Note: This example assumes the callback URL is a Rails action.
81
+ client.authorize_from_request(request_token.token, request_token.secret, :oauth_verifier => params[:oauth_verifier])
82
+ ```
83
+
84
+ You can now use the client to access the Xero API methods, e.g.
85
+
86
+ ```ruby
87
+ contacts = client.Contact.all
88
+ ```
89
+
90
+ #### Example Rails Controller
91
+
92
+ ```ruby
93
+ class XeroSessionController < ApplicationController
94
+
95
+ before_filter :get_xero_client
96
+
97
+ public
98
+
99
+ def new
100
+ request_token = @xero_client.request_token(:oauth_callback => 'http://yourapp.com/xero_session/create')
101
+ session[:request_token] = request_token.token
102
+ session[:request_secret] = request_token.secret
103
+
104
+ redirect_to request_token.authorize_url
105
+ end
106
+
107
+ def create
108
+ @xero_client.authorize_from_request(
109
+ session[:request_token],
110
+ session[:request_secret],
111
+ :oauth_verifier => params[:oauth_verifier] )
112
+
113
+ session[:xero_auth] = {
114
+ :access_token => @xero_client.access_token.token,
115
+ :access_key => @xero_client.access_token.key }
116
+
117
+ session.data.delete(:request_token)
118
+ session.data.delete(:request_secret)
119
+ end
120
+
121
+ def destroy
122
+ session.data.delete(:xero_auth)
123
+ end
124
+
125
+ private
126
+
127
+ def get_xero_client
128
+ @xero_client = Xeroizer::PublicApplication.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET)
129
+
130
+ # Add AccessToken if authorised previously.
131
+ if session[:xero_auth]
132
+ @xero_client.authorize_from_access(
133
+ session[:xero_auth][:access_token],
134
+ session[:xero_auth][:access_key] )
135
+ end
136
+ end
137
+ end
138
+ ```
139
+
140
+ #### Storing AccessToken
141
+
142
+ You can store the access token/secret pair so you can access the API again without user intervention. Currently these
143
+ tokens are only valid for 30 minutes and will raise a `Xeroizer::OAuth::TokenExpired` exception if you try to access
144
+ the API beyond the token's expiry time.
145
+
146
+ If you want API access for longer consider creating a PartnerApplication which will allow you to renew tokens.
147
+
148
+ ```ruby
149
+ access_key = client.access_token.token
150
+ access_secret = client.access_token.secret
151
+ ```
152
+
153
+ ### Private Applications
154
+
155
+ Private applications use a 2-legged authorisation process. When you register your application, you will select
156
+ the organisation that is authorised to your application. This cannot be changed afterwards, although you can
157
+ register another private application if you have multiple organisations.
158
+
159
+ Note: You can only register organisations you are authorised to yourself.
160
+
161
+ Private applications require a private RSA keypair which is used to sign each request to the API. You can
162
+ generate this keypair on Mac OSX or Linux with OpenSSL. For example:
163
+
164
+ openssl genrsa -out privatekey.pem 1024
165
+ openssl req -newkey rsa:1024 -x509 -key privatekey.pem -out publickey.cer -days 365
166
+ openssl pkcs12 -export -out public_privatekey.pfx -inkey privatekey.pem -in publickey.cer
167
+
168
+ You need to upload this `public_privatekey.pfx` file to your private application in [http://api.xero.com](http://api.xero.com).
169
+
170
+ Example usage:
171
+
172
+ ```ruby
173
+ client = Xeroizer::PrivateApplication.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET, "/path/to/privatekey.pem")
174
+ contacts = client.Contact.all
175
+ ```
176
+
177
+ ### Partner Applications
178
+
179
+ Partner applications use a combination of 3-legged authorisation, private key message signing and client-side SSL
180
+ certificate signing.
181
+
182
+ Partner applications are only in beta testing via the Xero API and you will need to contact Xero (network@xero.com) to
183
+ get permission to create a partner application and for them to send you information on obtaining your client-side SSL
184
+ certificate.
185
+
186
+ Ruby's OpenSSL library rqeuires the certificate and private key to be extracted from the `entrust-client.p12` file
187
+ downloaded via Xero's instructions. To extract:
188
+
189
+ openssl pkcs12 -in entrust-client.p12 -clcerts -nokeys -out entrust-cert.pem
190
+ openssl pkcs12 -in entrust-client.p12 -nocerts -out entrust-private.pem
191
+ openssl rsa -in entrust-private.pem -out entrust-private-nopass.pem
192
+
193
+ # This last step removes the password that you added to the private key
194
+ # when it was exported.
195
+
196
+ After you have followed the instructions provided by Xero for partner applications and uploaded your certificate you can
197
+ access the partner application in a similar way to public applications.
198
+
199
+ Authentication occcurs in 3 steps:
200
+
201
+ ```ruby
202
+ client = Xeroizer::PartnerApplication.new(
203
+ YOUR_OAUTH_CONSUMER_KEY,
204
+ YOUR_OAUTH_CONSUMER_SECRET,
205
+ "/path/to/privatekey.pem",
206
+ "/path/to/entrust-cert.pem",
207
+ "/path/to/entrust-private-nopass.pem"
208
+ )
209
+
210
+ # 1. Get a RequestToken from Xero. :oauth_callback is the URL the user will be redirected to
211
+ # after they have authenticated your application.
212
+ #
213
+ # Note: The callback URL's domain must match that listed for your application in http://api.xero.com
214
+ # otherwise the user will not be redirected and only be shown the authentication code.
215
+ request_token = client.request_token(:oauth_callback => 'http://yourapp.com/oauth/callback')
216
+
217
+ # 2. Redirect the user to the URL specified by the RequestToken.
218
+ #
219
+ # Note: example uses redirect_to method defined in Rails controllers.
220
+ redirect_to request_token.authorize_url
221
+
222
+ # 3. Exchange RequestToken for AccessToken.
223
+ # This access token will be used for all subsequent requests but it is stored within the client
224
+ # application so you don't have to record it.
225
+ #
226
+ # Note: This example assumes the callback URL is a Rails action.
227
+ client.authorize_from_request(request_token.token, request_token.secret, :oauth_verifier => params[:oauth_verifier])
228
+ ```
229
+
230
+ This AccessToken will last for 30 minutes however, when using the partner application API you can
231
+ renew this token. To be able to renew this token, you need to save the following data from this organisation's
232
+ AccessToken:
233
+
234
+ ```ruby
235
+ session_handle = client.session_handle
236
+ access_key = client.access_token.token
237
+ access_secret = client.access_token.secret
238
+ ```
239
+
240
+ Two other interesting attributes of the PartnerApplication client are:
241
+
242
+ > **`#expires_at`**: Time this AccessToken will expire (usually 30 minutes into the future).
243
+ > **`#authorization_expires_at`**: How long this organisation has authorised you to access their data (usually 365 days into the future).
244
+
245
+ #### AccessToken Renewal
246
+
247
+ Renewal of an access token requires knowledge of the previous access token generated for this organisation. To renew:
248
+
249
+ ```ruby
250
+ # If you still have a client instance.
251
+ client.renew_access_token
252
+
253
+ # If you are renewing from stored token/session details.
254
+ client.renew_access_token(access_token, access_secret, session_handle)
255
+ ```
256
+
257
+ This will invalidate the previous token and refresh the `access_key` and `access_secret` as specified in the
258
+ initial authorisation process. You must always know the previous token's details to renew access to this
259
+ session.
260
+
261
+ If you lose these details at any stage you can always reauthorise by redirecting the user back to the Xero OAuth gateway.
262
+
263
+ Retrieving Data
264
+ ---------------
265
+
266
+ Each of the below record types is implemented within this library. To allow for multiple access tokens to be used at the same
267
+ time in a single application, the model classes are accessed from the instance of PublicApplication, PrivateApplication
268
+ or PartnerApplication. All class-level operations occur on this singleton. For example:
269
+
270
+ ```ruby
271
+ xero = Xeroizer::PublicApplication.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET)
272
+ xero.authorize_from_access(session[:xero_auth][:access_token], session[:xero_auth][:access_key])
273
+
274
+ contacts = xero.Contact.all(:order => 'Name')
275
+
276
+ new_contact = xero.Contact.build(:name => 'ABC Development')
277
+ saved = new_contact.save
278
+ ```
279
+
280
+ ### \#all([options])
281
+
282
+ Retrieves list of all records with matching options.
283
+
284
+ **Note:** Some records (Invoice, CreditNote) only return summary information for the contact and no line items
285
+ when returning them this list operation. This library takes care of automatically retrieving the
286
+ contact and line items from Xero on first access however, this first access has a large performance penalty
287
+ and will count as an extra query towards your 1,000/day and 60/minute request per organisation limit.
288
+
289
+ Valid options are:
290
+
291
+ > **:modified\_since**
292
+
293
+ > Records modified after this `Time` (must be specified in UTC).
294
+
295
+ > **:order**
296
+
297
+ > Field to order by. Should be formatted as Xero-based field (e.g. 'Name', 'ContactID', etc)
298
+
299
+ > **:where**
300
+
301
+ > __See *Where Filters* section below.__
302
+
303
+ ### \#first([options])
304
+
305
+ This is a shortcut method for `all` and actually runs all however, this method only returns the
306
+ first entry returned by all and never an array.
307
+
308
+ ### \#find(id)
309
+
310
+ Looks up a single record matching `id`. This ID can either be the internal GUID Xero uses for the record
311
+ or, in the case of Invoice, CreditNote and Contact records, your own custom reference number used when
312
+ creating these records.
313
+
314
+ ### Where filters
315
+
316
+ #### Hash
317
+
318
+ You can specify find filters by providing the :where option with a hash. For example:
319
+
320
+ ```ruby
321
+ invoices = Xero.Invoice.all(:where => {:type => 'ACCREC', :amount_due_is_not => 0})
322
+ ```
323
+
324
+ will automatically create the Xero string:
325
+
326
+ Type=="ACCREC"&&AmountDue<>0
327
+
328
+ The default method for filtering is the equality '==' operator however, these can be overridden
329
+ by modifying the postfix of the attribute name (as you can see for the :amount\_due field above).
330
+
331
+ \{attribute_name}_is_not will use '<>'
332
+ \{attribute_name}_is_greater_than will use '>'
333
+ \{attribute_name}_is_greater_than_or_equal_to will use '>='
334
+ \{attribute_name}_is_less_than will use '<'
335
+ \{attribute_name}_is_less_than_or_equal_to will use '<='
336
+
337
+ The default is '=='
338
+
339
+ **Note:** Currently, the hash-conversion library only allows for AND-based criteria and doesn't
340
+ take into account associations. For these, please use the custom filter method below.
341
+
342
+ #### Custom Xero-formatted string
343
+
344
+ Xero allows advanced custom filters to be added to a request. The where parameter can reference any XML element
345
+ in the resulting response, including all nested XML elements.
346
+
347
+ **Example 1: Retrieve all invoices for a specific contact ID:**
348
+
349
+ invoices = xero.Invoice.all(:where => 'Contact.ContactID.ToString()=="cd09aa49-134d-40fb-a52b-b63c6a91d712"')
350
+
351
+ **Example 2: Retrieve all unpaid ACCREC Invoices against a particular Contact Name:**
352
+
353
+ invoices = xero.Invoice.all(:where => 'Contact.Name=="Basket Case" && Type=="ACCREC" && AmountDue<>0')
354
+
355
+ **Example 3: Retrieve all Invoices PAID between certain dates**
356
+
357
+ invoices = xero.Invoice.all(:where => 'FullyPaidOnDate>=DateTime.Parse("2010-01-01T00:00:00")&&FullyPaidOnDate<=DateTime.Parse("2010-01-08T00:00:00")')
358
+
359
+ **Example 4: Retrieve all Bank Accounts:**
360
+
361
+ accounts = xero.Account.all(:where => 'Type=="BANK"')
362
+
363
+ **Example 5: Retrieve all DELETED or VOIDED Invoices:**
364
+
365
+ invoices = xero.Invoice.all(:where => 'Status=="VOIDED" OR Status=="DELETED"')
366
+
367
+ **Example 6: Retrieve all contacts with specific text in the contact name:**
368
+
369
+ contacts = xero.Contact.all(:where => 'Name.Contains("Peter")')
370
+ contacts = xero.Contact.all(:where => 'Name.StartsWith("Pet")')
371
+ contacts = xero.Contact.all(:where => 'Name.EndsWith("er")')
372
+
373
+ Associations
374
+ ------------
375
+
376
+ Records may be associated with each other via two different methods, `has_many` and `belongs_to`.
377
+
378
+ **has\_many example:**
379
+
380
+ ```ruby
381
+ invoice = xero.Invoice.find('cd09aa49-134d-40fb-a52b-b63c6a91d712')
382
+ invoice.line_items.each do | line_item |
383
+ puts "Line Description: #{line_item.description}"
384
+ end
385
+ ```
386
+
387
+ **belongs\_to example:**
388
+
389
+ ```ruby
390
+ invoice = xero.Invoice.find('cd09aa49-134d-40fb-a52b-b63c6a91d712')
391
+ puts "Invoice Contact Name: #{invoice.contact.name}"
392
+ ```
393
+
394
+ Creating/Updating Data
395
+ ----------------------
396
+
397
+ ### Creating
398
+
399
+ New records can be created like:
400
+
401
+ ```ruby
402
+ contact = xero.Contact.build(:name => 'Contact Name')
403
+ contact.first_name = 'Joe'
404
+ contact.last_name = 'Bloggs'
405
+ contact.add_address(:type => 'STREET', :line1 => '12 Testing Lane', :city => 'Brisbane')
406
+ contact.add_phone(:type => 'DEFAULT', :area_code => '07', :number => '3033 1234')
407
+ contact.add_phone(:type => 'MOBILE', :number => '0412 123 456')
408
+ contact.save
409
+ ```
410
+
411
+ To add to a `has_many` association use the `add_{association}` method. For example:
412
+
413
+ ```ruby
414
+ contact.add_address(:type => 'STREET', :line1 => '12 Testing Lane', :city => 'Brisbane')
415
+ ```
416
+
417
+ To add to a `belongs_to` association use the `build_{association}` method. For example:
418
+
419
+ ```ruby
420
+ invoice.build_contact(:name => 'ABC Company')
421
+ ```
422
+
423
+ ### Updating
424
+
425
+ If the primary GUID for the record is present, the library will attempt to update the record instead of
426
+ creating it. It is important that this record is downloaded from the Xero API first before attempting
427
+ an update. For example:
428
+
429
+ ```ruby
430
+ contact = xero.Contact.find("cd09aa49-134d-40fb-a52b-b63c6a91d712")
431
+ contact.name = "Another Name Change"
432
+ contact.save
433
+ ```
434
+
435
+ Have a look at the models in `lib/xeroizer/models/` to see the valid attributes, associations and
436
+ minimum validation requirements for each of the record types.
437
+
438
+ ### Errors
439
+
440
+ If a record doesn't match it's internal validation requirements the `#save` method will return
441
+ `false` and the `#errors` attribute will be populated with what went wrong.
442
+
443
+ For example:
444
+
445
+ ```ruby
446
+ contact = xero.Contact.build
447
+ saved = contact.save
448
+
449
+ # contact.errors will contain [[:name, "can't be blank"]]
450
+ ```
451
+
452
+ \#errors\_for(:attribute\_name) is a helper method to return just the errors associated with
453
+ that attribute. For example:
454
+
455
+ ```ruby
456
+ contact.errors_for(:name) # will contain ["can't be blank"]
457
+ ```
458
+
459
+ If something goes really wrong and the particular validation isn't handled by the internal
460
+ validators then the library may raise a `Xeroizer::ApiException`.
461
+
462
+ Reports
463
+ -------
464
+
465
+ All Xero reports except GST report can be accessed through Xeroizer.
466
+
467
+ Currently, only generic report access functionality exists. This will be extended
468
+ to provide a more report-specific version of the data in the future (public submissions
469
+ are welcome).
470
+
471
+ Reports are accessed like the following example:
472
+
473
+ ```ruby
474
+ trial_balance = xero.TrialBalance.get(:date => '2011-03-21')
475
+
476
+ # Array containing report headings.
477
+ trial_balance.header.cells.map { | cell | cell.value }
478
+
479
+ # Report rows by section
480
+ trial_balance.sections.each do | section |
481
+ puts "Section Title: #{section.title}"
482
+ section.rows.each do | row |
483
+ puts "\t#{row.cells.map { | cell | cell.value }.join("\t")}"
484
+ end
485
+ end
486
+
487
+ # Summary row (if only one on the report)
488
+ trial_balance.summary.cells.map { | cell | cell.value }
489
+
490
+ # All report rows (including HeaderRow, SectionRow, Row and SummaryRow)
491
+ trial_balance.rows.each do | row |
492
+ case row
493
+ when Xeroizer::Report::HeaderRow
494
+ # do something with header
495
+
496
+ when Xeroizer::Report::SectionRow
497
+ # do something with section, will need to step into the rows for this section
498
+
499
+ when Xeroizer::Report::Row
500
+ # do something for standard report rows
501
+
502
+ when Xeroizer::Report::SummaryRow
503
+ # do something for summary rows
504
+
505
+ end
506
+ end
507
+ ```
508
+
509
+ Xero API Rate Limits
510
+ --------------------
511
+
512
+ The Xero API imposes the following limits on calls per organisation:
513
+
514
+ * A limit of 60 API calls in any 60 second period
515
+ * A limit of 1000 API calls in any 24 hour period
516
+
517
+ By default, the library will raise a `Xeroizer::OAuth::RateLimitExceeded`
518
+ exception when one of these limits is exceeded.
519
+
520
+ If required, the library can handle these exceptions internally by sleeping
521
+ for a configurable number of seconds and then repeating the last request.
522
+ You can set this option when initializing an application:
523
+
524
+ ```ruby
525
+ # Sleep for 2 seconds every time the rate limit is exceeded.
526
+ client = Xeroizer::PublicApplication.new(YOUR_OAUTH_CONSUMER_KEY,
527
+ YOUR_OAUTH_CONSUMER_SECRET,
528
+ :rate_limit_sleep => 2)
529
+ ```