loyverse_api 0.1.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8617a119e948c3c8d187b2046710f71dd442eed9bbde9772cf8f21bdb00c6b3b
4
- data.tar.gz: 503a06d272a520ff26e4cc37526f23dacd10df170a9b536e599b83f56f9f20d5
3
+ metadata.gz: 3dea99a28debaaafb892b7a49c1dd892dfa5d517e0c8282999353b0fc036c9cb
4
+ data.tar.gz: c87af19df702a36ce73e5741ec6f3e2ba8d4dcf7ef967b49f460e42f8098c8e4
5
5
  SHA512:
6
- metadata.gz: fa8bda79302447775991c4e267882f59c8e61bc4eed36aa1fa6f925f870de05f0f303b02bd309688a7715e5308c3c3ae90893f88fb338c13e836ba1a8e693b44
7
- data.tar.gz: 4518e72787d2aa4ac351a2739568d1ddab7d80f076e204b646216a0dac342835242b6b97f55a0d6c3b31d9dc5daf1b0731e8aca0d16d8bf96e59931894805425
6
+ metadata.gz: 7b33e3f022d0591c8416dd693484b30228eb22c024c64742b7c5f0570b500f2cfc224257bac2fa61a17a9f346033e007aa5757745b29f7a32d9aa3fe2d199987
7
+ data.tar.gz: 694975bdc4671d51b57880acc766fefa32e4a7afb69527815a67bb03cb4dabd04c5dfbaaafbac5a994fbb738a5ad962df56292effee354c3d54fa6e4b7d56a9d
data/CHANGELOG.md CHANGED
@@ -1,6 +1,14 @@
1
1
  # Changelog
2
2
 
3
- ## [0.1.0] - 2026-01-26
3
+ ## [0.2.0] - 2026-02-16
4
+
5
+ ### Fixed
6
+ - Receipts resource
7
+
8
+ ### Changed
9
+ - Simplified response handling to let the user customize it
10
+
11
+ ## [0.1.0] - 2026-02-16
4
12
 
5
13
  ### Added
6
14
  - Initial release of the Loyverse API Ruby gem
data/README.md CHANGED
@@ -338,55 +338,8 @@ client.delete_modifier('modifier-uuid')
338
338
 
339
339
  ### Webhooks
340
340
 
341
- Webhooks allow you to receive real-time notifications when events occur in your Loyverse account.
342
-
343
- **Setting up a webhook:**
344
-
345
- 1. **Create the webhook** pointing to your server endpoint:
346
- ```ruby
347
- webhook = client.create_webhook(
348
- url: 'https://your-server.com/webhooks/loyverse',
349
- event_types: ['ORDER_CREATED', 'ITEM_UPDATED', 'INVENTORY_UPDATED'],
350
- description: 'Production webhook'
351
- )
352
- ```
353
-
354
- 2. **Handle webhook requests** in your application (Rails example):
355
- ```ruby
356
- # POST /webhooks/loyverse
357
- def create
358
- payload = request.raw_post
359
- signature = request.headers['X-Loyverse-Signature']
360
-
361
- # Verify signature
362
- unless client.verify_webhook_signature(payload, signature, ENV['LOYVERSE_WEBHOOK_SECRET'])
363
- return head :unauthorized
364
- end
365
-
366
- # Process the webhook
367
- data = JSON.parse(payload)
368
- case data['event_type']
369
- when 'ORDER_CREATED'
370
- # Handle new order
371
- when 'ITEM_UPDATED'
372
- # Handle item update
373
- when 'INVENTORY_UPDATED'
374
- # Handle inventory update
375
- end
376
-
377
- head :ok
378
- end
379
- ```
380
-
381
- **Available event types:**
382
- - `ORDER_CREATED` - New receipts/sales
383
- - `ITEM_UPDATED` - Product changes
384
- - `INVENTORY_UPDATED` - Stock level changes
385
-
386
- 📖 **Full webhook documentation:** [Loyverse Webhooks Overview](https://developer.loyverse.com/docs/#section/Webhooks-overview/Adding-webhook)
387
-
388
341
  <details>
389
- <summary>Click to see more webhook management examples</summary>
342
+ <summary>Click to see Webhooks examples</summary>
390
343
 
391
344
  ```ruby
392
345
  # List webhooks
@@ -395,8 +348,22 @@ webhooks = client.list_webhooks
395
348
  # Get a specific webhook
396
349
  webhook = client.get_webhook('webhook-uuid')
397
350
 
351
+ # Create a webhook
352
+ new_webhook = client.create_webhook(
353
+ url: 'https://your-server.com/webhooks/loyverse',
354
+ event_types: ['ORDER_CREATED', 'ITEM_UPDATED'],
355
+ description: 'Production webhook'
356
+ )
357
+
398
358
  # Delete a webhook
399
359
  client.delete_webhook('webhook-uuid')
360
+
361
+ # Verify webhook signature
362
+ is_valid = client.verify_webhook_signature(
363
+ request.raw_post,
364
+ request.headers['X-Loyverse-Signature'],
365
+ 'your_webhook_secret'
366
+ )
400
367
  ```
401
368
 
402
369
  </details>
@@ -0,0 +1,111 @@
1
+ # Loyverse API Examples
2
+
3
+ This directory contains example code and sample API responses for the Loyverse API Ruby gem.
4
+
5
+ ## Sample API Responses
6
+
7
+ ### Receipts
8
+
9
+ See [`receipt_response_sample.json`](receipt_response_sample.json) for a complete example of a receipt object returned by the Loyverse API.
10
+
11
+ This sample demonstrates:
12
+ - **Receipt metadata**: receipt number, type, dates, source
13
+ - **Financial data**: totals, taxes, discounts, tips
14
+ - **Line items**: products with quantities, prices, costs
15
+ - **Modifiers**: customizations applied to items (e.g., milk type, flavor syrups, extra shots)
16
+ - **Payments**: payment methods and amounts
17
+ - **Pagination**: cursor for fetching additional results
18
+
19
+ #### Key Fields
20
+
21
+ **Receipt Level:**
22
+ - `receipt_number`: Unique receipt identifier (e.g., "1-10131")
23
+ - `receipt_type`: Type of transaction ("SALE", "REFUND", etc.)
24
+ - `total_money`: Total amount including tax
25
+ - `total_tax`: Total tax amount
26
+ - `employee_id`: ID of the employee who processed the sale
27
+ - `store_id`: ID of the store where the sale occurred
28
+ - `dining_option`: Customer's dining preference
29
+
30
+ **Line Items:**
31
+ - `item_name`: Product name
32
+ - `sku`: Stock keeping unit
33
+ - `quantity`: Number of items sold
34
+ - `price`: Base price per item
35
+ - `total_money`: Total for this line item including modifiers
36
+ - `cost`: Cost of goods sold
37
+ - `line_modifiers`: Array of customizations applied
38
+
39
+ **Modifiers:**
40
+ - `name`: Modifier category (e.g., "Flavor Syrup", "Espresso Shot")
41
+ - `option`: Selected option (e.g., "Chocolate", "Double Shot Extra")
42
+ - `price`: Additional charge for the modifier
43
+ - `money_amount`: Total amount for this modifier
44
+
45
+ **Payments:**
46
+ - `type`: Payment method ("CASH", "CARD", etc.)
47
+ - `money_amount`: Amount paid
48
+ - `paid_at`: Timestamp of payment
49
+
50
+ ## Usage Examples
51
+
52
+ ### Fetching Receipts
53
+
54
+ ```ruby
55
+ require 'loyverse_api'
56
+
57
+ # Configure the client
58
+ LoyverseApi.configure do |config|
59
+ config.access_token = ENV['LOYVERSE_ACCESS_TOKEN']
60
+ end
61
+
62
+ client = LoyverseApi.client
63
+
64
+ # List recent receipts
65
+ receipts = client.list_receipts(limit: 100)
66
+
67
+ # List receipts in a date range
68
+ receipts = client.list_receipts(
69
+ limit: 100,
70
+ created_at_min: '2025-07-01T00:00:00.000Z',
71
+ created_at_max: '2025-07-31T23:59:59.999Z'
72
+ )
73
+
74
+ # List receipts between specific receipt numbers
75
+ receipts = client.list_receipts(
76
+ limit: 250,
77
+ since_receipt_number: '1-10129',
78
+ before_receipt_number: '1-10132'
79
+ )
80
+
81
+ # Paginate through results
82
+ page1 = client.list_receipts(limit: 100)
83
+ page2 = client.list_receipts(limit: 100, cursor: page1['cursor'])
84
+ ```
85
+
86
+ ### Processing Receipt Data
87
+
88
+ ```ruby
89
+ receipts['receipts'].each do |receipt|
90
+ puts "Receipt: #{receipt['receipt_number']}"
91
+ puts "Total: $#{receipt['total_money']}"
92
+ puts "Date: #{receipt['receipt_date']}"
93
+
94
+ # Process line items
95
+ receipt['line_items'].each do |item|
96
+ puts " - #{item['item_name']}: #{item['quantity']} x $#{item['price']}"
97
+
98
+ # Process modifiers
99
+ item['line_modifiers']&.each do |modifier|
100
+ puts " + #{modifier['name']}: #{modifier['option']} (+$#{modifier['price']})"
101
+ end
102
+ end
103
+
104
+ puts "---"
105
+ end
106
+ ```
107
+
108
+ ## Additional Resources
109
+
110
+ - [Loyverse API Documentation](https://developer.loyverse.com/docs/)
111
+ - [Main README](../README.md)
@@ -0,0 +1,236 @@
1
+ {
2
+ "receipts": [
3
+ {
4
+ "receipt_number": "1-10131",
5
+ "note": null,
6
+ "receipt_type": "SALE",
7
+ "refund_for": null,
8
+ "order": null,
9
+ "created_at": "2025-07-19T07:00:02.000Z",
10
+ "updated_at": "2025-07-19T07:00:02.000Z",
11
+ "source": "point of sale",
12
+ "receipt_date": "2025-07-19T06:57:31.000Z",
13
+ "cancelled_at": null,
14
+ "total_money": 335.00,
15
+ "total_tax": 46.21,
16
+ "points_earned": 0.00,
17
+ "points_deducted": 0.00,
18
+ "points_balance": 0.00,
19
+ "customer_id": null,
20
+ "total_discount": 0.00,
21
+ "employee_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
22
+ "store_id": "f1e2d3c4-b5a6-4978-8c9d-0e1f2a3b4c5d",
23
+ "pos_device_id": "d1c2b3a4-e5f6-4978-8c9d-0e1f2a3b4c5d",
24
+ "dining_option": "Dine In",
25
+ "total_discounts": [],
26
+ "total_taxes": [
27
+ {
28
+ "id": "c2afb81c-d75f-4f70-8acc-dd0112b37aae",
29
+ "type": "INCLUDED",
30
+ "name": "VAT",
31
+ "rate": 16.0,
32
+ "money_amount": 46.21
33
+ }
34
+ ],
35
+ "tip": 0.00,
36
+ "surcharge": 0.00,
37
+ "line_items": [
38
+ {
39
+ "id": "9553152a-9d9d-f0cd-f6a3-2ab6fcbd516c",
40
+ "item_id": "edb828f0-23a8-4755-a171-b6b8c7d13808",
41
+ "variant_id": "96ceec2c-5f58-4170-84fd-96c84fb6482c",
42
+ "item_name": "Coffee Americano",
43
+ "variant_name": null,
44
+ "sku": "10006",
45
+ "quantity": 1,
46
+ "price": 50.00,
47
+ "gross_total_money": 95.00,
48
+ "total_money": 95.00,
49
+ "cost": 13.05,
50
+ "cost_total": 13.05,
51
+ "line_note": null,
52
+ "line_taxes": [
53
+ {
54
+ "money_amount": 13.10,
55
+ "id": "c2afb81c-d75f-4f70-8acc-dd0112b37aae",
56
+ "type": "INCLUDED",
57
+ "name": "VAT",
58
+ "rate": 16.0
59
+ }
60
+ ],
61
+ "total_discount": 0.00,
62
+ "line_discounts": [],
63
+ "line_modifiers": [
64
+ {
65
+ "id": "22c541f2-f224-4f26-bdbe-0eecdd77aa6c",
66
+ "modifier_option_id": "fc5ed733-1756-48c3-b7c1-529288e869af",
67
+ "name": "Flavor Syrup",
68
+ "option": "Chocolate",
69
+ "price": 15.00,
70
+ "money_amount": 15.00
71
+ },
72
+ {
73
+ "id": "01e734f1-9348-46b6-a3ba-d841f2042fe9",
74
+ "modifier_option_id": "571d5613-d909-427e-954e-f3b9e7227101",
75
+ "name": "Espresso Shot",
76
+ "option": "Double Shot Extra",
77
+ "price": 15.00,
78
+ "money_amount": 15.00
79
+ },
80
+ {
81
+ "id": "d0346233-92ec-4c58-9455-cd6c55d124f7",
82
+ "modifier_option_id": "f044d08d-f5c7-4a5c-adf8-cfdd8bf4edfc",
83
+ "name": "With Milk",
84
+ "option": "Light",
85
+ "price": 15.00,
86
+ "money_amount": 15.00
87
+ }
88
+ ]
89
+ },
90
+ {
91
+ "id": "9553152a-9d9d-f0cd-f6a3-2ab6fcbd516d",
92
+ "item_id": "016e03e8-ec36-4ec2-81be-dfcf30820fd2",
93
+ "variant_id": "4267d877-ba3c-44af-ac3a-0d15692a9e16",
94
+ "item_name": "Espresso",
95
+ "variant_name": null,
96
+ "sku": "10009",
97
+ "quantity": 1,
98
+ "price": 40.00,
99
+ "gross_total_money": 55.00,
100
+ "total_money": 55.00,
101
+ "cost": 9.73,
102
+ "cost_total": 9.73,
103
+ "line_note": null,
104
+ "line_taxes": [
105
+ {
106
+ "money_amount": 7.59,
107
+ "id": "c2afb81c-d75f-4f70-8acc-dd0112b37aae",
108
+ "type": "INCLUDED",
109
+ "name": "VAT",
110
+ "rate": 16.0
111
+ }
112
+ ],
113
+ "total_discount": 0.00,
114
+ "line_discounts": [],
115
+ "line_modifiers": [
116
+ {
117
+ "id": "01e734f1-9348-46b6-a3ba-d841f2042fe9",
118
+ "modifier_option_id": "571d5613-d909-427e-954e-f3b9e7227101",
119
+ "name": "Espresso Shot",
120
+ "option": "Double Shot Extra",
121
+ "price": 15.00,
122
+ "money_amount": 15.00
123
+ }
124
+ ]
125
+ },
126
+ {
127
+ "id": "9553152a-9d9d-f0cd-f6a3-2ab6fcbd516e",
128
+ "item_id": "3282814e-0638-49dd-9566-7f7a485e38fc",
129
+ "variant_id": "7966819c-f78b-4b81-909f-f9af478cee42",
130
+ "item_name": "Flat White",
131
+ "variant_name": null,
132
+ "sku": "10004",
133
+ "quantity": 1,
134
+ "price": 60.00,
135
+ "gross_total_money": 90.00,
136
+ "total_money": 90.00,
137
+ "cost": 17.28,
138
+ "cost_total": 17.28,
139
+ "line_note": null,
140
+ "line_taxes": [
141
+ {
142
+ "money_amount": 12.41,
143
+ "id": "c2afb81c-d75f-4f70-8acc-dd0112b37aae",
144
+ "type": "INCLUDED",
145
+ "name": "VAT",
146
+ "rate": 16.0
147
+ }
148
+ ],
149
+ "total_discount": 0.00,
150
+ "line_discounts": [],
151
+ "line_modifiers": [
152
+ {
153
+ "id": "69b59738-4e7f-447d-ab1c-74aa5b67b7b1",
154
+ "modifier_option_id": "6d64fb54-f667-452e-bfce-c43bebdfcc9e",
155
+ "name": "Oat Milk",
156
+ "option": "Barista Oat",
157
+ "price": 15.00,
158
+ "money_amount": 15.00
159
+ },
160
+ {
161
+ "id": "01e734f1-9348-46b6-a3ba-d841f2042fe9",
162
+ "modifier_option_id": "571d5613-d909-427e-954e-f3b9e7227101",
163
+ "name": "Espresso Shot",
164
+ "option": "Double Shot Extra",
165
+ "price": 15.00,
166
+ "money_amount": 15.00
167
+ }
168
+ ]
169
+ },
170
+ {
171
+ "id": "9553152a-9d9d-f0cd-f6a3-2ab6fcbd516f",
172
+ "item_id": "b8afa0b1-0851-4225-91e2-53c670d41374",
173
+ "variant_id": "2caa728f-0024-4f29-ae7a-d53420c4ef4d",
174
+ "item_name": "Latte",
175
+ "variant_name": null,
176
+ "sku": "10000",
177
+ "quantity": 1,
178
+ "price": 65.00,
179
+ "gross_total_money": 95.00,
180
+ "total_money": 95.00,
181
+ "cost": 23.36,
182
+ "cost_total": 23.36,
183
+ "line_note": null,
184
+ "line_taxes": [
185
+ {
186
+ "money_amount": 13.11,
187
+ "id": "c2afb81c-d75f-4f70-8acc-dd0112b37aae",
188
+ "type": "INCLUDED",
189
+ "name": "VAT",
190
+ "rate": 16.0
191
+ }
192
+ ],
193
+ "total_discount": 0.00,
194
+ "line_discounts": [],
195
+ "line_modifiers": [
196
+ {
197
+ "id": "0c75ed60-8713-413e-bd4d-8cbc2aed78ca",
198
+ "modifier_option_id": "3690e2a3-6062-4cb9-bdf6-ca58aa856c21",
199
+ "name": "Milk Type (Included)",
200
+ "option": "Lactose-Free",
201
+ "price": 0.00,
202
+ "money_amount": 0.00
203
+ },
204
+ {
205
+ "id": "22c541f2-f224-4f26-bdbe-0eecdd77aa6c",
206
+ "modifier_option_id": "a60ad701-ddbe-49da-9fee-fa3d59da4e3b",
207
+ "name": "Flavor Syrup",
208
+ "option": "Marzipan",
209
+ "price": 15.00,
210
+ "money_amount": 15.00
211
+ },
212
+ {
213
+ "id": "01e734f1-9348-46b6-a3ba-d841f2042fe9",
214
+ "modifier_option_id": "571d5613-d909-427e-954e-f3b9e7227101",
215
+ "name": "Espresso Shot",
216
+ "option": "Double Shot Extra",
217
+ "price": 15.00,
218
+ "money_amount": 15.00
219
+ }
220
+ ]
221
+ }
222
+ ],
223
+ "payments": [
224
+ {
225
+ "payment_type_id": "a9dd8a31-1ff2-4418-b538-8f66cd5a5878",
226
+ "name": "Cash",
227
+ "type": "CASH",
228
+ "money_amount": 335.00,
229
+ "paid_at": "2025-07-19T06:57:31.000Z",
230
+ "payment_details": null
231
+ }
232
+ ]
233
+ }
234
+ ],
235
+ "cursor": "CPnzvouCMxDn3P-LgjNCA-H8ekjn4sjhG2ABcAc="
236
+ }
@@ -42,113 +42,56 @@ module LoyverseApi
42
42
  end
43
43
 
44
44
  def get(path, params: {})
45
- handle_response do
46
45
  response = connection.get(path, params)
47
46
  response
48
- end
49
47
  end
50
48
 
51
49
  def post(path, body: {})
52
- handle_response do
53
50
  response = connection.post(path, body)
54
51
  response
55
- end
56
52
  end
57
53
 
58
54
  def put(path, body: {})
59
- handle_response do
60
55
  response = connection.put(path, body)
61
56
  response
62
- end
63
57
  end
64
58
 
65
59
  def delete(path)
66
- handle_response do
67
60
  response = connection.delete(path)
68
61
  response
69
- end
70
62
  end
71
63
 
72
64
  private
73
65
 
74
- def handle_response
75
- response = yield
76
-
77
- case response.status
78
- when 200, 201, 204
79
- response.body
80
- when 400
81
- raise BadRequestError.new(
82
- error_message(response) || "Bad Request: #{response.body.inspect}",
83
- code: error_code(response),
84
- details: error_details(response)
85
- )
86
- when 401
87
- raise AuthenticationError.new(
88
- error_message(response),
89
- code: error_code(response),
90
- details: error_details(response)
91
- )
92
- when 403
93
- raise AuthorizationError.new(
94
- error_message(response),
95
- code: error_code(response),
96
- details: error_details(response)
97
- )
98
- when 404
99
- raise NotFoundError.new(
100
- error_message(response),
101
- code: error_code(response),
102
- details: error_details(response)
103
- )
104
- when 429
105
- raise RateLimitError.new(
106
- error_message(response) || "Rate limit exceeded",
107
- code: error_code(response),
108
- details: error_details(response)
109
- )
110
- when 500, 502, 503, 504
111
- raise ServerError.new(
112
- error_message(response) || "Server error occurred",
113
- code: error_code(response),
114
- details: error_details(response)
115
- )
116
- else
117
- raise ApiError.new(
118
- error_message(response) || "Unknown error occurred",
119
- code: error_code(response),
120
- details: error_details(response)
121
- )
122
- end
123
- rescue Faraday::TimeoutError
124
- raise Error, "Request timeout"
125
- rescue Faraday::ConnectionFailed
126
- raise Error, "Connection failed"
127
- end
128
-
129
- def error_message(response)
130
- return nil unless response.body.is_a?(Hash)
131
- response.body.dig("error", "message") || response.body["message"]
132
- end
133
-
134
- def error_code(response)
135
- return nil unless response.body.is_a?(Hash)
136
- response.body.dig("error", "code")
137
- end
138
-
139
- def error_details(response)
140
- return nil unless response.body.is_a?(Hash)
141
- response.body.dig("error", "details")
142
- end
143
-
66
+ # Formats time values to ISO 8601 format for Loyverse API
67
+ #
68
+ # The Loyverse API requires timestamps in ISO 8601 format (e.g., "2024-01-15T14:30:00.000Z")
69
+ # This method handles different input types and converts them appropriately:
70
+ #
71
+ # @param time [String, Time, Date, nil] The time value to format
72
+ # @return [String, nil] ISO 8601 formatted timestamp or nil
73
+ #
74
+ # @example String input (already formatted)
75
+ # format_time("2024-01-15T14:30:00.000Z") #=> "2024-01-15T14:30:00.000Z"
76
+ #
77
+ # @example Time object (with time component)
78
+ # format_time(Time.now) #=> "2024-01-15T14:30:00.123Z"
79
+ #
80
+ # @example Date object (no time component - sets to midnight UTC)
81
+ # format_time(Date.today) #=> "2024-01-15T00:00:00.000Z"
82
+ #
83
+ # @example Nil input
84
+ # format_time(nil) #=> nil
144
85
  def format_time(time)
145
86
  return nil if time.nil?
146
87
  return time if time.is_a?(String)
147
88
 
89
+ # Date objects don't have hour method, so set to midnight UTC
148
90
  if time.respond_to?(:strftime) && !time.respond_to?(:hour)
149
91
  return "#{time.strftime('%Y-%m-%d')}T00:00:00.000Z"
150
92
  end
151
93
 
94
+ # Time objects - convert to UTC and format with milliseconds
152
95
  return time.utc.strftime('%Y-%m-%dT%H:%M:%S.%LZ') if time.respond_to?(:utc)
153
96
 
154
97
  time
@@ -9,46 +9,32 @@ module LoyverseApi
9
9
  end
10
10
 
11
11
  # List receipts
12
- # @param receipt_numbers [Array<String, Integer>] Array of specific receipt numbers (optional)
13
- # @param since_receipt_number [String, Integer] Return receipts after this number (optional)
14
- # @param before_receipt_number [String, Integer] Return receipts before this number (optional)
15
- # @param store_id [String] Filter by store UUID (optional)
16
- # @param order [String] Sort order: "ASC" or "DESC" (default: "DESC")
17
- # @param source [String] Filter by source (e.g., "POS", "API") (optional)
18
- # @param updated_at_min [String, Time] Filter by minimum update time (optional)
19
- # @param updated_at_max [String, Time] Filter by maximum update time (optional)
20
- # @param created_at_min [String, Time] Filter by minimum creation time (optional)
21
- # @param created_at_max [String, Time] Filter by maximum creation time (optional)
22
12
  # @param limit [Integer] Maximum number of results per page (default: 250)
23
- # @param cursor [String] Pagination cursor for next page
13
+ # @param options [Hash] Optional filters
14
+ # @option options [Array<String, Integer>] :receipt_numbers Array of specific receipt numbers
15
+ # @option options [String, Integer] :since_receipt_number Return receipts after this number
16
+ # @option options [String, Integer] :before_receipt_number Return receipts before this number
17
+ # @option options [String] :store_id Filter by store UUID
18
+ # @option options [String] :source Filter by source (e.g., "POS", "API")
19
+ # @option options [String, Time] :updated_at_min Filter by minimum update time
20
+ # @option options [String, Time] :updated_at_max Filter by maximum update time
21
+ # @option options [String, Time] :created_at_min Filter by minimum creation time
22
+ # @option options [String, Time] :created_at_max Filter by maximum creation time
23
+ # @option options [String] :cursor Pagination cursor for next page
24
24
  # @return [Hash] Response with receipts array
25
- def list_receipts(
26
- receipt_numbers: nil,
27
- since_receipt_number: nil,
28
- before_receipt_number: nil,
29
- store_id: nil,
30
- order: "DESC",
31
- source: nil,
32
- updated_at_min: nil,
33
- updated_at_max: nil,
34
- created_at_min: nil,
35
- created_at_max: nil,
36
- limit: 250,
37
- cursor: nil
38
- )
25
+ def list_receipts(limit: 100, **options)
39
26
  params = {
40
27
  limit: limit,
41
- order: order,
42
- receipt_numbers: receipt_numbers ? Array(receipt_numbers).join(",") : nil,
43
- since_receipt_number: since_receipt_number,
44
- before_receipt_number: before_receipt_number,
45
- store_id: store_id,
46
- source: source,
47
- cursor: cursor,
48
- updated_at_min: format_time(updated_at_min),
49
- updated_at_max: format_time(updated_at_max),
50
- created_at_min: format_time(created_at_min),
51
- created_at_max: format_time(created_at_max)
28
+ receipt_numbers: options[:receipt_numbers] ? Array(options[:receipt_numbers]).join(",") : nil,
29
+ since_receipt_number: options[:since_receipt_number],
30
+ before_receipt_number: options[:before_receipt_number],
31
+ store_id: options[:store_id],
32
+ source: options[:source],
33
+ cursor: options[:cursor],
34
+ updated_at_min: format_time(options[:updated_at_min]),
35
+ updated_at_max: format_time(options[:updated_at_max]),
36
+ created_at_min: format_time(options[:created_at_min]),
37
+ created_at_max: format_time(options[:created_at_max])
52
38
  }.compact
53
39
 
54
40
  get("receipts", params: params)
@@ -1,3 +1,3 @@
1
1
  module LoyverseApi
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loyverse_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Loyverse API Wrapper
@@ -125,8 +125,10 @@ files:
125
125
  - LICENSE.txt
126
126
  - README.md
127
127
  - Rakefile
128
+ - examples/README.md
128
129
  - examples/basic_usage.rb
129
130
  - examples/create_item.rb
131
+ - examples/receipt_response_sample.json
130
132
  - examples/webhook_server.rb
131
133
  - lib/loyverse_api.rb
132
134
  - lib/loyverse_api/client.rb