fakturoid 0.5.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -10
  3. data/.ruby-version +1 -1
  4. data/CHANGELOG.md +11 -0
  5. data/README.md +501 -145
  6. data/Rakefile +3 -1
  7. data/fakturoid.gemspec +36 -25
  8. data/lib/fakturoid/api/account.rb +13 -0
  9. data/lib/fakturoid/api/bank_account.rb +13 -0
  10. data/lib/fakturoid/api/base.rb +18 -0
  11. data/lib/fakturoid/api/event.rb +23 -0
  12. data/lib/fakturoid/api/expense.rb +55 -0
  13. data/lib/fakturoid/api/expense_payment.rb +20 -0
  14. data/lib/fakturoid/api/generator.rb +36 -0
  15. data/lib/fakturoid/api/inbox_file.rb +34 -0
  16. data/lib/fakturoid/api/inventory_item.rb +66 -0
  17. data/lib/fakturoid/api/inventory_move.rb +40 -0
  18. data/lib/fakturoid/api/invoice.rb +62 -0
  19. data/lib/fakturoid/api/invoice_message.rb +14 -0
  20. data/lib/fakturoid/api/invoice_payment.rb +26 -0
  21. data/lib/fakturoid/api/number_format.rb +13 -0
  22. data/lib/fakturoid/api/recurring_generator.rb +36 -0
  23. data/lib/fakturoid/api/subject.rb +42 -0
  24. data/lib/fakturoid/api/todo.rb +20 -0
  25. data/lib/fakturoid/api/user.rb +17 -0
  26. data/lib/fakturoid/api.rb +84 -9
  27. data/lib/fakturoid/client.rb +46 -12
  28. data/lib/fakturoid/config.rb +69 -12
  29. data/lib/fakturoid/oauth/access_token_service.rb +46 -0
  30. data/lib/fakturoid/oauth/credentials.rb +63 -0
  31. data/lib/fakturoid/oauth/flow/authorization_code.rb +53 -0
  32. data/lib/fakturoid/oauth/flow/base.rb +42 -0
  33. data/lib/fakturoid/oauth/flow/client_credentials.rb +27 -0
  34. data/lib/fakturoid/oauth/flow.rb +5 -0
  35. data/lib/fakturoid/oauth/request/api.rb +11 -0
  36. data/lib/fakturoid/oauth/request/base.rb +60 -0
  37. data/lib/fakturoid/oauth/request/oauth.rb +24 -0
  38. data/lib/fakturoid/oauth/request.rb +5 -0
  39. data/lib/fakturoid/oauth/token_response.rb +56 -0
  40. data/lib/fakturoid/oauth.rb +39 -0
  41. data/lib/fakturoid/response.rb +8 -20
  42. data/lib/fakturoid/utils.rb +27 -0
  43. data/lib/fakturoid/version.rb +1 -1
  44. data/lib/fakturoid.rb +22 -22
  45. metadata +47 -53
  46. data/.github/workflows/rubocop.yml +0 -20
  47. data/.github/workflows/tests.yml +0 -27
  48. data/.gitignore +0 -7
  49. data/Gemfile +0 -6
  50. data/lib/fakturoid/api/arguments.rb +0 -21
  51. data/lib/fakturoid/api/http_methods.rb +0 -23
  52. data/lib/fakturoid/client/account.rb +0 -11
  53. data/lib/fakturoid/client/bank_account.rb +0 -11
  54. data/lib/fakturoid/client/event.rb +0 -19
  55. data/lib/fakturoid/client/expense.rb +0 -49
  56. data/lib/fakturoid/client/generator.rb +0 -44
  57. data/lib/fakturoid/client/inventory_items.rb +0 -59
  58. data/lib/fakturoid/client/inventory_moves.rb +0 -36
  59. data/lib/fakturoid/client/invoice.rb +0 -73
  60. data/lib/fakturoid/client/number_format.rb +0 -11
  61. data/lib/fakturoid/client/subject.rb +0 -41
  62. data/lib/fakturoid/client/todo.rb +0 -18
  63. data/lib/fakturoid/client/user.rb +0 -20
  64. data/lib/fakturoid/connection.rb +0 -30
  65. data/lib/fakturoid/request.rb +0 -31
  66. data/test/api_test.rb +0 -24
  67. data/test/config_test.rb +0 -40
  68. data/test/fixtures/blocked_account.json +0 -8
  69. data/test/fixtures/invoice.json +0 -81
  70. data/test/fixtures/invoice.pdf +0 -0
  71. data/test/fixtures/invoice_error.json +0 -7
  72. data/test/fixtures/subjects.json +0 -52
  73. data/test/request_test.rb +0 -20
  74. data/test/response_test.rb +0 -189
  75. data/test/test_helper.rb +0 -19
data/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # Fakturoid
2
2
 
3
- The Fakturoid gem is ruby library for API communication with web based invoicing service [www.fakturoid.cz](https://fakturoid.cz).
4
- Fakturoid [API documentation](https://fakturoid.docs.apiary.io/).
3
+ The Fakturoid gem is Ruby library for API communication with web based invoicing service [www.fakturoid.cz](https://www.fakturoid.cz/).
4
+
5
+ Fakturoid [API documentation](https://www.fakturoid.cz/api/v3).
5
6
 
6
7
  [![Gem Version](https://badge.fury.io/rb/fakturoid.svg)](http://badge.fury.io/rb/fakturoid)
7
8
  [![Tests](https://github.com/fakturoid/fakturoid-ruby/actions/workflows/tests.yml/badge.svg)](https://github.com/fakturoid/fakturoid-ruby/actions/workflows/tests.yml)
@@ -17,148 +18,260 @@ gem "fakturoid"
17
18
 
18
19
  And then run:
19
20
 
20
- $ bundle
21
+ ```sh
22
+ bundle
23
+ ```
24
+
25
+ ## Gem Versions
26
+
27
+ | Gem version | Fakturoid API | Supported Ruby |
28
+ |-------------|---------------------------------------------|----------------|
29
+ | `1.x` | [API v3](https://www.fakturoid.cz/api/v3) | `>=2.7.0` |
30
+ | `0.x` | [API v2](https://fakturoid.docs.apiary.io/) | `>=2.7.0` |
21
31
 
22
32
  ## Configuration
23
33
 
24
- Fakturoid gem is configured within config block placed in `config/initializers/fakturoid.rb`:
34
+ ### Authorization with OAuth 2.0
35
+
36
+ #### Authorization Code Flow
37
+
38
+ Authorization using OAuth takes place in several steps. We use data obtained from the developer portal as client ID and
39
+ client secret (Settings → Connect other apps → OAuth 2 for app developers).
40
+
41
+ First, we offer the user a URL address where he enters his login information. We obtain this using the following method
42
+ (you can place it in an intializer `config/initializers/fakturoid.rb`):
25
43
 
26
44
  ```ruby
27
45
  Fakturoid.configure do |config|
28
- config.email = "yourfakturoid@email.com"
29
- config.api_key = "fasdff823fdasWRFKW843ladfjklasdf834"
30
- config.account = "applecorp" # former subdomain (first part of URL)
31
- config.user_agent = "Name of your app (your@email.com)"
46
+ config.email = "yourfakturoid@email.com"
47
+ config.account = "{fakturoid-account-slug}" # You can also set `account` dynamically later.
48
+ config.user_agent = "Name of your app (your@email.com)"
49
+ config.client_id = "{fakturoid-client-id}"
50
+ config.client_secret = "{fakturoid-client-secret}"
51
+ config.redirect_uri = "{your-redirect-uri}"
52
+ config.oauth_flow = "authorization_code"
32
53
  end
33
54
  ```
34
55
 
35
- ## Usage
56
+ Create a client and let the user come to our OAuth login page:
36
57
 
37
- ### Account resource
58
+ ```ruby
59
+ client = Fakturoid.client
60
+
61
+ # To be rendered on a web page. State is optional.
62
+ link_to client.authorization_uri, "Enable Fakturoid Integration"
63
+ link_to client.authorization_uri(state: "abcd1234"), "Enable Fakturoid Integration"
64
+ ```
38
65
 
39
- To get information about your account in Fakturoid run following code:
66
+ After entering the login data, the user is redirected to the specified redirect URI and with the code with which we
67
+ obtain his credentials. We process the code as follows:
40
68
 
41
69
  ```ruby
42
- response = Fakturoid::Client::Account.current
43
- response.status_code # returns response http code
44
- response.body # contains hash with returned body
70
+ client.authorize(code: params[:code])
45
71
  ```
46
72
 
47
- Accessing content of returned body:
73
+ Credentials are now established in the object instance and we can send queries to the Fakturoid API.
48
74
 
49
75
  ```ruby
50
- response.body["name"] # return name of your company
51
- response.name # alternative way of getting the name of your company
76
+ pp client.credentials.as_json
52
77
  ```
53
78
 
54
- For the list of all returned account fields see the [Account API documentation](https://fakturoid.docs.apiary.io/#reference/account)
79
+ Credentials can also be set manually (eg. loaded from a database):
55
80
 
56
- ### User resource
81
+ ```ruby
82
+ client.credentials = {
83
+ access_token: "1db22484a6d6256e7942158d216157d075ab6e7b583bd16416181ca6c4ac180167acd8d599bd123d", # Example
84
+ refresh_token: "5682a4bc6254d85934a03931ed5e235e0f81bca64aef054fa0049d8c953eab919ba67bd8ceb532d7",
85
+ expires_at: "2024-03-01T12:42:40+01:00", # This also accepts `Time` or `DateTime` object.
86
+ token_type: "Bearer"
87
+ }
88
+ ```
57
89
 
58
- For the information about current user use following code:
90
+ Don't forget to update your credentials after an access token refresh:
59
91
 
60
92
  ```ruby
61
- response = Fakturoid::Client::User.current
93
+ client.credentials_updated_callback do |credentials|
94
+ # Store new credentials into database.
95
+ pp client.credentials.as_json
96
+ end
62
97
  ```
63
98
 
64
- For all the users which belongs to current account:
99
+ You may need to set account slug dynamically:
65
100
 
66
101
  ```ruby
67
- response = Fakturoid::Client::User.all
102
+ client.account = client.users.current.body["accounts"].first["slug"]
68
103
  ```
69
104
 
70
- If you want to get information about one user which belongs to account use:
105
+ And if you need to create a separate client for a different account:
71
106
 
72
107
  ```ruby
73
- response = Fakturoid::Client::User.find(user_id)
108
+ client = Fakturoid::Client.new(account: "{another-fakturoid-account-slug}")
74
109
  ```
75
110
 
76
- For the list of all returned user fields see the [Users API documentation](https://fakturoid.docs.apiary.io/#reference/users)
111
+ Revoke access altogether (works in both flows):
77
112
 
78
- ### Number Format resource
113
+ ```ruby
114
+ client.revoke_access
115
+ ```
79
116
 
80
- For the list of invoice number formats which belong to the current account:
117
+ #### Client Credentials Flow
81
118
 
82
119
  ```ruby
83
- response = Fakturoid::Client::NumberFormat.invoices
120
+ Fakturoid.configure do |config|
121
+ config.email = "yourfakturoid@email.com"
122
+ config.account = "{fakturoid-account-slug}"
123
+ config.user_agent = "Name of your app (your@email.com)"
124
+ config.client_id = "{fakturoid-client-id}"
125
+ config.client_secret = "{fakturoid-client-secret}"
126
+ config.oauth_flow = "client_credentials"
127
+ end
84
128
  ```
85
129
 
86
- For the list of all returned user fields see the [Number formats API documentation](https://fakturoid.docs.apiary.io/#reference/number-formats)
130
+ Credentials can be set and stored the same way as above just without a refresh token.
87
131
 
88
- ### Subject resource
132
+ ## Usage
133
+
134
+ Almost all resources that return a list of things are paginated by 40 per page. You can specify the page number
135
+ by passing a `page` parameter: `client.some_resource.all(page: 2)`.
89
136
 
90
- To get all subjects run (Subjects are paginated by 20 per page):
137
+ ### [User Resource](https://www.fakturoid.cz/api/v3/users)
138
+
139
+ Get current user information along with a list of accounts he/she has access to
91
140
 
92
141
  ```ruby
93
- response = Fakturoid::Client::Subject.all(page: 2)
142
+ response = client.users.current
143
+ response.status_code # Returns response HTTP code.
144
+ response.body # Contains hash with returned body (JSON is parsed automatically).
94
145
  ```
95
146
 
96
- Fulltext search subjects:
147
+ Accessing content of returned body:
97
148
 
98
149
  ```ruby
99
- response = Fakturoid::Client::Subject.search("Client name")
150
+ response.body["name"] # Return name of your company.
151
+ response.name # Alternative way of getting the name of your company.
100
152
  ```
101
153
 
102
- To find one subject use:
154
+ Get a list of all account users:
103
155
 
104
156
  ```ruby
105
- response = Fakturoid::Client::Subject.find(subject_id)
157
+ response = client.users.all
106
158
  ```
107
159
 
108
- You can create new subject with:
160
+ ### [Account Resource](https://www.fakturoid.cz/api/v3/account)
161
+
162
+ Get Fakturoid account information:
109
163
 
110
164
  ```ruby
111
- response = Fakturoid::Client::Subject.create(name: "New client")
165
+ response = client.account.current
112
166
  ```
113
167
 
114
- To update subject use following code:
168
+ ### [Bank Account Resource](https://www.fakturoid.cz/api/v3/bank-accounts)
169
+
170
+ Get a list of bank accounts for current account:
115
171
 
116
172
  ```ruby
117
- response = Fakturoid::Client::Subject.update(subject_id, name: "Updated client")
173
+ response = client.bank_accounts.all
118
174
  ```
119
175
 
120
- Delete subject:
176
+ ### [Number Format Resource](https://www.fakturoid.cz/api/v3/number-formats)
177
+
178
+ Get a list of invoice number formats for current account:
121
179
 
122
180
  ```ruby
123
- Fakturoid::Client::Subject.delete subject_id
181
+ response = client.number_formats.invoices
124
182
  ```
125
183
 
126
- For the list of all subject fields and options see the [Subjects API documentation](https://fakturoid.docs.apiary.io/#reference/subjects)
184
+ ### [Subject Resource](https://www.fakturoid.cz/api/v3/subjects)
185
+
186
+ Get a list of subjects:
127
187
 
128
- ### Invoice resource
188
+ ```ruby
189
+ response = client.subjects.all(page: 2)
190
+ ```
129
191
 
130
- To get all invoices run (Invoices are paginated by 20 per page):
192
+ Fulltext search:
131
193
 
132
194
  ```ruby
133
- response = Fakturoid::Client::Invoice.all(page: 2)
195
+ response = client.subjects.search(query: "Client name")
134
196
  ```
135
197
 
136
- Fulltext search invoices:
198
+ Get a specific subject:
137
199
 
138
200
  ```ruby
139
- response = Fakturoid::Client::Invoice.search("Client name")
201
+ response = client.subjects.find(subject_id)
140
202
  ```
141
203
 
142
- To find one invoice use:
204
+ Create a new subject:
143
205
 
144
206
  ```ruby
145
- response = Fakturoid::Client::Invoice.find(invoice_id)
207
+ response = client.subjects.create(name: "New client")
146
208
  ```
147
209
 
148
- To download invoice in PDF format you can use following code:
210
+ Update a subject:
149
211
 
150
212
  ```ruby
151
- response = Fakturoid::Client::Invoice.download_pdf(invoice_id)
213
+ response = client.subjects.update(subject_id, name: "Updated client")
214
+ ```
215
+
216
+ Delete a subject:
217
+
218
+ ```ruby
219
+ client.subjects.delete(subject_id)
220
+ ```
221
+
222
+ ### [Invoice Resource](https://www.fakturoid.cz/api/v3/invoices)
223
+
224
+ Get a list of invoices:
225
+
226
+ ```ruby
227
+ response = client.invoices.all
228
+ ```
229
+
230
+ Fulltext search:
231
+
232
+ ```ruby
233
+ response = client.invoices.search(query: "Client name")
234
+ response = client.invoices.search(tags: "Housing")
235
+ response = client.invoices.search(tags: ["Housing", "Rent"])
236
+ response = client.invoices.search(query: "Client name", tags: ["Housing"])
237
+ ```
238
+
239
+ Get invoice details:
240
+
241
+ ```ruby
242
+ response = client.invoices.find(invoice_id)
243
+ ```
244
+
245
+ Download invoice in PDF format:
246
+
247
+ ```ruby
248
+ response = client.invoices.download_pdf(invoice_id)
152
249
 
153
250
  File.open("/path/to/file.pdf", "wb") do |f|
154
251
  f.write(response.body)
155
252
  end
156
253
  ```
157
254
 
158
- You can create new invoice with:
255
+ Download an attachment:
159
256
 
160
257
  ```ruby
161
- invoice = {
258
+ response = client.invoices.download_attachment(invoice_id, attachment_id)
259
+
260
+ File.open("/path/to/attachment.pdf", "wb") do |f|
261
+ f.write(response.body)
262
+ end
263
+ ```
264
+
265
+ Invoice actions (eg. lock invoice, cancel, etc., full list is in the API documentation):
266
+
267
+ ```ruby
268
+ response = client.invoices.fire(invoice_id, "lock")
269
+ ```
270
+
271
+ Create an invoice:
272
+
273
+ ```ruby
274
+ data = {
162
275
  subject_id: 123,
163
276
  lines: [
164
277
  {
@@ -170,79 +283,222 @@ invoice = {
170
283
  }
171
284
  ]
172
285
  }
173
- response = Fakturoid::Client::Invoice.create(invoice)
286
+ response = client.invoices.create(data)
174
287
  ```
175
288
 
176
- Invoice actions (eg. pay invoice):
289
+ Update an invoice:
177
290
 
178
291
  ```ruby
179
- response = Fakturoid::Client::Invoice.fire(invoice_id, "pay")
292
+ response = client.invoices.update(invoice_id, number: "2015-0015")
180
293
  ```
181
294
 
182
- Send invoice with customized message (for more information see [the API Documentation](https://fakturoid.docs.apiary.io/#reference/messages)):
295
+ Delete an invoice:
183
296
 
184
297
  ```ruby
185
- message = {
298
+ response = client.invoices.delete(invoice_id)
299
+ ```
300
+
301
+ ### [Invoice Payment Resource](https://www.fakturoid.cz/api/v3/invoice-payments)
302
+
303
+ Create an invoice payment:
304
+
305
+ ```ruby
306
+ response = client.invoice_payments.create(invoice_id, paid_on: Date.today)
307
+ response = client.invoice_payments.create(invoice_id, amount: "500")
308
+ ````
309
+
310
+ Create a tax document for a payment:
311
+
312
+ ```ruby
313
+ response = client.invoice_payments.create_tax_document(invoice_id, payment_id)
314
+ tax_document_response = client.invoices.find(response.tax_document_id)
315
+ ````
316
+
317
+ Delete a payment:
318
+
319
+ ```ruby
320
+ response = client.invoice_payments.delete(invoice_id, payment_id)
321
+ ```
322
+
323
+ ### [Invoice Message Resource](https://www.fakturoid.cz/api/v3/invoice-messages)
324
+
325
+ Send a message to the client (you can use more variables in the `message`, full list is in the API documentation):
326
+
327
+ ```ruby
328
+ data = {
186
329
  email: "testemail@testemail.cz",
187
330
  email_copy: "some@emailcopy.cz",
188
331
  subject: "I have an invoice for you",
189
332
  message: "Hi,\n\nyou can find invoice no. #no# on the following page #link#\n\nHave a nice day"
190
333
  }
191
334
 
192
- response = Fakturoid::Client::Invoice.deliver_message(181, message)
193
- response.status_code # => 201
335
+ response = client.invoice_messages.create(invoice_id, data)
336
+ ```
337
+
338
+ ### [Expense Resource](https://www.fakturoid.cz/api/v3/expenses)
339
+
340
+ Get a list of expenses:
341
+
342
+ ```ruby
343
+ response = client.expenses.all
344
+ ```
345
+
346
+ Fulltext search:
347
+
348
+ ```ruby
349
+ response = client.expenses.search(query: "Supplier name")
350
+ response = client.expenses.search(tags: "Housing")
351
+ response = client.expenses.search(tags: ["Housing", "Rent"])
352
+ response = client.expenses.search(query: "Supplier name", tags: ["Housing"])
353
+ ```
354
+
355
+ Get expense details:
356
+
357
+ ```ruby
358
+ response = client.expenses.find(expense_id)
359
+ ```
360
+
361
+ Download an attachment:
362
+
363
+ ```ruby
364
+ response = client.expenses.download_attachment(expense_id, attachment_id)
365
+
366
+ File.open("/path/to/attachment.pdf", "wb") do |f|
367
+ f.write(response.body)
368
+ end
369
+ ```
370
+
371
+ Expense actions (eg. lock expense etc., full list is in the API documentation):
372
+
373
+ ```ruby
374
+ response = client.expenses.fire(expense_id, "lock")
375
+ ```
376
+
377
+ Create an expense:
378
+
379
+ ```ruby
380
+ data = {
381
+ subject_id: 123,
382
+ lines: [
383
+ {
384
+ quantity: 5,
385
+ unit_name: "kg",
386
+ name: "Sand",
387
+ unit_price: "100",
388
+ vat_rate: 21
389
+ }
390
+ ]
391
+ }
392
+ response = client.expenses.create(data)
393
+ ```
394
+
395
+ Update an expense:
396
+
397
+ ```ruby
398
+ response = client.expenses.update(expense_id, number: "N20240201")
399
+ ```
400
+
401
+ Delete an expense:
402
+
403
+ ```ruby
404
+ response = client.expenses.delete(expense_id)
405
+ ```
406
+
407
+ ### [Expense Payment Resource](https://www.fakturoid.cz/api/v3/expense-payments)
408
+
409
+ Create an expense payment:
410
+
411
+ ```ruby
412
+ response = client.expense_payments.create(expense_id, paid_on: Date.today)
413
+ response = client.expense_payments.create(expense_id, amount: "500")
414
+ ````
415
+
416
+ Delete a payment:
417
+
418
+ ```ruby
419
+ response = client.expense_payments.delete(expense_id, payment_id)
420
+ ```
421
+
422
+ ### [Inbox File Resource](https://www.fakturoid.cz/api/v3/inbox-files)
423
+
424
+ Get a list of inbox files:
425
+
426
+ ```ruby
427
+ response = client.inbox_files.all
428
+ ```
429
+
430
+ Create an inbox file:
431
+
432
+ ```ruby
433
+ require "base64"
434
+
435
+ client.inbox_files.create(
436
+ attachment: "data:application/pdf;base64,#{Base64.urlsafe_encode64(File.read("some-file.pdf"))}",
437
+ filename: "some-file.pdf", # This is optional and defaults to `attachment.{extension}`.
438
+ send_to_ocr: true # Also optional
439
+ )
194
440
  ```
195
441
 
196
- To update invoice use following code:
442
+ Send a file to OCR (data extraction service):
197
443
 
198
444
  ```ruby
199
- response = Fakturoid::Client::Invoice.update(invoice_id, number: "2015-0015")
445
+ client.inbox_files.send_to_ocr(inbox_file_id)
200
446
  ```
201
447
 
202
- Delete invoice:
448
+ Download a file:
203
449
 
204
450
  ```ruby
205
- response = Fakturoid::Client::Invoice.delete(invoice_id)
451
+ filename = client.inbox_files.find(inbox_file_id).filename
452
+ response = client.inbox_files.download(inbox_file_id)
453
+
454
+ File.open("/path/to/file.pdf", "wb") do |f|
455
+ f.write(response.body)
456
+ end
206
457
  ```
207
458
 
208
- For the list of all invoice fields and options see the [Invoices API documentation](https://fakturoid.docs.apiary.io/#reference/invoices)
459
+ Delete a file:
460
+
461
+ ```ruby
462
+ response = client.inbox_files.delete(inbox_file_id)
463
+ ```
209
464
 
210
- ### InventoryItem resource
465
+ ### [InventoryItem Resource](https://www.fakturoid.cz/api/v3/inventory-items)
211
466
 
212
- To get all inventory items:
467
+ Get a list of inventory items:
213
468
 
214
469
  ```ruby
215
- response = Fakturoid::Client::InventoryItems.all
470
+ response = client.inventory_items.all
471
+ response = client.inventory_items.all(sku: "SKU1234") # Filter by SKU code
216
472
  ```
217
473
 
218
- To filter inventory items by certain SKU code:
474
+ Get a list of archived inventory items:
219
475
 
220
476
  ```ruby
221
- response = Fakturoid::Client::InventoryItems.all(sku: 'SKU1234')
477
+ response = client.inventory_items.archived
222
478
  ```
223
479
 
224
- To search inventory items (searches in `name`, `article_number` and `sku`):
480
+ Get a list of inventory items that are running low on quantity:
225
481
 
226
482
  ```ruby
227
- response = Fakturoid::Client::InventoryItems.search('Item name')
483
+ response = client.inventory_items.low_quantity
228
484
  ```
229
485
 
230
- To get all archived inventory items:
486
+ Search inventory items (searches in `name`, `article_number` and `sku`):
231
487
 
232
488
  ```ruby
233
- response = Fakturoid::Client::InventoryItems.archived
489
+ response = client.inventory_items.search(query: "Item name")
234
490
  ```
235
491
 
236
- To get a single inventory item:
492
+ Get a single inventory item:
237
493
 
238
494
  ```ruby
239
- response = Fakturoid::Client::InventoryItems.find(inventory_item_id)
495
+ response = client.inventory_items.find(inventory_item_id)
240
496
  ```
241
497
 
242
- To create an inventory item:
498
+ Create an inventory item:
243
499
 
244
500
  ```ruby
245
- inventory_item = {
501
+ data = {
246
502
  name: "Item name",
247
503
  sku: "SKU1234",
248
504
  track_quantity: true,
@@ -250,57 +506,57 @@ inventory_item = {
250
506
  native_purchase_price: 500,
251
507
  native_retail_price: 1000
252
508
  }
253
- response = Fakturoid::Client::InventoryItems.create(inventory_item)
509
+ response = client.inventory_items.create(data)
254
510
  ```
255
511
 
256
- To update an inventory item:
512
+ Update an inventory item:
257
513
 
258
514
  ```ruby
259
- response = Fakturoid::Client::InventoryItems.update(inventory_item_id, name: "Another name")
515
+ response = client.inventory_items.update(inventory_item_id, name: "Another name")
260
516
  ```
261
517
 
262
- To archive an inventory item:
518
+ Delete an inventory item:
263
519
 
264
520
  ```ruby
265
- response = Fakturoid::Client::InventoryItems.archive(inventory_item_id)
521
+ response = client.inventory_items.delete(inventory_item_id)
266
522
  ```
267
523
 
268
- To unarchive an inventory item:
524
+ Archive an inventory item:
269
525
 
270
526
  ```ruby
271
- response = Fakturoid::Client::InventoryItems.unarchive(inventory_item_id)
527
+ response = client.inventory_items.archive(inventory_item_id)
272
528
  ```
273
529
 
274
- To delete an inventory item:
530
+ Unarchive an inventory item:
275
531
 
276
532
  ```ruby
277
- response = Fakturoid::Client::InventoryItems.delete(inventory_item_id)
533
+ response = client.inventory_items.unarchive(inventory_item_id)
278
534
  ```
279
535
 
280
- ### InventoryMove resource
536
+ ### [InventoryMove Resource](https://www.fakturoid.cz/api/v3/inventory-moves)
281
537
 
282
- To get get all inventory moves across all inventory items:
538
+ Get a list of inventory moves across all inventory items:
283
539
 
284
540
  ```ruby
285
- response = Fakturoid::Client::InventoryMoves.all
541
+ response = client.inventory_moves.all
286
542
  ```
287
543
 
288
- To get inventory moves for a single inventory item:
544
+ Get a list of inventory moves for a single inventory item:
289
545
 
290
546
  ```ruby
291
- response = Fakturoid::Client::InventoryMoves.all(inventory_item_id: inventory_item_id)
547
+ response = client.inventory_moves.all(inventory_item_id: inventory_item_id)
292
548
  ```
293
549
 
294
- To get a single inventory move:
550
+ Get a single inventory move:
295
551
 
296
552
  ```ruby
297
- response = Fakturoid::Client::InventoryMoves.find(inventory_item_id, inventory_move_id)
553
+ response = client.inventory_moves.find(inventory_item_id, inventory_move_id)
298
554
  ```
299
555
 
300
- To create a stock-in inventory move:
556
+ Create a stock-in inventory move:
301
557
 
302
558
  ```ruby
303
- response = Fakturoid::Client::InventoryMoves.create(
559
+ response = client.inventory_moves.create(
304
560
  inventory_item_id,
305
561
  direction: "in",
306
562
  moved_on: Date.today,
@@ -311,10 +567,10 @@ response = Fakturoid::Client::InventoryMoves.create(
311
567
  )
312
568
  ```
313
569
 
314
- To create a stock-out inventory move:
570
+ Create a stock-out inventory move:
315
571
 
316
572
  ```ruby
317
- response = Fakturoid::Client::InventoryMoves.create(
573
+ response = client.inventory_moves.create(
318
574
  inventory_item_id,
319
575
  direction: "out",
320
576
  moved_on: Date.today,
@@ -325,29 +581,149 @@ response = Fakturoid::Client::InventoryMoves.create(
325
581
  )
326
582
  ```
327
583
 
328
- To update an inventory move:
584
+ Update an inventory move:
329
585
 
330
586
  ```ruby
331
- inventory_move = {
587
+ data = {
332
588
  private_note: "Text"
333
589
  # Plus other fields if necessary
334
590
  }
335
- response = Fakturoid::Client::InventoryMoves.update(inventory_item_id, inventory_move_id, inventory_move)
591
+ response = client.inventory_moves.update(inventory_item_id, inventory_move_id, data)
592
+ ```
593
+
594
+ Delete an inventory move:
595
+
596
+ ```ruby
597
+ response = client.inventory_moves.delete(inventory_item_id, inventory_move_id)
336
598
  ```
337
599
 
338
- To delete an inventory move:
600
+ ### [Generator Resource](https://www.fakturoid.cz/api/v3/generators)
601
+
602
+ Get a list of generators:
339
603
 
340
604
  ```ruby
341
- response = Fakturoid::Client::InventoryMoves.delete(inventory_item_id, inventory_move_id)
605
+ response = client.generators.all
342
606
  ```
343
607
 
344
- ## Handling error responses
608
+ Get generator details:
345
609
 
346
- The Fakturoid gem raises exceptions if error response is returned from the servers. All exceptions contains following attributes:
610
+ ```ruby
611
+ response = client.generators.find(generator_id)
612
+ ```
347
613
 
348
- - `message` - Error description
349
- - `response_code` - http code of error (only number)
350
- - `response_body` - response body parsed in the hash
614
+ Create a generator:
615
+
616
+ ```ruby
617
+ data = {
618
+ name: "Workshop",
619
+ subject_id: 123,
620
+ lines: [
621
+ {
622
+ quantity: 5,
623
+ unit_name: "kg",
624
+ name: "Sand",
625
+ unit_price: "100",
626
+ vat_rate: 21
627
+ }
628
+ ]
629
+ }
630
+ response = client.generators.create(data)
631
+ ```
632
+
633
+ Update an generator:
634
+
635
+ ```ruby
636
+ response = client.generators.update(generator_id, name: "Another name")
637
+ ```
638
+
639
+ Delete an generator:
640
+
641
+ ```ruby
642
+ response = client.generators.delete(generator_id)
643
+ ```
644
+
645
+ ### [RecurringGenerator Resource](https://www.fakturoid.cz/api/v3/recurring-generators)
646
+
647
+ Get a list of recurring generators:
648
+
649
+ ```ruby
650
+ response = client.recurring_generators.all
651
+ ```
652
+
653
+ Get recurring generator details:
654
+
655
+ ```ruby
656
+ response = client.recurring_generators.find(recurring_generator_id)
657
+ ```
658
+
659
+ Create a recurring generator:
660
+
661
+ ```ruby
662
+ data = {
663
+ name: "Workshop",
664
+ subject_id: subject_id,
665
+ start_date: Date.today,
666
+ months_period: 1,
667
+ lines: [
668
+ {
669
+ quantity: 5,
670
+ unit_name: "kg",
671
+ name: "Sand",
672
+ unit_price: "100",
673
+ vat_rate: 21
674
+ }
675
+ ]
676
+ }
677
+ response = client.recurring_generators.create(data)
678
+ ```
679
+
680
+ Update a recurring generator:
681
+
682
+ ```ruby
683
+ response = client.recurring_generators.update(recurring_generator_id, name: "Another name")
684
+ ```
685
+
686
+ Delete a recurring generator:
687
+
688
+ ```ruby
689
+ response = client.recurring_generators.delete(recurring_generator_id)
690
+ ```
691
+ ### [Event Resource](https://www.fakturoid.cz/api/v3/events)
692
+
693
+ Get a list of all events:
694
+
695
+ ```ruby
696
+ response = client.events.all
697
+ ````
698
+
699
+ Get a list of document-paid events:
700
+
701
+ ```ruby
702
+ response = client.events.paid
703
+ ````
704
+
705
+ ### [Todo Resource](https://www.fakturoid.cz/api/v3/todos)
706
+
707
+ Get a list of all todos:
708
+
709
+ ```ruby
710
+ response = client.todos.all
711
+ ````
712
+
713
+ Toggle a todo completion:
714
+
715
+ ```ruby
716
+ response = client.todos.toggle_completion(todo_id)
717
+ ```
718
+
719
+ ## Handling Errors
720
+
721
+ The Fakturoid gem raises exceptions if server responds with an error.
722
+ All exceptions except `ConfigurationError` contain following attributes:
723
+
724
+ - `message`: Error description
725
+ - `response_code`: HTTP code of error (only number)
726
+ - `response_body`: Response body parsed as a hash
351
727
 
352
728
  <table>
353
729
  <thead>
@@ -357,49 +733,29 @@ The Fakturoid gem raises exceptions if error response is returned from the serve
357
733
  </thead>
358
734
  <tbody>
359
735
  <tr>
360
- <td>ContentTypeError</td><td>415 Unsupported Media Type</td><td>Wrong content type</td>
361
- </tr>
362
- <tr>
363
- <td>UserAgentError</td><td>400 Bad Request</td><td>Missing `user_agent` configuration</td>
364
- </tr>
365
- <tr>
366
- <td>PaginationError</td><td>400 Bad Request</td><td>Page with given number does not exist</td>
367
- </tr>
368
- <tr>
369
- <td>AuthenticationError</td><td>401 Unauthorized</td><td>Wrong authentication `email` or `api_key` configuration</td>
370
- </tr>
371
- <tr>
372
- <td>BlockedAccountError</td><td>402 Payment Required</td><td>Fakturoid account is blocked</td>
736
+ <td>ConfigurationError</td><td>N/A</td><td>Important configuration is missing.</td>
373
737
  </tr>
374
738
  <tr>
375
- <td>RateLimitError</td><td>429 Too Many Requests</td><td>Too many request sent during last 5 minutes</td>
739
+ <td>OauthError</td><td>400 Bad Request</td><td>OAuth request fails.</td>
376
740
  </tr>
377
741
  <tr>
378
- <td>ReadOnlySiteError</td><td>503 Service Unavailable</td><td>Fakturoid is read only</td>
742
+ <td>AuthenticationError</td><td>401 Unauthorized</td><td>Authentication fails due to client credentials error or access token expired.</td>
379
743
  </tr>
380
744
  <tr>
381
- <td>RecordNotFoundError</td><td>404 Not Found</td><td>Document with given ID does not exists or current account has read only permission and trying to edit something</td>
745
+ <td>ClientError</td><td>4XX</td><td>User-sent data are invalid.</td>
382
746
  </tr>
383
747
  <tr>
384
- <td>InvalidRecordError</td><td>422 Unprocessable Entity</td><td>Invalid data sent to server</td>
385
- </tr>
386
- <tr>
387
- <td>DestroySubjectError</td><td>403 Forbidden</td><td>Subject has invoices or expenses and cannot be deleted</td>
388
- </tr>
389
- <tr>
390
- <td>SubjectLimitError</td><td>403 Forbidden</td><td>Subject quota reached for adding more subjects upgrade to higher plan</td>
391
- </tr>
392
- <tr>
393
- <td>GeneratorLimitError</td><td>403 Forbidden</td><td>Generator quota reached for adding more recurring generators upgrade to higher plan</td>
394
- </tr>
395
- <tr>
396
- <td>UnsupportedFeatureError</td><td>403 Forbidden</td><td>Feature is not supported in your plan to use this feature upgrade to higher plan</td>
397
- </tr>
398
- <tr>
399
- <td>ClientError</td><td>4XX</td><td>Server returns response code which is not specified above</td>
400
- </tr>
401
- <tr>
402
- <td>ServerError</td><td>5XX</td><td>Server returns response code which is not specified above</td>
748
+ <td>ServerError</td><td>5XX</td><td>An exception happened while processing a request.</td>
403
749
  </tr>
404
750
  </tbody>
405
751
  </table>
752
+
753
+ ## Development
754
+
755
+ ```sh
756
+ git clone <repo-url>
757
+ cd fakturoid-ruby
758
+ bundle
759
+ bundle exec rake # Run tests
760
+ bundle exec rake build # Test the package building process
761
+ ```