xeroizer 0.1.0
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.
- data/.bundle/config +2 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +22 -0
- data/LICENSE.txt +20 -0
- data/README.md +416 -0
- data/Rakefile +39 -0
- data/VERSION +1 -0
- data/lib/.DS_Store +0 -0
- data/lib/big_decimal_to_s.rb +9 -0
- data/lib/class_level_inheritable_attributes.rb +25 -0
- data/lib/nokogiri_utils.rb +58 -0
- data/lib/xeroizer.rb +55 -0
- data/lib/xeroizer/ca-certificates.crt +2642 -0
- data/lib/xeroizer/exceptions.rb +94 -0
- data/lib/xeroizer/generic_application.rb +40 -0
- data/lib/xeroizer/http.rb +148 -0
- data/lib/xeroizer/http_encoding_helper.rb +49 -0
- data/lib/xeroizer/models/account.rb +60 -0
- data/lib/xeroizer/models/address.rb +31 -0
- data/lib/xeroizer/models/branding_theme.rb +22 -0
- data/lib/xeroizer/models/contact.rb +46 -0
- data/lib/xeroizer/models/credit_note.rb +113 -0
- data/lib/xeroizer/models/currency.rb +18 -0
- data/lib/xeroizer/models/invoice.rb +138 -0
- data/lib/xeroizer/models/item.rb +27 -0
- data/lib/xeroizer/models/item_purchase_sale_details.rb +17 -0
- data/lib/xeroizer/models/journal.rb +25 -0
- data/lib/xeroizer/models/journal_line.rb +28 -0
- data/lib/xeroizer/models/line_item.rb +43 -0
- data/lib/xeroizer/models/manual_journal.rb +42 -0
- data/lib/xeroizer/models/manual_journal_line.rb +24 -0
- data/lib/xeroizer/models/option.rb +15 -0
- data/lib/xeroizer/models/organisation.rb +23 -0
- data/lib/xeroizer/models/payment.rb +30 -0
- data/lib/xeroizer/models/phone.rb +25 -0
- data/lib/xeroizer/models/tax_rate.rb +25 -0
- data/lib/xeroizer/models/tracking_category.rb +23 -0
- data/lib/xeroizer/models/tracking_category_child.rb +17 -0
- data/lib/xeroizer/oauth.rb +130 -0
- data/lib/xeroizer/partner_application.rb +44 -0
- data/lib/xeroizer/private_application.rb +27 -0
- data/lib/xeroizer/public_application.rb +21 -0
- data/lib/xeroizer/record/application_helper.rb +22 -0
- data/lib/xeroizer/record/base.rb +116 -0
- data/lib/xeroizer/record/base_model.rb +138 -0
- data/lib/xeroizer/record/base_model_http_proxy.rb +134 -0
- data/lib/xeroizer/record/model_definition_helper.rb +94 -0
- data/lib/xeroizer/record/record_association_helper.rb +94 -0
- data/lib/xeroizer/record/validation_helper.rb +59 -0
- data/lib/xeroizer/record/validators/associated_validator.rb +33 -0
- data/lib/xeroizer/record/validators/inclusion_of_validator.rb +22 -0
- data/lib/xeroizer/record/validators/presence_of_validator.rb +19 -0
- data/lib/xeroizer/record/validators/validator.rb +24 -0
- data/lib/xeroizer/record/xml_helper.rb +113 -0
- data/lib/xeroizer/response.rb +17 -0
- data/test/stub_responses/accounts.xml +589 -0
- data/test/stub_responses/api_exception.xml +153 -0
- data/test/stub_responses/bogus_oauth_error +1 -0
- data/test/stub_responses/branding_themes.xml +20 -0
- data/test/stub_responses/contact.xml +40 -0
- data/test/stub_responses/contacts.xml +3349 -0
- data/test/stub_responses/create_credit_note.xml +104 -0
- data/test/stub_responses/create_invoice.xml +64 -0
- data/test/stub_responses/credit_note.xml +69 -0
- data/test/stub_responses/credit_note_not_found_error.xml +1 -0
- data/test/stub_responses/credit_notes.xml +149 -0
- data/test/stub_responses/currencies.xml +12 -0
- data/test/stub_responses/invalid_api_key_error.xml +1 -0
- data/test/stub_responses/invalid_consumer_key +1 -0
- data/test/stub_responses/invalid_request_token +1 -0
- data/test/stub_responses/invoice.xml +91 -0
- data/test/stub_responses/invoice_not_found_error.xml +1 -0
- data/test/stub_responses/invoices.xml +1728 -0
- data/test/stub_responses/items.xml +112 -0
- data/test/stub_responses/manual_journal.xml +45 -0
- data/test/stub_responses/manual_journals.xml +40 -0
- data/test/stub_responses/organisation.xml +16 -0
- data/test/stub_responses/organisations.xml +16 -0
- data/test/stub_responses/rate_limit_exceeded +1 -0
- data/test/stub_responses/records/contact-043892a1-aef1-4c18-88d8-b8ccb6d31466.xml +38 -0
- data/test/stub_responses/records/contact-09664078-efe2-4a88-89a5-67eac9b0047b.xml +40 -0
- data/test/stub_responses/records/contact-0a4cf37b-a1a8-4753-9ee2-f9207f63a8ff.xml +48 -0
- data/test/stub_responses/records/contact-0e74f929-11b9-4255-a035-1fdfe573e676.xml +40 -0
- data/test/stub_responses/records/contact-0f471ca5-15c9-405e-a1b9-7cc35194b673.xml +38 -0
- data/test/stub_responses/records/contact-13cd4c47-baa6-4f07-93f6-6442310df4bf.xml +47 -0
- data/test/stub_responses/records/contact-158a2667-82ee-43bf-8f33-a6cc9524092d.xml +38 -0
- data/test/stub_responses/records/contact-17465072-6fa3-40bf-bc42-97765d9e1bea.xml +38 -0
- data/test/stub_responses/records/contact-1975b0ed-b7ba-4c61-bae8-2aa6d78b0dee.xml +39 -0
- data/test/stub_responses/records/contact-1b2be6e9-8d58-4da9-aaf8-4fe5471b653c.xml +53 -0
- data/test/stub_responses/records/contact-1c40da58-fe1d-4e97-b729-b2abdae94d9e.xml +38 -0
- data/test/stub_responses/records/contact-258176a5-c622-4394-9c94-6f88c3ea12e5.xml +40 -0
- data/test/stub_responses/records/contact-299dd3a0-a417-4a37-8a04-2f55e91963e5.xml +40 -0
- data/test/stub_responses/records/contact-2be39278-5154-4ed1-8eb0-676f25acfc66.xml +40 -0
- data/test/stub_responses/records/contact-2e58cff6-488c-4a32-884b-baf848010229.xml +40 -0
- data/test/stub_responses/records/contact-2faccd41-935e-40aa-b74e-e2fc28ac34c3.xml +38 -0
- data/test/stub_responses/records/contact-31af01e7-2ca7-45b9-a500-b02db996568e.xml +38 -0
- data/test/stub_responses/records/contact-344f1113-a25b-4344-b82e-bedeacc17c8e.xml +40 -0
- data/test/stub_responses/records/contact-3e776c4b-ea9e-4bb1-96be-6b0c7a71a37f.xml +39 -0
- data/test/stub_responses/records/contact-3fc1fc6c-e5ff-4e40-b6f3-7eb535637d87.xml +38 -0
- data/test/stub_responses/records/contact-416ab20c-5357-4beb-a740-e8d175d71efb.xml +38 -0
- data/test/stub_responses/records/contact-41a42865-f15a-4fa1-b643-47877608f557.xml +54 -0
- data/test/stub_responses/records/contact-42771b60-19a7-4692-af81-dd9f9b9362d4.xml +43 -0
- data/test/stub_responses/records/contact-451ceb28-9610-44c9-8f35-3225482f2413.xml +40 -0
- data/test/stub_responses/records/contact-4ab343ad-1ebb-4afe-9d48-1814a93c2081.xml +38 -0
- data/test/stub_responses/records/contact-4bb77692-42d4-4565-85a0-8849eb85e039.xml +39 -0
- data/test/stub_responses/records/contact-4dec292f-3ab7-46a8-83e4-5fb5eac42c7f.xml +40 -0
- data/test/stub_responses/records/contact-4e2f192e-8397-4d4d-97ca-a4fc5ac531bf.xml +38 -0
- data/test/stub_responses/records/contact-5188c17c-7786-4436-ad6e-9da2997386d0.xml +40 -0
- data/test/stub_responses/records/contact-52442753-b1c4-40b7-9b79-c33997de5837.xml +40 -0
- data/test/stub_responses/records/contact-565acaa9-e7f3-4fbf-80c3-16b081ddae10.xml +38 -0
- data/test/stub_responses/records/contact-571a2414-81ff-4f8f-8498-d91d83793131.xml +44 -0
- data/test/stub_responses/records/contact-58697449-85ef-46ae-83fc-6a9446f037fb.xml +40 -0
- data/test/stub_responses/records/contact-58bf2ae3-5144-4628-8de2-e165ac2bcdc6.xml +40 -0
- data/test/stub_responses/records/contact-5d41dafd-eb7e-42c1-bd5a-ba3be1da0960.xml +38 -0
- data/test/stub_responses/records/contact-5f005a09-5ce4-4fb4-8096-e69c18be636e.xml +38 -0
- data/test/stub_responses/records/contact-60d578d9-3e10-4aef-b5dc-9d9fd60a3633.xml +47 -0
- data/test/stub_responses/records/contact-62392126-dba4-4a75-b907-5875ebf75259.xml +40 -0
- data/test/stub_responses/records/contact-642c7fb5-e8e5-48e1-a710-39a18c6c3217.xml +40 -0
- data/test/stub_responses/records/contact-64aebf9c-bb89-4b38-b99b-405bd1ece6fd.xml +40 -0
- data/test/stub_responses/records/contact-64eedbc9-1fa0-485a-837f-705f23188161.xml +38 -0
- data/test/stub_responses/records/contact-65e96c9f-1595-4653-9a8a-2a36d49223c2.xml +40 -0
- data/test/stub_responses/records/contact-67d26b93-ccb4-4890-9bf1-284b70ea755d.xml +38 -0
- data/test/stub_responses/records/contact-69d3e538-44b3-4e00-a5f6-7dddcb6e0656.xml +40 -0
- data/test/stub_responses/records/contact-6a8450bc-f81a-4bb0-a8f6-aa4afe9497c7.xml +40 -0
- data/test/stub_responses/records/contact-6c70e424-41d6-4b9b-af3e-b3a9f3589106.xml +40 -0
- data/test/stub_responses/records/contact-6de0b0cf-560c-4503-aab3-e1543c329deb.xml +54 -0
- data/test/stub_responses/records/contact-72dd6a02-396e-42a2-a4d6-cc3fa75dfece.xml +41 -0
- data/test/stub_responses/records/contact-755f1475-d255-43a8-bedc-5ea7fd26c71f.xml +51 -0
- data/test/stub_responses/records/contact-78a9d0a0-3d8c-4f84-af3e-f260bf4a9dc0.xml +38 -0
- data/test/stub_responses/records/contact-79aa39ca-22b0-42c2-9026-78757a29d665.xml +42 -0
- data/test/stub_responses/records/contact-804f4140-5978-48fe-ba20-b56e5b834b18.xml +40 -0
- data/test/stub_responses/records/contact-812d4f28-1681-4241-8e34-d15c5520ba35.xml +38 -0
- data/test/stub_responses/records/contact-860b99a9-0958-4c8d-a98f-bb1f092b16bb.xml +60 -0
- data/test/stub_responses/records/contact-87c8da45-97cc-46be-b170-398da0eacfb8.xml +40 -0
- data/test/stub_responses/records/contact-8a154a19-6c6c-404b-bbc9-6deae2d18251.xml +38 -0
- data/test/stub_responses/records/contact-8bb6931d-2865-44e9-9a23-ed1fb9c7a46c.xml +40 -0
- data/test/stub_responses/records/contact-936c9759-01da-4063-b472-424ab9f48212.xml +38 -0
- data/test/stub_responses/records/contact-9d12a994-9640-4b75-95cc-3de1e9d0ef09.xml +38 -0
- data/test/stub_responses/records/contact-9fe59245-1fbb-4157-93c3-dc97388f3746.xml +40 -0
- data/test/stub_responses/records/contact-a06a7225-6f8a-4522-8400-c534dd43a16e.xml +40 -0
- data/test/stub_responses/records/contact-a76a85fe-73a2-46fa-aba7-791f36103cdb.xml +40 -0
- data/test/stub_responses/records/contact-a93b5f40-0346-4d21-9181-431e129911c0.xml +40 -0
- data/test/stub_responses/records/contact-abf272dd-6b1d-4829-af88-c57bf55855e3.xml +38 -0
- data/test/stub_responses/records/contact-ad24c33b-256b-4157-ad56-cbcf0e8db7b1.xml +47 -0
- data/test/stub_responses/records/contact-b107129d-f4c9-438e-9573-64b778527f4a.xml +40 -0
- data/test/stub_responses/records/contact-b233288a-aa26-4b26-9fc7-779d797dd56f.xml +40 -0
- data/test/stub_responses/records/contact-b2b5333a-2546-4975-891f-d71a8a640d23.xml +38 -0
- data/test/stub_responses/records/contact-b4d149bf-1823-4bd2-96da-9032388c9686.xml +40 -0
- data/test/stub_responses/records/contact-b78d4fd1-4306-4d83-a0b9-61458d1c53a2.xml +40 -0
- data/test/stub_responses/records/contact-b7d108a8-d5f7-4f16-a7c9-26eaed98e8de.xml +40 -0
- data/test/stub_responses/records/contact-baeed0f3-7989-4874-99b3-59f23032cb73.xml +38 -0
- data/test/stub_responses/records/contact-bc51a3a1-b7f6-46ca-ac9e-19b87e6ca100.xml +40 -0
- data/test/stub_responses/records/contact-be9f3aab-52f5-4d9c-94b4-87f7d9e5ee8b.xml +38 -0
- data/test/stub_responses/records/contact-c135f994-01e4-427b-9e15-acfe8a477c16.xml +49 -0
- data/test/stub_responses/records/contact-c14edf75-15e4-4a9c-86e4-f52e2fe7cfa4.xml +40 -0
- data/test/stub_responses/records/contact-ca9b9abc-c2dc-4221-8101-31f464d314cc.xml +44 -0
- data/test/stub_responses/records/contact-cc4db604-9ed8-4eef-8a29-51b5b70496a0.xml +38 -0
- data/test/stub_responses/records/contact-cce9b044-be4a-43b3-9dc7-c027d8dd35b2.xml +38 -0
- data/test/stub_responses/records/contact-d0cd2c4f-18a0-4f7c-a32a-2db00f29d298.xml +43 -0
- data/test/stub_responses/records/contact-d6851dc2-9ed9-4515-bc0b-810b09c06a6a.xml +38 -0
- data/test/stub_responses/records/contact-d6a384fb-f46f-41a3-8ac7-b7bc9e0b5efa.xml +46 -0
- data/test/stub_responses/records/contact-d74e61cf-2ad0-4f0d-b9d1-6a808e3f70cf.xml +40 -0
- data/test/stub_responses/records/contact-d9ab0f61-3b56-4e2b-be39-f33c11bd99e3.xml +40 -0
- data/test/stub_responses/records/contact-dbb1f0b5-a71b-4458-8462-104acd0fec6b.xml +38 -0
- data/test/stub_responses/records/contact-dd981bd6-40dd-496d-a282-bf7d3391b8b9.xml +40 -0
- data/test/stub_responses/records/contact-e1826204-cc0a-42a5-a6d0-4b352d9d5953.xml +40 -0
- data/test/stub_responses/records/contact-e2d955db-f366-42dd-87f7-fbdb4da2306f.xml +40 -0
- data/test/stub_responses/records/contact-e32e2130-3d27-443a-8313-48fffa03cf53.xml +40 -0
- data/test/stub_responses/records/contact-e3a68332-d322-4816-8678-73a537c8cd33.xml +38 -0
- data/test/stub_responses/records/contact-e6ac76a3-ca32-4fa1-8ef9-6a4bf8b0ec2a.xml +40 -0
- data/test/stub_responses/records/contact-e6ca965d-7c48-480e-be39-e847307f474a.xml +38 -0
- data/test/stub_responses/records/contact-e77d1f20-2e8e-46ec-9a10-50335a216724.xml +40 -0
- data/test/stub_responses/records/contact-e8b98c13-a424-41d2-ba0e-7b7621411e7a.xml +38 -0
- data/test/stub_responses/records/contact-e8e9a2c2-3e7e-48ed-8528-c3d61b28f276.xml +39 -0
- data/test/stub_responses/records/contact-eb43fcc6-87ec-4a0a-b243-d718bee4e2cb.xml +38 -0
- data/test/stub_responses/records/contact-ef6f54c1-eb45-4956-b8cd-1be82ad665f2.xml +43 -0
- data/test/stub_responses/records/contact-efdb3600-f233-42e2-8f18-ce7e2a95e4b1.xml +38 -0
- data/test/stub_responses/records/contact-f7eca431-5c97-4d24-93fd-004bb8a6c644.xml +40 -0
- data/test/stub_responses/records/contact-fb078879-5d6d-474f-825f-61dc90689349.xml +38 -0
- data/test/stub_responses/records/contact-fc39b273-4aa2-4785-99ca-24672f6c0000.xml +38 -0
- data/test/stub_responses/records/contact-fc9ec3a6-a2fe-4300-a8cb-ca8a0b3662e0.xml +40 -0
- data/test/stub_responses/records/contact-fdf96102-7491-44b6-bf4d-7a77ff25f890.xml +40 -0
- data/test/stub_responses/records/contact-fe61ead1-8afc-4f0b-beda-066620227aad.xml +38 -0
- data/test/stub_responses/records/credit_note-371cd138-1e5c-4ec1-a8c6-a1c10e8bdab1.xml +69 -0
- data/test/stub_responses/records/credit_note-3bffc09b-79f2-490d-b91b-c59b700b43a4.xml +91 -0
- data/test/stub_responses/records/credit_note-43c678ee-f357-48e2-b192-b6e3634762f9.xml +90 -0
- data/test/stub_responses/records/credit_note-482c018b-d329-4e05-9b4f-7a4cfc695aa0.xml +73 -0
- data/test/stub_responses/records/credit_note-4f67130a-749a-4ee6-98b2-743adbc11245.xml +60 -0
- data/test/stub_responses/records/credit_note-50e98404-2fba-4031-af67-8ba4bb227c44.xml +74 -0
- data/test/stub_responses/records/credit_note-7df8949c-b71f-40c0-bbcf-39f2f450f286.xml +73 -0
- data/test/stub_responses/records/credit_note-b356e488-2678-4be4-ad4b-d294df2d48d6.xml +76 -0
- data/test/stub_responses/records/invoice-0032f627-3156-4d30-9b1c-4d3b994dc921.xml +82 -0
- data/test/stub_responses/records/invoice-00c9511b-24b9-4190-a90a-8abf2fe9f4a0.xml +74 -0
- data/test/stub_responses/records/invoice-024d7994-a26c-4c20-9894-13934840fc31.xml +73 -0
- data/test/stub_responses/records/invoice-0e64a623-c2a1-446a-93ed-eb897f118cbc.xml +96 -0
- data/test/stub_responses/records/invoice-15e88e57-2554-4496-a18e-eb3f5c622345.xml +73 -0
- data/test/stub_responses/records/invoice-166f0588-d0ba-458c-b28a-8edd4c8fc463.xml +73 -0
- data/test/stub_responses/records/invoice-1d1ba340-afa2-4f4c-8ff7-a147bda9a47b.xml +91 -0
- data/test/stub_responses/records/invoice-290ef4c4-baec-492b-b4dd-c102826470ae.xml +85 -0
- data/test/stub_responses/records/invoice-30a87092-31b5-4a2c-831e-327486533dd2.xml +77 -0
- data/test/stub_responses/records/invoice-30dbd181-72a8-43df-b392-4241bf43d5fc.xml +68 -0
- data/test/stub_responses/records/invoice-33e4123e-7cdd-4f05-9a0a-eb8adeb2b868.xml +92 -0
- data/test/stub_responses/records/invoice-387db692-26ac-47e6-b6cc-015343809bda.xml +73 -0
- data/test/stub_responses/records/invoice-3b28bf11-ed2f-4cf4-8e9e-fcae730cc292.xml +89 -0
- data/test/stub_responses/records/invoice-3fcb9847-b350-412e-ab90-7d9d774ad881.xml +89 -0
- data/test/stub_responses/records/invoice-4602eda6-abe9-448e-b65f-ae6bea21f0eb.xml +96 -0
- data/test/stub_responses/records/invoice-46441f63-873f-4cdc-a278-b8fe516f3abb.xml +91 -0
- data/test/stub_responses/records/invoice-4ad1ec01-f4a3-41d7-bbb4-d2ab2fec8e65.xml +73 -0
- data/test/stub_responses/records/invoice-4b9afceb-f7c7-4e64-8aac-7b009971fd52.xml +84 -0
- data/test/stub_responses/records/invoice-4edbf6d5-4e92-43af-bedd-7effc0b86833.xml +68 -0
- data/test/stub_responses/records/invoice-4fad1af2-b871-4ac5-a15a-3c5e32d2e2c4.xml +83 -0
- data/test/stub_responses/records/invoice-52ee4d67-cae4-462c-adb2-182c39017f3d.xml +81 -0
- data/test/stub_responses/records/invoice-54585f46-c1a0-4432-bd4f-c1fae2fba59b.xml +66 -0
- data/test/stub_responses/records/invoice-5613938b-9e27-472e-92ae-3b038b669d10.xml +85 -0
- data/test/stub_responses/records/invoice-5aa9451d-95d1-4f95-a966-bbab2573f71c.xml +73 -0
- data/test/stub_responses/records/invoice-5aadcd34-01a9-4b8d-a2bb-d7cc1de9fa45.xml +87 -0
- data/test/stub_responses/records/invoice-5f6deadf-36a2-495a-9980-ceb11e8af9a9.xml +83 -0
- data/test/stub_responses/records/invoice-625ffe1b-f5d8-438e-a376-981de5f5a733.xml +75 -0
- data/test/stub_responses/records/invoice-64cd559e-8e03-46af-b461-8555285cee71.xml +84 -0
- data/test/stub_responses/records/invoice-666f8dbb-bc9a-476c-8ec4-4665d7f83190.xml +63 -0
- data/test/stub_responses/records/invoice-66fbe37f-49b1-43fd-97ed-85114022cd2f.xml +77 -0
- data/test/stub_responses/records/invoice-673dd7cc-beb7-4697-83d4-0c47cb400cc2.xml +85 -0
- data/test/stub_responses/records/invoice-69fc971e-9b37-41c5-9c87-174330f22343.xml +65 -0
- data/test/stub_responses/records/invoice-70e6db69-e5a4-42c7-a397-aa3212c2945f.xml +73 -0
- data/test/stub_responses/records/invoice-766d1289-b440-4675-a656-1a0612ecac77.xml +74 -0
- data/test/stub_responses/records/invoice-76bcb361-f93b-4513-b312-5a4af306d276.xml +66 -0
- data/test/stub_responses/records/invoice-76e3f056-479f-417c-a72b-f3d767899b87.xml +89 -0
- data/test/stub_responses/records/invoice-77b338ef-ecc0-4b95-a0d7-2617b0054611.xml +103 -0
- data/test/stub_responses/records/invoice-7be9956d-5316-4f6b-a66a-d355b3f159b2.xml +82 -0
- data/test/stub_responses/records/invoice-7dae876a-b424-436b-a4e6-17b3fdeec80c.xml +82 -0
- data/test/stub_responses/records/invoice-7e862d93-8dab-4856-8b0c-d844e09d750f.xml +66 -0
- data/test/stub_responses/records/invoice-803f70b0-56d9-4157-9787-41df271777a0.xml +82 -0
- data/test/stub_responses/records/invoice-86102312-aa3f-438c-9938-6840f4d8dda6.xml +74 -0
- data/test/stub_responses/records/invoice-8694c9c5-7097-4449-a708-b8c1982921a4.xml +68 -0
- data/test/stub_responses/records/invoice-86d6e00f-ef56-49f7-9a54-796ccd5ca057.xml +83 -0
- data/test/stub_responses/records/invoice-88e77f0f-54a5-4efc-a979-7e22223cc4d7.xml +65 -0
- data/test/stub_responses/records/invoice-8b0ccb6a-d9b7-4da5-8360-ef7fb157b5aa.xml +65 -0
- data/test/stub_responses/records/invoice-935fc854-8037-4111-8d91-993010c331cc.xml +73 -0
- data/test/stub_responses/records/invoice-95ef3000-c764-4ba9-a66a-b6e2d161f839.xml +62 -0
- data/test/stub_responses/records/invoice-962ef33f-c9d2-4602-9b9f-93a02bea23b3.xml +90 -0
- data/test/stub_responses/records/invoice-9868b472-1983-48e9-8edf-7e81ddf2c03a.xml +83 -0
- data/test/stub_responses/records/invoice-9a448e9b-a9fa-4a8b-98f5-6dc892a37374.xml +62 -0
- data/test/stub_responses/records/invoice-a1d04a14-96a8-4067-a0ff-8136990a354f.xml +91 -0
- data/test/stub_responses/records/invoice-a3bc62ef-f11b-4a9c-a4f9-a342bda371b5.xml +65 -0
- data/test/stub_responses/records/invoice-a6894ca0-60ee-4d45-9dd4-b44fcba46ec5.xml +88 -0
- data/test/stub_responses/records/invoice-a9f765e6-b9bc-4505-a47b-fb3ecb327e7b.xml +85 -0
- data/test/stub_responses/records/invoice-aa0173af-8707-4e7f-8dde-4c7a357bd312.xml +92 -0
- data/test/stub_responses/records/invoice-ab63738a-370a-43a5-bfa3-620d684e66d0.xml +81 -0
- data/test/stub_responses/records/invoice-b0344791-5a8a-40dd-a208-d99a461a6c10.xml +82 -0
- data/test/stub_responses/records/invoice-b1e53910-473c-46a3-b3cb-38ece571220e.xml +66 -0
- data/test/stub_responses/records/invoice-b2c02d0b-41a8-4d4d-97d7-014c78b3547d.xml +91 -0
- data/test/stub_responses/records/invoice-b75b3928-ab72-4424-8b93-9cdbbde4cd72.xml +80 -0
- data/test/stub_responses/records/invoice-bcd8a71f-aa31-4d0f-8a01-13ea26363ddf.xml +92 -0
- data/test/stub_responses/records/invoice-bfbb7c45-de02-45e7-b065-d9863ecfb0d8.xml +65 -0
- data/test/stub_responses/records/invoice-c12aff7e-12bf-4185-8702-460929f19674.xml +76 -0
- data/test/stub_responses/records/invoice-c3380b96-976d-4b3e-8b26-8d01eb6a3742.xml +85 -0
- data/test/stub_responses/records/invoice-c963f2b0-cbe1-4abd-9ccc-7e512c942068.xml +66 -0
- data/test/stub_responses/records/invoice-d62646b9-d0a9-4fdb-9561-756a8b7eba45.xml +63 -0
- data/test/stub_responses/records/invoice-dba2f021-f149-4191-a126-5351d587ab0e.xml +74 -0
- data/test/stub_responses/records/invoice-de5d9c29-21b3-4342-958b-ed72c4bd7ab0.xml +106 -0
- data/test/stub_responses/records/invoice-e3d96555-2876-4364-a46a-7551a4f52611.xml +119 -0
- data/test/stub_responses/records/invoice-e4a0afbd-aea0-450b-ae23-0ce921e84a77.xml +99 -0
- data/test/stub_responses/records/invoice-e9cb9ecb-58ef-43a8-bd20-69a85338142d.xml +74 -0
- data/test/stub_responses/records/invoice-ec9a6f67-7128-4a63-8ba3-5e516f455f9b.xml +92 -0
- data/test/stub_responses/records/invoice-ed0f2587-84fc-4aef-bc4b-b1a262e24484.xml +78 -0
- data/test/stub_responses/records/invoice-f362ca53-8ade-4047-865a-bb64bee5863d.xml +73 -0
- data/test/stub_responses/records/invoice-f571c38b-5be1-41e1-ad5a-ff6184284beb.xml +104 -0
- data/test/stub_responses/records/invoice-f5832195-5cd3-4660-ad3f-b73d9c64f263.xml +83 -0
- data/test/stub_responses/records/invoice-f9c857eb-64cd-4235-a078-d04b52c77ea7.xml +74 -0
- data/test/stub_responses/records/manual_journal-4765d07b-aa03-4e56-9166-50661958c864.xml +38 -0
- data/test/stub_responses/records/manual_journal-53fc5558-5b76-4ecd-ae5c-c4af3ccde87c.xml +31 -0
- data/test/stub_responses/records/manual_journal-bb6cfcfc-4500-4475-bd3a-93ee512428e0.xml +31 -0
- data/test/stub_responses/records/manual_journal-f00a355b-7374-445c-886b-0437bea4095c.xml +45 -0
- data/test/stub_responses/refresh_responses.rb +29 -0
- data/test/stub_responses/tax_rates.xml +118 -0
- data/test/stub_responses/token_expired +1 -0
- data/test/stub_responses/tracking_categories.xml +27 -0
- data/test/stub_responses/unknown_error.xml +1 -0
- data/test/test_helper.rb +49 -0
- data/test/unit/models/contact_test.rb +26 -0
- data/test/unit/models/credit_note_test.rb +37 -0
- data/test/unit/models/invoice_test.rb +51 -0
- data/test/unit/oauth_test.rb +72 -0
- data/test/unit/private_application_test.rb +20 -0
- data/test/unit/record/base_model_test.rb +50 -0
- data/test/unit/record/base_test.rb +57 -0
- data/test/unit/record/model_definition_test.rb +159 -0
- data/test/unit/record/parse_where_hash_test.rb +63 -0
- data/test/unit/record/record_association_test.rb +36 -0
- data/test/unit/record/validators_test.rb +180 -0
- data/xeroizer.gemspec +375 -0
- metadata +533 -0
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
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
|
+
|
|
6
|
+
module Xeroizer
|
|
7
|
+
module Record
|
|
8
|
+
|
|
9
|
+
class Base
|
|
10
|
+
|
|
11
|
+
include ClassLevelInheritableAttributes
|
|
12
|
+
class_inheritable_attributes :fields, :possible_primary_keys, :primary_key_name, :summary_only, :validators
|
|
13
|
+
|
|
14
|
+
attr_reader :attributes
|
|
15
|
+
attr_reader :parent
|
|
16
|
+
attr_accessor :errors
|
|
17
|
+
attr_accessor :complete_record_downloaded
|
|
18
|
+
|
|
19
|
+
include ModelDefinitionHelper
|
|
20
|
+
include RecordAssociationHelper
|
|
21
|
+
include ValidationHelper
|
|
22
|
+
include XmlHelper
|
|
23
|
+
|
|
24
|
+
class << self
|
|
25
|
+
|
|
26
|
+
# Build a record with attributes set to the value of attributes.
|
|
27
|
+
def build(attributes, parent)
|
|
28
|
+
record = new(parent)
|
|
29
|
+
attributes.each do | key, value |
|
|
30
|
+
record.send("#{key}=".to_sym, value)
|
|
31
|
+
end
|
|
32
|
+
record
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
public
|
|
38
|
+
|
|
39
|
+
def initialize(parent)
|
|
40
|
+
@parent = parent
|
|
41
|
+
@attributes = {}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def new_model_class(model_name)
|
|
45
|
+
Xeroizer::Record.const_get("#{model_name}Model".to_sym).new(parent.application, model_name.to_s)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def [](attribute)
|
|
49
|
+
self.send(attribute)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def []=(attribute, value)
|
|
53
|
+
self.send("#{attribute}=", value)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def new_record?
|
|
57
|
+
self.class.possible_primary_keys.all? { | key | @attributes[key].nil? }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Check to see if the complete record is downloaded.
|
|
61
|
+
def complete_record_downloaded?
|
|
62
|
+
if !!self.class.list_contains_summary_only?
|
|
63
|
+
!!complete_record_downloaded
|
|
64
|
+
else
|
|
65
|
+
true
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Downloads the complete record if we only have a summary of the record.
|
|
70
|
+
def download_complete_record!
|
|
71
|
+
record = self.parent.find(self.id)
|
|
72
|
+
@attributes = record.attributes if record
|
|
73
|
+
@complete_record_downloaded = true
|
|
74
|
+
self
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def save
|
|
78
|
+
return false unless valid?
|
|
79
|
+
if new_record?
|
|
80
|
+
create
|
|
81
|
+
else
|
|
82
|
+
update
|
|
83
|
+
end
|
|
84
|
+
true
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
protected
|
|
88
|
+
|
|
89
|
+
# Attempt to create a new record.
|
|
90
|
+
def create
|
|
91
|
+
parse_save_response(parent.http_put(to_xml))
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Attempt to update an existing record.
|
|
95
|
+
def update
|
|
96
|
+
if self.class.possible_primary_keys && self.class.possible_primary_keys.all? { | possible_key | self[possible_key].nil? }
|
|
97
|
+
raise RecordKeyMustBeDefined.new(self.class.possible_primary_keys)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
parse_save_response(parent.http_post(to_xml))
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Parse the response from a create/update request.
|
|
104
|
+
def parse_save_response(response_xml)
|
|
105
|
+
record = parent.parse_response(response_xml)
|
|
106
|
+
record = record.first if record.is_a?(Array)
|
|
107
|
+
if record && record.is_a?(self.class)
|
|
108
|
+
@attributes = record.attributes
|
|
109
|
+
end
|
|
110
|
+
self
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
require 'xeroizer/record/base_model_http_proxy'
|
|
2
|
+
|
|
3
|
+
module Xeroizer
|
|
4
|
+
module Record
|
|
5
|
+
|
|
6
|
+
class BaseModel
|
|
7
|
+
|
|
8
|
+
include ClassLevelInheritableAttributes
|
|
9
|
+
class_inheritable_attributes :api_controller_name
|
|
10
|
+
|
|
11
|
+
class InvaidPermissionError < StandardError; end
|
|
12
|
+
ALLOWED_PERMISSIONS = [:read, :write, :update]
|
|
13
|
+
class_inheritable_attributes :permissions
|
|
14
|
+
|
|
15
|
+
include BaseModelHttpProxy
|
|
16
|
+
|
|
17
|
+
attr_reader :application
|
|
18
|
+
attr_reader :model_name
|
|
19
|
+
attr :model_class
|
|
20
|
+
attr_reader :response
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
|
|
24
|
+
# Method to allow override of the default controller name used
|
|
25
|
+
# in the API URLs.
|
|
26
|
+
#
|
|
27
|
+
# Default: pluaralized model name (e.g. if the controller name is
|
|
28
|
+
# Invoice then the default is Invoices.
|
|
29
|
+
def set_api_controller_name(controller_name)
|
|
30
|
+
self.api_controller_name = controller_name
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Set the permissions allowed for this class type.
|
|
34
|
+
# There are no permissions set by default.
|
|
35
|
+
# Valid permissions are :read, :write, :update.
|
|
36
|
+
def set_permissions(*args)
|
|
37
|
+
self.permissions = {}
|
|
38
|
+
args.each do | permission |
|
|
39
|
+
raise InvaidPermissionError.new("Permission #{permission} is invalid.") unless ALLOWED_PERMISSIONS.include?(permission)
|
|
40
|
+
self.permissions[permission] = true
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
public
|
|
47
|
+
|
|
48
|
+
def initialize(application, model_name)
|
|
49
|
+
@application = application
|
|
50
|
+
@model_name = model_name
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Retrieve the controller name.
|
|
54
|
+
#
|
|
55
|
+
# Default: pluaralized model name (e.g. if the controller name is
|
|
56
|
+
# Invoice then the default is Invoices.
|
|
57
|
+
def api_controller_name
|
|
58
|
+
self.class.api_controller_name || model_name.pluralize
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def model_class
|
|
62
|
+
@model_class ||= Xeroizer::Record.const_get(model_name.to_sym)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Build a record with attributes set to the value of attributes.
|
|
66
|
+
def build(attributes = {})
|
|
67
|
+
model_class.build(attributes, self)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Retreive full record list for this model.
|
|
71
|
+
def all(options = {})
|
|
72
|
+
raise MethodNotAllowed.new(self, :all) unless self.class.permissions[:read]
|
|
73
|
+
response_xml = http_get(parse_params(options))
|
|
74
|
+
parse_response(response_xml, options) || []
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Helper method to retrieve just the first element from
|
|
78
|
+
# the full record list.
|
|
79
|
+
def first(options = {})
|
|
80
|
+
raise MethodNotAllowed.new(self, :all) unless self.class.permissions[:read]
|
|
81
|
+
result = all(options)
|
|
82
|
+
result.first if result.is_a?(Array)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Retrieve record matching the passed in ID.
|
|
86
|
+
def find(id, options = {})
|
|
87
|
+
raise MethodNotAllowed.new(self, :all) unless self.class.permissions[:read]
|
|
88
|
+
response_xml = @application.http_get(@application.client, "#{url}/#{CGI.escape(id)}", options)
|
|
89
|
+
result = parse_response(response_xml, options)
|
|
90
|
+
result = result.first if result.is_a?(Array)
|
|
91
|
+
result.complete_record_downloaded = true if result
|
|
92
|
+
result
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Parse the response retreived during any request.
|
|
96
|
+
def parse_response(raw_response, request = {}, options = {})
|
|
97
|
+
@response = Xeroizer::Response.new
|
|
98
|
+
@response.response_xml = raw_response
|
|
99
|
+
|
|
100
|
+
doc = Nokogiri::XML(raw_response) { | cfg | cfg.noblanks }
|
|
101
|
+
|
|
102
|
+
# check for responses we don't understand
|
|
103
|
+
raise Xeroizer::UnparseableResponse.new(doc.root.name) unless doc.root.name == 'Response'
|
|
104
|
+
|
|
105
|
+
doc.root.elements.each do | element |
|
|
106
|
+
|
|
107
|
+
# Text element
|
|
108
|
+
if element.children && element.children.size == 1 && element.children.first.text?
|
|
109
|
+
case element.name
|
|
110
|
+
when 'Id' then @response.id = element.text
|
|
111
|
+
when 'Status' then @response.status = element.text
|
|
112
|
+
when 'ProviderName' then @response.provider = element.text
|
|
113
|
+
when 'DateTimeUTC' then @response.date_time = Time.parse(element.text)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Records in response
|
|
117
|
+
elsif element.children && element.children.size > 0 && element.children.first.name == model_name
|
|
118
|
+
parse_records(element.children)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
@response.response_items
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
protected
|
|
126
|
+
|
|
127
|
+
# Parse the records part of the XML response and builds model instances as necessary.
|
|
128
|
+
def parse_records(elements)
|
|
129
|
+
@response.response_items = []
|
|
130
|
+
elements.each do | element |
|
|
131
|
+
@response.response_items << model_class.build_from_node(element, self)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
module Xeroizer
|
|
2
|
+
module Record
|
|
3
|
+
module BaseModelHttpProxy
|
|
4
|
+
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.send :include, InstanceMethods
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module InstanceMethods
|
|
10
|
+
|
|
11
|
+
public
|
|
12
|
+
|
|
13
|
+
# URL end-point for this model.
|
|
14
|
+
def url
|
|
15
|
+
@application.xero_url + '/' + api_controller_name
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def http_get(extra_params = {})
|
|
19
|
+
application.http_get(application.client, url, extra_params)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def http_put(xml, extra_params = {})
|
|
23
|
+
application.http_put(application.client, url, xml, extra_params)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def http_post(xml, extra_params = {})
|
|
27
|
+
application.http_post(application.client, url, xml, extra_params)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
protected
|
|
31
|
+
|
|
32
|
+
# Parse parameters for GET requests.
|
|
33
|
+
def parse_params(options)
|
|
34
|
+
params = {}
|
|
35
|
+
params[:ModifiedAfter] = options[:modified_since] if options[:modified_since]
|
|
36
|
+
params[:OrderBy] = options[:order] if options[:order]
|
|
37
|
+
if options[:where]
|
|
38
|
+
params[:where] = case options[:where]
|
|
39
|
+
when String then options[:where]
|
|
40
|
+
when Hash then parse_where_hash(options[:where])
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
params[:offset] = options[:offset] if options[:offset]
|
|
44
|
+
params
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Parse the :where part of the options for GET parameters and construct a valid
|
|
48
|
+
# .Net version of the criteria to pass to Xero.
|
|
49
|
+
#
|
|
50
|
+
# Attribute names can be modified as follows to change the expression used:
|
|
51
|
+
# {attribute_name}_is_greater_than or {attribute_name}> uses '>'
|
|
52
|
+
# {attribute_name}_is_greater_than_or_equal_to or {attribute_name}>= uses '>='
|
|
53
|
+
# {attribute_name}_is_less_than or {attribute_name}< uses '<'
|
|
54
|
+
# {attribute_name}_is_less_than_or_equal_to or {attribute_name}< uses '<='
|
|
55
|
+
# DEFAULT: '=='
|
|
56
|
+
def parse_where_hash(where)
|
|
57
|
+
conditions = []
|
|
58
|
+
where.each do | key, value |
|
|
59
|
+
(attribute_name, expression) = extract_expression_from_attribute_name(key)
|
|
60
|
+
(field_name, field) = model_class.fields.find { | k, v | v[:internal_name] == attribute_name }
|
|
61
|
+
if field
|
|
62
|
+
conditions << where_condition_part(field, expression, value)
|
|
63
|
+
else
|
|
64
|
+
raise InvalidAttributeInWhere.new(model_name, attribute_name)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
escaped_where = CGI.escape(conditions.map { | (attr, expression, value) | "#{attr}#{expression}#{value}"}.join('&&'))
|
|
68
|
+
escaped_where
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Extract the attribute name and expression from the attribute.
|
|
72
|
+
#
|
|
73
|
+
# @return [Array] containing [actual_attribute_name, expression]
|
|
74
|
+
def extract_expression_from_attribute_name(key)
|
|
75
|
+
case key.to_s
|
|
76
|
+
when /(_is_not|\<\>)$/
|
|
77
|
+
[
|
|
78
|
+
key.to_s.gsub(/(_is_not|\<\>)$/, '').to_sym,
|
|
79
|
+
'<>'
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
when /(_is_greater_than|\>)$/
|
|
83
|
+
[
|
|
84
|
+
key.to_s.gsub(/(_is_greater_than|\>)$/, '').to_sym,
|
|
85
|
+
'>'
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
when /(_is_greater_than_or_equal_to|\>\=)$/
|
|
89
|
+
[
|
|
90
|
+
key.to_s.gsub(/(_is_greater_than_or_equal_to|\>\=)$/, '').to_sym,
|
|
91
|
+
'>='
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
when /(_is_less_than|\<)$/
|
|
95
|
+
[
|
|
96
|
+
key.to_s.gsub(/(_is_less_than|\<)$/, '').to_sym,
|
|
97
|
+
'<'
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
when /(_is_less_than_or_equal_to|\<\=)$/
|
|
101
|
+
[
|
|
102
|
+
key.to_s.gsub(/(_is_less_than_or_equal_to|\<\=)$/, '').to_sym,
|
|
103
|
+
'<='
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
else
|
|
107
|
+
[key, '==']
|
|
108
|
+
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Creates a condition part array containing the:
|
|
113
|
+
# * Field's API name
|
|
114
|
+
# * Expression
|
|
115
|
+
# * .Net formatted value.
|
|
116
|
+
def where_condition_part(field, expression, value)
|
|
117
|
+
case field[:type]
|
|
118
|
+
when :guid then ["#{field[:api_name]}.ToString()", expression, "\"#{value}\""]
|
|
119
|
+
when :string then [field[:api_name], expression, "\"#{value}\""]
|
|
120
|
+
when :boolean then [field[:api_name], expression, value ? 'true' : 'false']
|
|
121
|
+
when :integer then [field[:api_name], expression, value.to_s]
|
|
122
|
+
when :decimal then [field[:api_name], expression, value.to_s]
|
|
123
|
+
when :date then [field[:api_name], expression, "DateTime.Parse(\"#{value.strftime("%Y-%m-%d")}\")"]
|
|
124
|
+
when :datetime then [field[:api_name], expression, "DateTime.Parse(\"#{value.utc.strftime("%Y-%m-%dT%H:%M:%S")}\")"]
|
|
125
|
+
when :belongs_to then
|
|
126
|
+
when :has_many then
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
module Xeroizer
|
|
2
|
+
module Record
|
|
3
|
+
module ModelDefinitionHelper
|
|
4
|
+
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.extend(ClassMethods)
|
|
7
|
+
base.send :include, InstanceMethods
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module ClassMethods
|
|
11
|
+
|
|
12
|
+
# Possible primary keys. At least one of these must exist before attempting to update a record.
|
|
13
|
+
def set_possible_primary_keys(*args)
|
|
14
|
+
args = [args] unless args.is_a?(Array)
|
|
15
|
+
self.possible_primary_keys = args
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Set the actual Xero primary key for this record.
|
|
19
|
+
def set_primary_key(primary_key_name)
|
|
20
|
+
self.primary_key_name = primary_key_name
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Whether this record type's list results contain summary data only.
|
|
24
|
+
#
|
|
25
|
+
# Records like invoices, when returning a list, only show summary data for
|
|
26
|
+
# certain types of associations (like the contact record) and do not return
|
|
27
|
+
# any data for line items.
|
|
28
|
+
#
|
|
29
|
+
# Default: false
|
|
30
|
+
def list_contains_summary_only(status)
|
|
31
|
+
self.summary_only = status
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def list_contains_summary_only?
|
|
35
|
+
!!summary_only
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Helper methods used to define the fields this model has.
|
|
39
|
+
def string(field_name, options = {}); define_simple_attribute(field_name, :string, options); end
|
|
40
|
+
def boolean(field_name, options = {}); define_simple_attribute(field_name, :boolean, options); end
|
|
41
|
+
def integer(field_name, options = {}); define_simple_attribute(field_name, :integer, options, 0); end
|
|
42
|
+
def decimal(field_name, options = {}); define_simple_attribute(field_name, :decimal, options, 0.0); end
|
|
43
|
+
def date(field_name, options = {}); define_simple_attribute(field_name, :date, options); end
|
|
44
|
+
def datetime(field_name, options = {}); define_simple_attribute(field_name, :datetime, options); end
|
|
45
|
+
|
|
46
|
+
def guid(field_name, options = {})
|
|
47
|
+
# Ensure all automated Id conversions are changed to ID.
|
|
48
|
+
options[:api_name] ||= field_name.to_s.camelize.gsub(/Id/, 'ID')
|
|
49
|
+
define_simple_attribute(field_name, :guid, options)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Helper method to simplify field definition.
|
|
53
|
+
# Creates an accessor and reader for the field.
|
|
54
|
+
# Options:
|
|
55
|
+
# :internal_name => allows the specification of an internal field name differing from the API's field name.
|
|
56
|
+
# :api_name => allows the API name to be specified if it can't be properly converted from camelize.
|
|
57
|
+
# :model_name => allows class used for children to be different from it's ndoe name in the XML.
|
|
58
|
+
# :type => type of field
|
|
59
|
+
def define_simple_attribute(field_name, field_type, options, value_if_nil = nil)
|
|
60
|
+
self.fields ||= {}
|
|
61
|
+
|
|
62
|
+
internal_field_name = options[:internal_name] || field_name
|
|
63
|
+
self.fields[field_name] = options.merge({
|
|
64
|
+
:internal_name => internal_field_name,
|
|
65
|
+
:api_name => options[:api_name] || field_name.to_s.camelize,
|
|
66
|
+
:type => field_type
|
|
67
|
+
})
|
|
68
|
+
define_method internal_field_name do
|
|
69
|
+
@attributes[field_name] || value_if_nil
|
|
70
|
+
end
|
|
71
|
+
define_method "#{internal_field_name}=".to_sym do | value |
|
|
72
|
+
@attributes[field_name] = value
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
module InstanceMethods
|
|
79
|
+
|
|
80
|
+
# Returns the value of the Xero primary key for this record if it exists.
|
|
81
|
+
def id
|
|
82
|
+
self[self.class.primary_key_name]
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Sets the value of the Xero primary key for this record if it exists.
|
|
86
|
+
def id=(new_id)
|
|
87
|
+
self[self.class.primary_key_name] = new_id
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|