xeroizer-float 2.15.3.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,23 @@
1
+ module Xeroizer
2
+ module Record
3
+
4
+ class TrackingCategoryModel < BaseModel
5
+
6
+ set_permissions :read
7
+
8
+ end
9
+
10
+ class TrackingCategory < Base
11
+
12
+ set_primary_key :tracking_category_id
13
+
14
+ guid :tracking_category_id
15
+ string :name
16
+ string :status
17
+
18
+ has_many :options
19
+
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ module Xeroizer
2
+ module Record
3
+
4
+ class TrackingCategoryChildModel < BaseModel
5
+
6
+ set_xml_root_name 'Tracking'
7
+ set_xml_node_name 'TrackingCategory'
8
+
9
+ end
10
+
11
+ class TrackingCategoryChild < Base
12
+
13
+ string :name
14
+ string :option
15
+ guid :tracking_category_id
16
+
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,130 @@
1
+ module Xeroizer
2
+
3
+ # Shamelessly taken from the XeroGateway library by Tim Connor which is shamelessly
4
+ # based on the Twitter Gem's OAuth implementation by John Nunemaker
5
+ # Thanks!
6
+ #
7
+ # http://github.com/tlconnor/xero_gateway
8
+ # http://twitter.rubyforge.org/
9
+ # http://github.com/jnunemaker/twitter/
10
+
11
+ class OAuth
12
+
13
+ class TokenExpired < StandardError; end
14
+ class TokenInvalid < StandardError; end
15
+ class RateLimitExceeded < StandardError; end
16
+ class UnknownError < StandardError; end
17
+
18
+ unless defined? XERO_CONSUMER_OPTIONS
19
+ XERO_CONSUMER_OPTIONS = {
20
+ :site => "https://api.xero.com",
21
+ :request_token_path => "/oauth/RequestToken",
22
+ :access_token_path => "/oauth/AccessToken",
23
+ :authorize_path => "/oauth/Authorize",
24
+ :ca_file => File.expand_path(File.join(File.dirname(__FILE__), 'ca-certificates.crt'))
25
+ }.freeze
26
+ end
27
+
28
+ # Mixin real OAuth methods for consumer.
29
+ extend Forwardable
30
+ def_delegators :access_token, :get, :post, :put, :delete
31
+
32
+ # @attr_reader [String] ctoken consumer key/token from application developer (found at http://api.xero.com for your application).
33
+ # @attr_reader [String] csecret consumer secret from application developer (found at http://api.xero.com for your application).
34
+ # @attr_reader [Time] expires_at time the AccessToken expires if using the PartnerApplication mode (usually 30 minutes for Xero).
35
+ # @attr_reader [Time] authorization_expires_at time the session expires if using the ParnterApplication mode (usually 365 days for Xero).
36
+ attr_reader :ctoken, :csecret, :consumer_options, :expires_at, :authorization_expires_at
37
+
38
+ # @attr_reader [String] session_handle session handle used to renew AccessToken if using the PartnerApplication mode.
39
+ # @attr_writer [String] session_handle session handle used to renew AccessToken if using the PartnerApplication mode.
40
+ attr_accessor :session_handle
41
+
42
+ # OAuth constructor.
43
+ #
44
+ # @param [String] ctoken consumer key/token from application developer (found at http://api.xero.com for your application).
45
+ # @param [String] csecret consumer secret from application developer (found at http://api.xero.com for your application).
46
+ # @option options [String] :access_token_path base URL path for getting an AccessToken (default: "/oauth/AccessToken")
47
+ # @option options [String] :authorize_path base URL path for authorising (default: "/oauth/Authorize")
48
+ # @option options [String] :ca_file file containing SSL root certificates (default: "lib/xeroizer/ca-certificates.crt")
49
+ # @option options [String] :private_key_file private key used when :signature_method set to RSA-SHA1 (used for PartnerApplication and PrivateApplication modes)
50
+ # @option options [String] :request_token_path base URL path for getting a RequestToken (default: "/oauth/RequestToken")
51
+ # @option options [String] :signature_method method usd to sign requests (default: OAuth library default)
52
+ # @option options [String] :site base site for API requests (default: "https://api.xero.com")
53
+ # @option options [OpenSSL:X509::Certificate] :ssl_client_cert client-side SSL certificate to use for requests (used for PartnerApplication mode)
54
+ # @option options [OpenSSL::PKey::RSA] :ssl_client_key client-side SSL private key to use for requests (used for PartnerApplication mode)
55
+ def initialize(ctoken, csecret, options = {})
56
+ @ctoken, @csecret = ctoken, csecret
57
+ @consumer_options = XERO_CONSUMER_OPTIONS.merge(options)
58
+ end
59
+
60
+ # OAuth consumer creator.
61
+ #
62
+ # @return [OAuth::Consumer] consumer object for GET/POST/PUT methods.
63
+ def consumer
64
+ create_consumer
65
+ end
66
+
67
+ # RequestToken for PUBLIC/PARTNER authorisation
68
+ # (used to redirect to Xero for authentication).
69
+ #
70
+ # @option params [String] :oauth_callback URL to redirect user to when they have authenticated your application with Xero. If not specified, the user will be shown an authorisation code on the screen that they need to get into your application.
71
+ def request_token(params = {})
72
+ consumer.get_request_token(params)
73
+ end
74
+
75
+ # Create an AccessToken from a PUBLIC/PARTNER authorisation.
76
+ def authorize_from_request(rtoken, rsecret, params = {})
77
+ request_token = ::OAuth::RequestToken.new(consumer, rtoken, rsecret)
78
+ access_token = request_token.get_access_token(params)
79
+ update_attributes_from_token(access_token)
80
+ end
81
+
82
+ # AccessToken created from authorize_from_access method.
83
+ def access_token
84
+ ::OAuth::AccessToken.new(consumer, @atoken, @asecret)
85
+ end
86
+
87
+ # Used for PRIVATE applications where the AccessToken uses the
88
+ # token/secret from Xero which would normally be used in the request.
89
+ # No request authorisation necessary.
90
+ #
91
+ # For PUBLIC/PARTNER applications this is used to recreate a client
92
+ # from a stored AccessToken key/secret.
93
+ def authorize_from_access(atoken, asecret)
94
+ @atoken, @asecret = atoken, asecret
95
+ end
96
+
97
+ # Renew an access token from a previously authorised token for a
98
+ # PARTNER application.
99
+ def renew_access_token(atoken = nil, asecret = nil, session_handle = nil)
100
+ old_token = ::OAuth::RequestToken.new(consumer, atoken || @atoken, asecret || @asecret)
101
+ access_token = old_token.get_access_token({
102
+ :oauth_session_handle => (session_handle || @session_handle),
103
+ :token => old_token
104
+ })
105
+ update_attributes_from_token(access_token)
106
+ end
107
+
108
+ private
109
+
110
+ # Create an OAuth consumer with the SSL client key if specified in @consumer_options when
111
+ # this instance was created.
112
+ def create_consumer
113
+ consumer = ::OAuth::Consumer.new(@ctoken, @csecret, consumer_options)
114
+ if @consumer_options[:ssl_client_cert] && @consumer_options[:ssl_client_key]
115
+ consumer.http.cert = @consumer_options[:ssl_client_cert]
116
+ consumer.http.key = @consumer_options[:ssl_client_key]
117
+ end
118
+ consumer
119
+ end
120
+
121
+ # Update instance variables with those from the AccessToken.
122
+ def update_attributes_from_token(access_token)
123
+ @expires_at = Time.now + access_token.params[:oauth_expires_in].to_i
124
+ @authorization_expires_at = Time.now + access_token.params[:oauth_authorization_expires_in].to_i
125
+ @session_handle = access_token.params[:oauth_session_handle]
126
+ @atoken, @asecret = access_token.token, access_token.secret
127
+ end
128
+
129
+ end
130
+ end
@@ -0,0 +1,46 @@
1
+ module Xeroizer
2
+ class PartnerApplication < GenericApplication
3
+
4
+ extend Forwardable
5
+ def_delegators :client, :request_token, :authorize_from_request, :renew_access_token, :expires_at, :authorization_expires_at, :session_handle, :authorize_from_access
6
+
7
+ public
8
+
9
+ # Partner applications allow for public AccessToken's received via the stanard OAuth
10
+ # authentication process to be renewed up until the session's expiry. The default session
11
+ # expiry for Xero is 365 days and the default AccessToken expiry is 30 minutes.
12
+ #
13
+ # @param [String] consumer_key consumer key/token from application developer (found at http://api.xero.com for your application).
14
+ # @param [String] consumer_secret consumer secret from application developer (found at http://api.xero.com for your application).
15
+ # @param [String] path_to_private_key application's private key for message signing (uploaded to http://api.xero.com)
16
+ # @param [String] path_to_ssl_client_cert client-side SSL certificate file to use for requests
17
+ # @param [String] path_to_ssl_client_key client-side SSL private key to use for requests
18
+ # @param [Hash] options other options to pass to the GenericApplication constructor
19
+ # @return [PartnerApplication] instance of PrivateApplication
20
+ def initialize(consumer_key, consumer_secret, path_to_private_key, path_to_ssl_client_cert, path_to_ssl_client_key, options = {})
21
+ default_options = {
22
+ :xero_url => 'https://api-partner.network.xero.com/api.xro/2.0',
23
+ :site => 'https://api-partner.network.xero.com',
24
+ :authorize_url => 'https://api.xero.com/oauth/Authorize',
25
+ :signature_method => 'RSA-SHA1'
26
+ }
27
+ options = default_options.merge(options).merge(
28
+ :private_key_file => path_to_private_key,
29
+ :ssl_client_cert => OpenSSL::X509::Certificate.new(File.read(path_to_ssl_client_cert)),
30
+ :ssl_client_key => OpenSSL::PKey::RSA.new(File.read(path_to_ssl_client_key))
31
+ )
32
+ super(consumer_key, consumer_secret, options)
33
+
34
+ # Load up an existing token if passed the token/key.
35
+ if options[:access_token] && options[:access_key]
36
+ authorize_from_access(options[:access_token], options[:access_key])
37
+ end
38
+
39
+ # Save the session_handle if passed in so we can renew the token.
40
+ if options[:session_handle]
41
+ client.session_handle = options[:session_handle]
42
+ end
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,27 @@
1
+ module Xeroizer
2
+ class PrivateApplication < GenericApplication
3
+
4
+ extend Forwardable
5
+ def_delegators :client, :authorize_from_access
6
+
7
+ public
8
+
9
+ # Private applications are defined in the Xero API website and can be accessed in the
10
+ # background without ever requiring a redirect to the Xero website for authorisation.
11
+ #
12
+ # @param [String] consumer_key consumer key/token from application developer (found at http://api.xero.com for your application).
13
+ # @param [String] consumer_secret consumer secret from application developer (found at http://api.xero.com for your application).
14
+ # @param [String] path_to_private_key aapplication's private key for message signing (uploaded to http://api.xero.com)
15
+ # @param [Hash] options other options to pass to the GenericApplication constructor
16
+ # @return [PrivateApplication] instance of PrivateApplication
17
+ def initialize(consumer_key, consumer_secret, path_to_private_key, options = {})
18
+ options.merge!(
19
+ :signature_method => 'RSA-SHA1',
20
+ :private_key_file => path_to_private_key
21
+ )
22
+ super(consumer_key, consumer_secret, options)
23
+ @client.authorize_from_access(consumer_key, consumer_secret)
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ module Xeroizer
2
+ class PublicApplication < GenericApplication
3
+
4
+ extend Forwardable
5
+ def_delegators :client, :request_token, :authorize_from_request, :authorize_from_access
6
+
7
+ public
8
+
9
+ # Public appliations are authenticated via the Xero website via OAuth. AccessTokens are valid for 30 minutes
10
+ # after authentication. To extend this time you must redirect the user to Xero's OAuth server again.
11
+ #
12
+ # @param [String] consumer_key consumer key/token from application developer (found at http://api.xero.com for your application)
13
+ # @param [String] consumer_secret consumer secret from application developer (found at http://api.xero.com for your application)
14
+ # @param [Hash] options other options to pass to the GenericApplication constructor
15
+ # @return [PublicApplication] instance of PrivateApplication
16
+ def initialize(consumer_key, consumer_secret, options = {})
17
+ super(consumer_key, consumer_secret, options)
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,32 @@
1
+ module Xeroizer
2
+ module Record
3
+ module ApplicationHelper
4
+
5
+ # Factory for new BaseModel instances with the class name `record_type`.
6
+ # Only creates the instance if one doesn't already exist.
7
+ #
8
+ # @param [Symbol] record_type Symbol of the record type (e.g. :Invoice)
9
+ # @return [BaseModel] instance of BaseModel subclass matching `record_type`
10
+ def record(record_type)
11
+ define_method record_type do
12
+ var_name = "@#{record_type}_cache".to_sym
13
+ unless instance_variable_defined?(var_name)
14
+ instance_variable_set(var_name, Xeroizer::Record.const_get("#{record_type}Model".to_sym).new(self, record_type.to_s))
15
+ end
16
+ instance_variable_get(var_name)
17
+ end
18
+ end
19
+
20
+ def report(report_type)
21
+ define_method report_type do
22
+ var_name = "@#{report_type}_cache".to_sym
23
+ unless instance_variable_defined?(var_name)
24
+ instance_variable_set(var_name, Xeroizer::Report::Factory.new(self, report_type.to_s))
25
+ end
26
+ instance_variable_get(var_name)
27
+ end
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,155 @@
1
+ require 'xeroizer/record/model_definition_helper'
2
+ require 'xeroizer/record/record_association_helper'
3
+ require 'xeroizer/record/validation_helper'
4
+ require 'xeroizer/record/xml_helper'
5
+ require 'xeroizer/logging'
6
+
7
+ module Xeroizer
8
+ module Record
9
+
10
+ class Base
11
+
12
+ include ClassLevelInheritableAttributes
13
+ class_inheritable_attributes :fields, :possible_primary_keys, :primary_key_name, :summary_only, :validators
14
+
15
+ attr_reader :attributes
16
+ attr_reader :parent
17
+ attr_accessor :errors
18
+ attr_accessor :complete_record_downloaded
19
+
20
+ include ModelDefinitionHelper
21
+ include RecordAssociationHelper
22
+ include ValidationHelper
23
+ include XmlHelper
24
+
25
+ class << self
26
+
27
+ # Build a record with attributes set to the value of attributes.
28
+ def build(attributes, parent)
29
+ record = new(parent)
30
+ attributes.each do | key, value |
31
+ record.send("#{key}=".to_sym, value)
32
+ end
33
+ record
34
+ end
35
+
36
+ end
37
+
38
+ public
39
+
40
+ def initialize(parent)
41
+ @parent = parent
42
+ @attributes = {}
43
+ end
44
+
45
+ def new_model_class(model_name)
46
+ Xeroizer::Record.const_get("#{model_name}Model".to_sym).new(parent.application, model_name.to_s)
47
+ end
48
+
49
+ def [](attribute)
50
+ self.send(attribute)
51
+ end
52
+
53
+ def []=(attribute, value)
54
+ self.send("#{attribute}=".to_sym, value)
55
+ end
56
+
57
+ def attributes=(new_attributes)
58
+ return unless new_attributes.is_a?(Hash)
59
+ new_attributes.each do | key, value |
60
+ self.send("#{key}=".to_sym, value)
61
+ end
62
+ end
63
+
64
+ def update_attributes(attributes)
65
+ self.attributes = attributes
66
+ save
67
+ end
68
+
69
+ def new_record?
70
+ id.nil?
71
+ end
72
+
73
+ # Check to see if the complete record is downloaded.
74
+ def complete_record_downloaded?
75
+ if !!self.class.list_contains_summary_only?
76
+ !!complete_record_downloaded
77
+ else
78
+ true
79
+ end
80
+ end
81
+
82
+ # Downloads the complete record if we only have a summary of the record.
83
+ def download_complete_record!
84
+ record = self.parent.find(self.id)
85
+ @attributes = record.attributes if record
86
+ @complete_record_downloaded = true
87
+ self
88
+ end
89
+
90
+ def save
91
+ return false unless valid?
92
+ if new_record?
93
+ create
94
+ else
95
+ update
96
+ end
97
+ @complete_record_downloaded = true
98
+ true
99
+ end
100
+
101
+ def inspect
102
+ attribute_string = self.attributes.collect do |attr, value|
103
+ "#{attr.inspect}: #{value.inspect}"
104
+ end.join(", ")
105
+ "#<#{self.class} #{attribute_string}>"
106
+ end
107
+
108
+ protected
109
+
110
+ # Attempt to create a new record.
111
+ def create
112
+ request = to_xml
113
+ log "[CREATE SENT] (#{__FILE__}:#{__LINE__}) #{request}"
114
+
115
+ response = parent.http_put(request)
116
+ log "[CREATE RECEIVED] (#{__FILE__}:#{__LINE__}) #{response}"
117
+
118
+ parse_save_response(response)
119
+ end
120
+
121
+ # Attempt to update an existing record.
122
+ def update
123
+ if self.class.possible_primary_keys && self.class.possible_primary_keys.all? { | possible_key | self[possible_key].nil? }
124
+ raise RecordKeyMustBeDefined.new(self.class.possible_primary_keys)
125
+ end
126
+
127
+ request = to_xml
128
+
129
+ log "[UPDATE SENT] (#{__FILE__}:#{__LINE__}) \r\n#{request}"
130
+
131
+ response = parent.http_post(request)
132
+
133
+ log "[UPDATE RECEIVED] (#{__FILE__}:#{__LINE__}) \r\n#{response}"
134
+
135
+ parse_save_response(response)
136
+ end
137
+
138
+ # Parse the response from a create/update request.
139
+ def parse_save_response(response_xml)
140
+ response = parent.parse_response(response_xml)
141
+ record = response.response_items.first if response.response_items.is_a?(Array)
142
+ if record && record.is_a?(self.class)
143
+ @attributes = record.attributes
144
+ end
145
+ self
146
+ end
147
+
148
+ def log(what)
149
+ Xeroizer::Logging::Log.info what
150
+ end
151
+
152
+ end
153
+
154
+ end
155
+ end