conexa 0.0.9 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +49 -1
- data/Gemfile.lock +1 -1
- data/README.md +90 -73
- data/README_pt-BR.md +43 -19
- data/REFERENCE.md +33 -13
- data/lib/conexa/authenticator.rb +2 -0
- data/lib/conexa/configuration.rb +2 -0
- data/lib/conexa/core_ext.rb +11 -6
- data/lib/conexa/errors.rb +5 -3
- data/lib/conexa/model.rb +44 -28
- data/lib/conexa/object.rb +6 -16
- data/lib/conexa/{order_commom.rb → order_common.rb} +5 -5
- data/lib/conexa/request.rb +9 -8
- data/lib/conexa/resources/bill.rb +3 -1
- data/lib/conexa/resources/company.rb +2 -0
- data/lib/conexa/resources/credit_card.rb +2 -0
- data/lib/conexa/resources/customer.rb +21 -3
- data/lib/conexa/resources/invoicing_method.rb +2 -0
- data/lib/conexa/resources/legal_person.rb +2 -0
- data/lib/conexa/resources/pagination.rb +2 -0
- data/lib/conexa/resources/person.rb +2 -0
- data/lib/conexa/resources/plan.rb +2 -0
- data/lib/conexa/resources/product.rb +2 -0
- data/lib/conexa/resources/recurring_sale.rb +2 -0
- data/lib/conexa/resources/result.rb +32 -5
- data/lib/conexa/token_manager.rb +3 -1
- data/lib/conexa/util.rb +37 -50
- data/lib/conexa/version.rb +1 -1
- data/lib/conexa.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c71329999c6d13c4e935ef1e37a8eca6df5811c44d0326184cc1676d31fb199b
|
|
4
|
+
data.tar.gz: c6f6946375a05712ed7d952a4314738e86a2429bf3a249e269d2fd40b254c11f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 13fc7859937cd156cd8ae68b78d6c303b62460d4f6e682f270f58927e87c8a99e29e7d43a4814318b53ed5c5e20ce5e0ea3892d46db8d4d08147e9aea79a690e
|
|
7
|
+
data.tar.gz: c1ae89758b0cea23df6c5f5cc16895c060baef04da9a31fefd58eb7ac9c7ba1b1483dfc44b81c00ddfb592cada2e34cace170237e5f298b3ea8b3217572bd1c9
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,52 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.1.1] - 2026-03-31
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Instance methods `Customer#persons`, `Customer#contracts`, `Customer#charges` for idiomatic Ruby usage
|
|
14
|
+
- `customer = Conexa::Customer.find(127); customer.persons` — fetches persons for the loaded customer
|
|
15
|
+
- Class methods `Customer.persons(id)`, `Customer.contracts(id)`, `Customer.charges(id)` remain available
|
|
16
|
+
- Useful to save a request when you don't need the customer data itself
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
- Customer sub-resource methods now available in both class and instance forms
|
|
20
|
+
|
|
21
|
+
## [0.1.0] - 2026-03-31
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
- `Result#next_page` — automatically fetches the next page preserving original filter params
|
|
25
|
+
- `Result#has_next?` — convenience method to check if more pages are available
|
|
26
|
+
- Pagination migration guide added to README (EN/PT-BR) and REFERENCE.md
|
|
27
|
+
- Validation for `limit` (must be positive integer) and `offset` (must be non-negative integer) parameters
|
|
28
|
+
- `frozen_string_literal: true` pragma added to all Ruby source files
|
|
29
|
+
- ActiveSupport compatibility guard for `blank?`/`present?` monkey-patches
|
|
30
|
+
- `respond_to_missing?` implemented in `ConexaObject` and `Result` (Ruby best practice)
|
|
31
|
+
- Integration tests for all new API v2 resources (24 specs)
|
|
32
|
+
- Unit tests for pagination validation and `class_name` camelCase preservation (6 specs)
|
|
33
|
+
- Total: 502 specs
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
- **Breaking**: Default pagination is now `limit: 100, offset: 0` (was `page: 1, size: 100`)
|
|
37
|
+
- Calling `.all` or `.find_by` without pagination params now uses the new model
|
|
38
|
+
- Legacy `page`/`size` is only used when explicitly passed (emits deprecation warning)
|
|
39
|
+
- `Model.all` simplified — delegates directly to `find_by` without double param extraction
|
|
40
|
+
- `Model.class_name` now returns proper lowerCamelCase (e.g. `recurringSale` instead of `recurringsale`)
|
|
41
|
+
- `OrderCommom` renamed to `OrderCommon` (backwards-compatible alias kept)
|
|
42
|
+
- `Bill#save` now raises `NoMethodError` with descriptive message
|
|
43
|
+
- README updated: all examples now use correct method names (`.all`, `.find`, `.destroy`)
|
|
44
|
+
- README error handling section rewritten with actual exception classes
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
- **Concurrency bug**: `DEFAULT_HEADERS` constant was mutated on every request; now uses `.dup`
|
|
48
|
+
- **Boolean false bug**: `Result#method_missing` skipped `false` attribute values due to `||` operator
|
|
49
|
+
- **ValidationError crash**: undefined variable `error` in block scope — fixed to use `msg`
|
|
50
|
+
- **TokenManager typo**: `ShiConexa` → `Conexa` in credentials handling
|
|
51
|
+
- **Singularize**: `SINGULARS` patterns were stored as strings, never used as regex — rewritten with proper `Regexp` objects
|
|
52
|
+
- **Deep copy**: `Result#next_page` now uses `Marshal.load(Marshal.dump(...))` to prevent param mutation between pages
|
|
53
|
+
- Stray `-` character removed from `util.rb`
|
|
54
|
+
- Removed dead code: `Hash#except_nested` monkey-patch, commented-out `to_s` method
|
|
55
|
+
|
|
10
56
|
## [0.0.9] - 2026-03-30
|
|
11
57
|
|
|
12
58
|
### Added
|
|
@@ -87,7 +133,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
87
133
|
- Charge with settle and PIX methods
|
|
88
134
|
- Pagination support
|
|
89
135
|
|
|
90
|
-
[Unreleased]: https://github.com/guilhermegazzinelli/conexa-ruby/compare/v0.
|
|
136
|
+
[Unreleased]: https://github.com/guilhermegazzinelli/conexa-ruby/compare/v0.1.1...HEAD
|
|
137
|
+
[0.1.1]: https://github.com/guilhermegazzinelli/conexa-ruby/compare/v0.1.0...v0.1.1
|
|
138
|
+
[0.1.0]: https://github.com/guilhermegazzinelli/conexa-ruby/compare/v0.0.9...v0.1.0
|
|
91
139
|
[0.0.9]: https://github.com/guilhermegazzinelli/conexa-ruby/compare/v0.0.8...v0.0.9
|
|
92
140
|
[0.0.8]: https://github.com/guilhermegazzinelli/conexa-ruby/compare/v0.0.7...v0.0.8
|
|
93
141
|
[0.0.7]: https://github.com/guilhermegazzinelli/conexa-ruby/compare/v0.0.6...v0.0.7
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -46,13 +46,13 @@ Conexa.configure do |config|
|
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
# List customers
|
|
49
|
-
customers = Conexa::Customer.
|
|
49
|
+
customers = Conexa::Customer.all
|
|
50
50
|
customers.data.each do |customer|
|
|
51
51
|
puts "#{customer.customer_id}: #{customer.name}"
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
# Get a specific customer
|
|
55
|
-
customer = Conexa::Customer.
|
|
55
|
+
customer = Conexa::Customer.find(127)
|
|
56
56
|
puts customer.name
|
|
57
57
|
puts customer.address.city
|
|
58
58
|
```
|
|
@@ -110,7 +110,7 @@ customer = Conexa::Customer.create(
|
|
|
110
110
|
)
|
|
111
111
|
|
|
112
112
|
# Retrieve customer
|
|
113
|
-
customer = Conexa::Customer.
|
|
113
|
+
customer = Conexa::Customer.find(127)
|
|
114
114
|
customer.name # => "Empresa ABC Ltda"
|
|
115
115
|
customer.company_id # => 3
|
|
116
116
|
customer.is_active # => true
|
|
@@ -118,14 +118,28 @@ customer.address.city # => "Campinas"
|
|
|
118
118
|
customer.legal_person['cnpj'] # => "99.557.155/0001-90"
|
|
119
119
|
|
|
120
120
|
# Update customer
|
|
121
|
-
Conexa::Customer.
|
|
121
|
+
customer = Conexa::Customer.find(127)
|
|
122
|
+
customer.name = 'New Name'
|
|
123
|
+
customer.cell_number = '11888887777'
|
|
124
|
+
customer.save
|
|
122
125
|
|
|
123
126
|
# List customers with filters (new pagination)
|
|
124
|
-
customers = Conexa::Customer.
|
|
127
|
+
customers = Conexa::Customer.all(
|
|
125
128
|
company_id: [3],
|
|
126
129
|
is_active: true,
|
|
127
130
|
limit: 20
|
|
128
131
|
)
|
|
132
|
+
|
|
133
|
+
# Sub-resources (instance methods)
|
|
134
|
+
customer = Conexa::Customer.find(127)
|
|
135
|
+
customer.persons # => persons for this customer
|
|
136
|
+
customer.contracts # => contracts for this customer
|
|
137
|
+
customer.charges # => charges for this customer
|
|
138
|
+
|
|
139
|
+
# Sub-resources (class methods — saves a request)
|
|
140
|
+
Conexa::Customer.persons(127)
|
|
141
|
+
Conexa::Customer.contracts(127)
|
|
142
|
+
Conexa::Customer.charges(127)
|
|
129
143
|
```
|
|
130
144
|
|
|
131
145
|
### Contract
|
|
@@ -152,7 +166,7 @@ contract = Conexa::Contract.create_with_products(
|
|
|
152
166
|
)
|
|
153
167
|
|
|
154
168
|
# Retrieve contract
|
|
155
|
-
contract = Conexa::Contract.
|
|
169
|
+
contract = Conexa::Contract.find(456)
|
|
156
170
|
|
|
157
171
|
# Cancel contract
|
|
158
172
|
Conexa::Contract.cancel(456, cancel_date: '2024-12-31')
|
|
@@ -174,13 +188,13 @@ sale = Conexa::Sale.create(
|
|
|
174
188
|
puts sale.id # => 188481
|
|
175
189
|
|
|
176
190
|
# Retrieve sale
|
|
177
|
-
sale = Conexa::Sale.
|
|
191
|
+
sale = Conexa::Sale.find(188510)
|
|
178
192
|
sale.status # => "notBilled"
|
|
179
193
|
sale.amount # => 80.99
|
|
180
194
|
sale.discount_value # => 69.21
|
|
181
195
|
|
|
182
196
|
# List sales
|
|
183
|
-
sales = Conexa::Sale.
|
|
197
|
+
sales = Conexa::Sale.all(
|
|
184
198
|
customer_id: [450, 216],
|
|
185
199
|
status: 'notBilled',
|
|
186
200
|
date_from: '2024-01-01',
|
|
@@ -190,10 +204,13 @@ sales = Conexa::Sale.list(
|
|
|
190
204
|
)
|
|
191
205
|
|
|
192
206
|
# Update sale
|
|
193
|
-
Conexa::Sale.
|
|
207
|
+
sale = Conexa::Sale.find(188510)
|
|
208
|
+
sale.quantity = 2
|
|
209
|
+
sale.amount = 150.00
|
|
210
|
+
sale.save
|
|
194
211
|
|
|
195
212
|
# Delete sale (only if not billed)
|
|
196
|
-
Conexa::Sale.
|
|
213
|
+
Conexa::Sale.destroy(188510)
|
|
197
214
|
```
|
|
198
215
|
|
|
199
216
|
### Recurring Sale
|
|
@@ -208,20 +225,20 @@ recurring = Conexa::RecurringSale.create(
|
|
|
208
225
|
)
|
|
209
226
|
|
|
210
227
|
# List recurring sales for a contract
|
|
211
|
-
Conexa::RecurringSale.
|
|
228
|
+
Conexa::RecurringSale.all(contract_id: 456)
|
|
212
229
|
```
|
|
213
230
|
|
|
214
231
|
### Charge
|
|
215
232
|
|
|
216
233
|
```ruby
|
|
217
234
|
# Retrieve charge
|
|
218
|
-
charge = Conexa::Charge.
|
|
235
|
+
charge = Conexa::Charge.find(789)
|
|
219
236
|
charge.status # => "paid"
|
|
220
237
|
charge.amount # => 299.90
|
|
221
238
|
charge.due_date # => "2024-02-10"
|
|
222
239
|
|
|
223
240
|
# List charges
|
|
224
|
-
charges = Conexa::Charge.
|
|
241
|
+
charges = Conexa::Charge.all(
|
|
225
242
|
customer_id: [127],
|
|
226
243
|
status: 'pending',
|
|
227
244
|
due_date_from: '2024-01-01',
|
|
@@ -239,10 +256,10 @@ Conexa::Charge.send_email(789)
|
|
|
239
256
|
|
|
240
257
|
```ruby
|
|
241
258
|
# Retrieve bill
|
|
242
|
-
bill = Conexa::Bill.
|
|
259
|
+
bill = Conexa::Bill.find(101)
|
|
243
260
|
|
|
244
261
|
# List bills
|
|
245
|
-
bills = Conexa::Bill.
|
|
262
|
+
bills = Conexa::Bill.all(
|
|
246
263
|
customer_id: [127],
|
|
247
264
|
page: 1,
|
|
248
265
|
size: 50
|
|
@@ -253,10 +270,10 @@ bills = Conexa::Bill.list(
|
|
|
253
270
|
|
|
254
271
|
```ruby
|
|
255
272
|
# List plans
|
|
256
|
-
plans = Conexa::Plan.
|
|
273
|
+
plans = Conexa::Plan.all(company_id: [3])
|
|
257
274
|
|
|
258
275
|
# Retrieve plan
|
|
259
|
-
plan = Conexa::Plan.
|
|
276
|
+
plan = Conexa::Plan.find(5)
|
|
260
277
|
plan.name # => "Plano Básico"
|
|
261
278
|
plan.price # => 99.90
|
|
262
279
|
```
|
|
@@ -265,66 +282,66 @@ plan.price # => 99.90
|
|
|
265
282
|
|
|
266
283
|
```ruby
|
|
267
284
|
# List products
|
|
268
|
-
products = Conexa::Product.
|
|
285
|
+
products = Conexa::Product.all(company_id: [3], limit: 50)
|
|
269
286
|
|
|
270
287
|
# Retrieve product
|
|
271
|
-
product = Conexa::Product.
|
|
288
|
+
product = Conexa::Product.find(101)
|
|
272
289
|
|
|
273
290
|
# Create product
|
|
274
291
|
product = Conexa::Product.create(name: 'Novo Produto', company_id: 3)
|
|
275
292
|
|
|
276
293
|
# Delete product
|
|
277
|
-
Conexa::Product.
|
|
294
|
+
Conexa::Product.destroy(101)
|
|
278
295
|
```
|
|
279
296
|
|
|
280
297
|
### Receiving Method
|
|
281
298
|
|
|
282
299
|
```ruby
|
|
283
|
-
methods = Conexa::ReceivingMethod.
|
|
284
|
-
method = Conexa::ReceivingMethod.
|
|
300
|
+
methods = Conexa::ReceivingMethod.all(limit: 50)
|
|
301
|
+
method = Conexa::ReceivingMethod.find(11)
|
|
285
302
|
method.name # => "Cartão de Crédito"
|
|
286
303
|
```
|
|
287
304
|
|
|
288
305
|
### Payment Method
|
|
289
306
|
|
|
290
307
|
```ruby
|
|
291
|
-
methods = Conexa::PaymentMethod.
|
|
292
|
-
method = Conexa::PaymentMethod.
|
|
308
|
+
methods = Conexa::PaymentMethod.all(limit: 50)
|
|
309
|
+
method = Conexa::PaymentMethod.find(2)
|
|
293
310
|
```
|
|
294
311
|
|
|
295
312
|
### Bill Category / Subcategory
|
|
296
313
|
|
|
297
314
|
```ruby
|
|
298
|
-
categories = Conexa::BillCategory.
|
|
299
|
-
subcategories = Conexa::BillSubcategory.
|
|
315
|
+
categories = Conexa::BillCategory.all(limit: 50)
|
|
316
|
+
subcategories = Conexa::BillSubcategory.all(limit: 50)
|
|
300
317
|
```
|
|
301
318
|
|
|
302
319
|
### Cost Center
|
|
303
320
|
|
|
304
321
|
```ruby
|
|
305
|
-
centers = Conexa::CostCenter.
|
|
306
|
-
center = Conexa::CostCenter.
|
|
322
|
+
centers = Conexa::CostCenter.all(limit: 50)
|
|
323
|
+
center = Conexa::CostCenter.find(11)
|
|
307
324
|
```
|
|
308
325
|
|
|
309
326
|
### Account
|
|
310
327
|
|
|
311
328
|
```ruby
|
|
312
|
-
accounts = Conexa::Account.
|
|
313
|
-
account = Conexa::Account.
|
|
329
|
+
accounts = Conexa::Account.all(limit: 50)
|
|
330
|
+
account = Conexa::Account.find(23)
|
|
314
331
|
```
|
|
315
332
|
|
|
316
333
|
### Service Category
|
|
317
334
|
|
|
318
335
|
```ruby
|
|
319
|
-
categories = Conexa::ServiceCategory.
|
|
320
|
-
category = Conexa::ServiceCategory.
|
|
336
|
+
categories = Conexa::ServiceCategory.all(limit: 50)
|
|
337
|
+
category = Conexa::ServiceCategory.find(1)
|
|
321
338
|
```
|
|
322
339
|
|
|
323
340
|
### Room Booking
|
|
324
341
|
|
|
325
342
|
```ruby
|
|
326
343
|
# List bookings
|
|
327
|
-
bookings = Conexa::RoomBooking.
|
|
344
|
+
bookings = Conexa::RoomBooking.all(limit: 20)
|
|
328
345
|
|
|
329
346
|
# Create booking
|
|
330
347
|
booking = Conexa::RoomBooking.create(room_id: 5, customer_id: 127)
|
|
@@ -350,20 +367,20 @@ card = Conexa::CreditCard.create(
|
|
|
350
367
|
)
|
|
351
368
|
|
|
352
369
|
# List customer's cards
|
|
353
|
-
cards = Conexa::CreditCard.
|
|
370
|
+
cards = Conexa::CreditCard.all(customer_id: 127)
|
|
354
371
|
|
|
355
372
|
# Delete card
|
|
356
|
-
Conexa::CreditCard.
|
|
373
|
+
Conexa::CreditCard.destroy(card_id)
|
|
357
374
|
```
|
|
358
375
|
|
|
359
376
|
### Company (Unit)
|
|
360
377
|
|
|
361
378
|
```ruby
|
|
362
379
|
# List companies/units
|
|
363
|
-
companies = Conexa::Company.
|
|
380
|
+
companies = Conexa::Company.all
|
|
364
381
|
|
|
365
382
|
# Retrieve company
|
|
366
|
-
company = Conexa::Company.
|
|
383
|
+
company = Conexa::Company.find(3)
|
|
367
384
|
company.name # => "Matriz"
|
|
368
385
|
company.document # => "12.345.678/0001-90"
|
|
369
386
|
```
|
|
@@ -373,19 +390,27 @@ company.document # => "12.345.678/0001-90"
|
|
|
373
390
|
### New Pagination (recommended) — `limit`/`offset`/`hasNext`
|
|
374
391
|
|
|
375
392
|
```ruby
|
|
376
|
-
result = Conexa::Customer.
|
|
393
|
+
result = Conexa::Customer.all(limit: 50)
|
|
377
394
|
|
|
378
395
|
result.data # Array of customers
|
|
379
396
|
result.pagination.limit # => 50
|
|
380
397
|
result.pagination.offset # => 0
|
|
381
|
-
result.
|
|
398
|
+
result.has_next? # => true/false
|
|
382
399
|
|
|
383
|
-
# Iterate through all pages
|
|
400
|
+
# Iterate through all pages using next_page
|
|
401
|
+
result = Conexa::Customer.all(limit: 50)
|
|
402
|
+
loop do
|
|
403
|
+
result.data.each { |customer| process(customer) }
|
|
404
|
+
break unless result.has_next?
|
|
405
|
+
result = result.next_page
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
# Or manually with offset
|
|
384
409
|
offset = 0
|
|
385
410
|
loop do
|
|
386
|
-
result = Conexa::Customer.
|
|
411
|
+
result = Conexa::Customer.all(limit: 50, offset: offset)
|
|
387
412
|
result.data.each { |customer| process(customer) }
|
|
388
|
-
break unless result.
|
|
413
|
+
break unless result.has_next?
|
|
389
414
|
offset += 50
|
|
390
415
|
end
|
|
391
416
|
```
|
|
@@ -394,7 +419,7 @@ end
|
|
|
394
419
|
|
|
395
420
|
```ruby
|
|
396
421
|
# Still works but emits a deprecation warning
|
|
397
|
-
result = Conexa::Customer.
|
|
422
|
+
result = Conexa::Customer.all(page: 1, size: 20)
|
|
398
423
|
result.pagination.current_page # => 1
|
|
399
424
|
result.pagination.total_pages # => 10
|
|
400
425
|
```
|
|
@@ -407,12 +432,12 @@ The legacy `page`/`size` pagination is deprecated and will be removed on **2026-
|
|
|
407
432
|
|
|
408
433
|
```ruby
|
|
409
434
|
# BEFORE (legacy — deprecated)
|
|
410
|
-
result = Conexa::Customer.
|
|
411
|
-
result = Conexa::Customer.
|
|
435
|
+
result = Conexa::Customer.all(page: 1, size: 50)
|
|
436
|
+
result = Conexa::Customer.all(page: 2, size: 50)
|
|
412
437
|
|
|
413
438
|
# AFTER (new)
|
|
414
|
-
result = Conexa::Customer.
|
|
415
|
-
result = Conexa::Customer.
|
|
439
|
+
result = Conexa::Customer.all(limit: 50) # offset defaults to 0
|
|
440
|
+
result = Conexa::Customer.all(limit: 50, offset: 50) # second page
|
|
416
441
|
```
|
|
417
442
|
|
|
418
443
|
**Conversion formula:** `offset = (page - 1) * size`
|
|
@@ -436,19 +461,18 @@ result.pagination.has_next # => true/false
|
|
|
436
461
|
# BEFORE (legacy)
|
|
437
462
|
page = 1
|
|
438
463
|
loop do
|
|
439
|
-
result = Conexa::Customer.
|
|
464
|
+
result = Conexa::Customer.all(page: page, size: 100)
|
|
440
465
|
break if result.empty?
|
|
441
466
|
result.data.each { |c| process(c) }
|
|
442
467
|
page += 1
|
|
443
468
|
end
|
|
444
469
|
|
|
445
|
-
# AFTER (new)
|
|
446
|
-
|
|
470
|
+
# AFTER (new — using next_page)
|
|
471
|
+
result = Conexa::Customer.all(limit: 100)
|
|
447
472
|
loop do
|
|
448
|
-
result = Conexa::Customer.list(limit: 100, offset: offset)
|
|
449
473
|
result.data.each { |c| process(c) }
|
|
450
|
-
break unless result.
|
|
451
|
-
|
|
474
|
+
break unless result.has_next?
|
|
475
|
+
result = result.next_page
|
|
452
476
|
end
|
|
453
477
|
```
|
|
454
478
|
|
|
@@ -481,29 +505,22 @@ begin
|
|
|
481
505
|
customer = Conexa::Customer.create(name: '')
|
|
482
506
|
rescue Conexa::ValidationError => e
|
|
483
507
|
# Field validation errors (400)
|
|
484
|
-
e.errors.each do |error|
|
|
485
|
-
puts "#{error['field']}: #{error['messages'].join(', ')}"
|
|
486
|
-
end
|
|
487
|
-
rescue Conexa::AuthenticationError => e
|
|
488
|
-
# Authentication required (401)
|
|
489
|
-
puts e.message
|
|
490
|
-
rescue Conexa::AuthorizationError => e
|
|
491
|
-
# Not authorized (403)
|
|
492
508
|
puts e.message
|
|
493
|
-
rescue Conexa::
|
|
509
|
+
rescue Conexa::NotFound => e
|
|
494
510
|
# Resource not found (404)
|
|
495
511
|
puts e.message
|
|
496
|
-
rescue Conexa::
|
|
497
|
-
#
|
|
498
|
-
e.
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
512
|
+
rescue Conexa::ResponseError => e
|
|
513
|
+
# API response error (4xx/5xx)
|
|
514
|
+
puts e.message
|
|
515
|
+
rescue Conexa::RequestError => e
|
|
516
|
+
# Request-level error (invalid params, etc.)
|
|
517
|
+
puts e.message
|
|
518
|
+
rescue Conexa::ConnectionError => e
|
|
519
|
+
# Network/connection error
|
|
520
|
+
puts e.message
|
|
521
|
+
rescue Conexa::ConexaError => e
|
|
522
|
+
# Generic Conexa error (catch-all)
|
|
523
|
+
puts e.message
|
|
507
524
|
end
|
|
508
525
|
```
|
|
509
526
|
|
data/README_pt-BR.md
CHANGED
|
@@ -73,25 +73,27 @@ Cada recurso segue um conjunto consistente de padrões de métodos:
|
|
|
73
73
|
|
|
74
74
|
### Paginação
|
|
75
75
|
|
|
76
|
-
A
|
|
77
|
-
|
|
78
|
-
- **page**: Número da página atual (padrão: `1`)
|
|
79
|
-
- **size**: Quantidade de itens por página (padrão: `100`)
|
|
76
|
+
A gem utiliza por padrão `limit: 100, offset: 0` (nova paginação). O modelo legado `page`/`size` ainda funciona mas emite um aviso de depreciação.
|
|
80
77
|
|
|
81
78
|
#### Chamando com Paginação
|
|
82
79
|
|
|
83
80
|
```ruby
|
|
84
|
-
# Paginação padrão (
|
|
81
|
+
# Paginação padrão (limit: 100, offset: 0)
|
|
85
82
|
Conexa::Customer.all
|
|
86
83
|
|
|
87
|
-
#
|
|
88
|
-
Conexa::Customer.all(
|
|
84
|
+
# Com limite customizado
|
|
85
|
+
Conexa::Customer.all(limit: 50)
|
|
89
86
|
|
|
90
|
-
#
|
|
91
|
-
Conexa::Customer.all(
|
|
87
|
+
# Com offset
|
|
88
|
+
Conexa::Customer.all(limit: 50, offset: 100)
|
|
92
89
|
|
|
93
|
-
#
|
|
94
|
-
Conexa::Customer.
|
|
90
|
+
# Iteração automática com next_page
|
|
91
|
+
resultado = Conexa::Customer.all(limit: 50)
|
|
92
|
+
loop do
|
|
93
|
+
resultado.data.each { |cliente| processa(cliente) }
|
|
94
|
+
break unless resultado.has_next?
|
|
95
|
+
resultado = resultado.next_page
|
|
96
|
+
end
|
|
95
97
|
```
|
|
96
98
|
|
|
97
99
|
### Objeto Result
|
|
@@ -309,14 +311,22 @@ resultado = Conexa::Customer.all(limit: 50)
|
|
|
309
311
|
resultado.data # Array de clientes
|
|
310
312
|
resultado.pagination.limit # => 50
|
|
311
313
|
resultado.pagination.offset # => 0
|
|
312
|
-
resultado.
|
|
314
|
+
resultado.has_next? # => true/false
|
|
313
315
|
|
|
314
|
-
# Iterar por todas as páginas
|
|
316
|
+
# Iterar por todas as páginas usando next_page
|
|
317
|
+
resultado = Conexa::Customer.all(limit: 50)
|
|
318
|
+
loop do
|
|
319
|
+
resultado.data.each { |cliente| processa(cliente) }
|
|
320
|
+
break unless resultado.has_next?
|
|
321
|
+
resultado = resultado.next_page
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
# Ou manualmente com offset
|
|
315
325
|
offset = 0
|
|
316
326
|
loop do
|
|
317
327
|
resultado = Conexa::Customer.all(limit: 50, offset: offset)
|
|
318
328
|
resultado.data.each { |cliente| processa(cliente) }
|
|
319
|
-
break unless resultado.
|
|
329
|
+
break unless resultado.has_next?
|
|
320
330
|
offset += 50
|
|
321
331
|
end
|
|
322
332
|
```
|
|
@@ -364,13 +374,12 @@ loop do
|
|
|
364
374
|
pagina += 1
|
|
365
375
|
end
|
|
366
376
|
|
|
367
|
-
# DEPOIS (novo)
|
|
368
|
-
|
|
377
|
+
# DEPOIS (novo — usando next_page)
|
|
378
|
+
resultado = Conexa::Customer.all(limit: 100)
|
|
369
379
|
loop do
|
|
370
|
-
resultado = Conexa::Customer.all(limit: 100, offset: offset)
|
|
371
380
|
resultado.data.each { |c| processa(c) }
|
|
372
|
-
break unless resultado.
|
|
373
|
-
|
|
381
|
+
break unless resultado.has_next?
|
|
382
|
+
resultado = resultado.next_page
|
|
374
383
|
end
|
|
375
384
|
```
|
|
376
385
|
|
|
@@ -443,6 +452,21 @@ cliente.destroy
|
|
|
443
452
|
clientes = Conexa::Customer.find({ name: 'João Silva' }, 1, 20)
|
|
444
453
|
```
|
|
445
454
|
|
|
455
|
+
##### Sub-recursos do Cliente
|
|
456
|
+
|
|
457
|
+
```ruby
|
|
458
|
+
# Via instância (quando já possui o customer carregado)
|
|
459
|
+
cliente = Conexa::Customer.find(127)
|
|
460
|
+
cliente.persons # => Lista de persons deste cliente
|
|
461
|
+
cliente.contracts # => Lista de contratos deste cliente
|
|
462
|
+
cliente.charges # => Lista de cobranças deste cliente
|
|
463
|
+
|
|
464
|
+
# Via classe (economiza um request, não precisa buscar o customer)
|
|
465
|
+
Conexa::Customer.persons(127)
|
|
466
|
+
Conexa::Customer.contracts(127)
|
|
467
|
+
Conexa::Customer.charges(127)
|
|
468
|
+
```
|
|
469
|
+
|
|
446
470
|
#### Faturas (Bills)
|
|
447
471
|
|
|
448
472
|
##### Criando uma Fatura
|
data/REFERENCE.md
CHANGED
|
@@ -32,7 +32,7 @@ Conexa is a Brazilian SaaS platform for **recurring billing**, **subscription ma
|
|
|
32
32
|
|
|
33
33
|
```ruby
|
|
34
34
|
# Gemfile
|
|
35
|
-
gem 'conexa', '~> 0.
|
|
35
|
+
gem 'conexa', '~> 0.1.1'
|
|
36
36
|
|
|
37
37
|
# Or install directly
|
|
38
38
|
gem install conexa
|
|
@@ -211,7 +211,13 @@ customer.destroy
|
|
|
211
211
|
# or
|
|
212
212
|
Conexa::Customer.destroy(127)
|
|
213
213
|
|
|
214
|
-
# Sub-resources
|
|
214
|
+
# Sub-resources (instance methods — requires fetching customer first)
|
|
215
|
+
customer = Conexa::Customer.find(127)
|
|
216
|
+
customer.persons # List persons for this customer
|
|
217
|
+
customer.contracts # List contracts for this customer
|
|
218
|
+
customer.charges # List charges for this customer
|
|
219
|
+
|
|
220
|
+
# Sub-resources (class methods — saves a request, no need to fetch customer)
|
|
215
221
|
Conexa::Customer.persons(127) # List persons for customer
|
|
216
222
|
Conexa::Customer.contracts(127) # List contracts for customer
|
|
217
223
|
Conexa::Customer.charges(127) # List charges for customer
|
|
@@ -1034,7 +1040,7 @@ person.destroy
|
|
|
1034
1040
|
|
|
1035
1041
|
#### New Pagination (recommended) — `limit`/`offset`/`hasNext`
|
|
1036
1042
|
|
|
1037
|
-
All `#all` and `#find_by` methods
|
|
1043
|
+
All `#all` and `#find_by` methods use `limit`/`offset` by default. When no pagination params are passed, the gem defaults to `limit: 100, offset: 0`.
|
|
1038
1044
|
|
|
1039
1045
|
```ruby
|
|
1040
1046
|
# Page 1, 50 items
|
|
@@ -1043,24 +1049,35 @@ result = Conexa::Customer.all(limit: 50)
|
|
|
1043
1049
|
result.data # => Array of customers
|
|
1044
1050
|
result.pagination.limit # => 50
|
|
1045
1051
|
result.pagination.offset # => 0
|
|
1046
|
-
result.
|
|
1052
|
+
result.has_next? # => true/false
|
|
1047
1053
|
result.empty? # => false
|
|
1048
1054
|
|
|
1049
|
-
# Iterate all pages
|
|
1055
|
+
# Iterate all pages using next_page
|
|
1056
|
+
result = Conexa::Customer.all(limit: 100)
|
|
1057
|
+
loop do
|
|
1058
|
+
result.each { |customer| process(customer) }
|
|
1059
|
+
break unless result.has_next?
|
|
1060
|
+
result = result.next_page
|
|
1061
|
+
end
|
|
1062
|
+
|
|
1063
|
+
# Or manually with offset
|
|
1050
1064
|
offset = 0
|
|
1051
1065
|
loop do
|
|
1052
1066
|
result = Conexa::Customer.all(limit: 100, offset: offset)
|
|
1053
1067
|
break if result.empty?
|
|
1054
|
-
|
|
1055
1068
|
result.each { |customer| process(customer) }
|
|
1056
|
-
break unless result.
|
|
1069
|
+
break unless result.has_next?
|
|
1057
1070
|
offset += 100
|
|
1058
1071
|
end
|
|
1059
1072
|
```
|
|
1060
1073
|
|
|
1074
|
+
**`next_page`** — Fetches the next page automatically, preserving all original filter params. Raises `StopIteration` when there are no more pages.
|
|
1075
|
+
|
|
1076
|
+
**`has_next?`** — Returns `true` if more pages are available.
|
|
1077
|
+
|
|
1061
1078
|
#### Legacy Pagination (deprecated — removed 2026-08-01)
|
|
1062
1079
|
|
|
1063
|
-
If `
|
|
1080
|
+
If `page:` or `size:` is explicitly passed, the gem uses the old pagination model
|
|
1064
1081
|
(emitting a deprecation warning):
|
|
1065
1082
|
|
|
1066
1083
|
```ruby
|
|
@@ -1115,13 +1132,12 @@ loop do
|
|
|
1115
1132
|
page += 1
|
|
1116
1133
|
end
|
|
1117
1134
|
|
|
1118
|
-
# AFTER
|
|
1119
|
-
|
|
1135
|
+
# AFTER (using next_page)
|
|
1136
|
+
result = Conexa::Customer.all(limit: 100)
|
|
1120
1137
|
loop do
|
|
1121
|
-
result = Conexa::Customer.all(limit: 100, offset: offset)
|
|
1122
1138
|
result.each { |c| process(c) }
|
|
1123
|
-
break unless result.
|
|
1124
|
-
|
|
1139
|
+
break unless result.has_next?
|
|
1140
|
+
result = result.next_page
|
|
1125
1141
|
end
|
|
1126
1142
|
```
|
|
1127
1143
|
|
|
@@ -1255,6 +1271,10 @@ The API enforces a limit of 100 requests per minute (changing to **60 requests p
|
|
|
1255
1271
|
|
|
1256
1272
|
## Version History
|
|
1257
1273
|
|
|
1274
|
+
- **v0.1.1** - Add instance methods for Customer sub-resources (persons, contracts, charges)
|
|
1275
|
+
- **v0.1.0** - Default new pagination, Result#next_page, code review fixes, 502 specs
|
|
1276
|
+
- **v0.0.9** - New pagination model (limit/offset), new API v2 resources
|
|
1277
|
+
- **v0.0.8** - Fix Auth.login, integration tests, REFERENCE.md rewrite
|
|
1258
1278
|
- **v0.0.7** - Add Auth resource, fix Auth.login, add test suite with VCR
|
|
1259
1279
|
- **v0.0.6** - Fix nil guard in camelize_hash, fix Result#empty? delegation
|
|
1260
1280
|
- **v0.0.5** - Initial public release
|
data/lib/conexa/authenticator.rb
CHANGED