conexa 0.2.0 → 0.2.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 +59 -1
- data/README.md +2 -2
- data/README_pt-BR.md +3 -3
- data/REFERENCE.md +25 -10
- data/lib/conexa/deprecation.rb +44 -0
- data/lib/conexa/model.rb +7 -4
- data/lib/conexa/resources/charge.rb +48 -6
- data/lib/conexa/resources/contract.rb +58 -15
- data/lib/conexa/util.rb +7 -4
- data/lib/conexa/version.rb +1 -1
- data/lib/conexa.rb +2 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: af7a51117e4a311ae46b22248f416838e385336138f60d80c741aa671f47c4fe
|
|
4
|
+
data.tar.gz: 44aefe94b1b0fccf3b186be4377308bb6fe16e734d6c7c3fbd8adf7e5568cdc9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 52c72131519a01ee69239ac6f63b2f36f4f9f3252ec9d423ce74bd80096ae9e7d25b4eb229dae27a9ad7dac94883cd2b6a3c72db91e9f41cdf68db590a7d7db7
|
|
7
|
+
data.tar.gz: e85125857aa04e1ec23391063f7a93edaccadfde8dc726ff895fe50ce09dc19b9cd84d846d4ddd5a70046edfec8055c604dd14d64ec12b5d6dc56a0ffff85114
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,63 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.1] - 2026-08-13
|
|
11
|
+
|
|
12
|
+
Found validating 0.2.1 against a live tenant before publishing, and by reviewing
|
|
13
|
+
the same release. Folded in rather than shipped separately — 0.2.1 was never
|
|
14
|
+
published.
|
|
15
|
+
|
|
16
|
+
### Fixed — found validating and reviewing
|
|
17
|
+
- **`Charge::STATUSES` was the filter list, not the field list.** It shipped with
|
|
18
|
+
nine values, built from the 400 the API returns for an unrecognised filter. The
|
|
19
|
+
field itself can also hold `excluded`, which `?status=` does not accept — two
|
|
20
|
+
different lists, now `STATUSES` (10) and `FILTERABLE_STATUSES` (9).
|
|
21
|
+
- **`REFERENCE.md` still documented the pre-0.2.1 behaviour** — `contract.status`,
|
|
22
|
+
`charge.pending?`, and `status` listed as `active, ended, cancelled` /
|
|
23
|
+
`pending, paid, overdue`. A reader following it wrote code against fields and
|
|
24
|
+
values that do not exist. Every doc example filtering charges by
|
|
25
|
+
`status: "pending"` was also rejected by the API; corrected to `unpaid`.
|
|
26
|
+
- **Deprecations warn once per process.** `charges.select(&:pending?)` over one
|
|
27
|
+
page emitted a hundred identical lines, which is how a warning stops being read.
|
|
28
|
+
- `HANDOFF-0.2.1` §2 offered `Charge.settle(1)` to verify read-only mode. That
|
|
29
|
+
calls `find` first — a GET the guard allows — so it answered `NotFound` and
|
|
30
|
+
never reached the guard; and making it work would require pointing a real
|
|
31
|
+
settlement at a real charge to test the brake. Replaced with a transport call.
|
|
32
|
+
(#26)
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
- `Contract#active?` documents that `ended?` is the safe negation: `!active?`
|
|
36
|
+
reads an unknown contract as closed, because Ruby cannot tell `nil` from
|
|
37
|
+
`false` through `!`.
|
|
38
|
+
|
|
39
|
+
### Fixed — the original issue #23
|
|
40
|
+
- **`Contract#active?` and `#ended?` read `is_active`.** They compared a `status`
|
|
41
|
+
field contracts have never had, so `active?` answered `false` for an active
|
|
42
|
+
contract — the answer that biases a caller toward creating a second one. Both
|
|
43
|
+
return `nil` rather than a guess when the response did not carry `is_active`.
|
|
44
|
+
Deliberately not derived from `end_date`: an active contract can carry a future
|
|
45
|
+
closing date, so a present `end_date` does not mean closed. (#23)
|
|
46
|
+
- **`Charge#pending?` and `#overdue?` never matched anything.** API v2 has no
|
|
47
|
+
`pending` or `overdue` status — it rejects both and names the real set in the
|
|
48
|
+
400. The open state is **`unpaid`**. `#unpaid?` and `#cancelled?` are the
|
|
49
|
+
replacements; `pending?` stays as a deprecated alias, and `overdue?` warns and
|
|
50
|
+
returns false, since an overdue charge is `unpaid` with a `due_date` in the
|
|
51
|
+
past. `Charge::STATUSES` records the enum the API named.
|
|
52
|
+
- **`Contract`'s attribute documentation** described `status`, `payment_day`,
|
|
53
|
+
`value` and `billing_day`. None of the four exists. Replaced with the real
|
|
54
|
+
fields, verified against a live response rather than the collection alone.
|
|
55
|
+
|
|
56
|
+
`Sale`'s predicates were checked and left alone — `billed`, `paid` and
|
|
57
|
+
`notBilled` are all real values.
|
|
58
|
+
|
|
59
|
+
### Added
|
|
60
|
+
- `PostmanCollection.response_fields`, and specs asserting that the attributes
|
|
61
|
+
the predicates depend on appear in a documented response. The contract layer
|
|
62
|
+
compared verbs and paths only, which is exactly how a predicate could read a
|
|
63
|
+
field that has never existed. It is deliberately a union across examples and
|
|
64
|
+
never an exact set: the collection under-documents responses, so an exact-match
|
|
65
|
+
check would report real fields as missing.
|
|
66
|
+
|
|
10
67
|
## [0.2.0] - 2026-08-11
|
|
11
68
|
|
|
12
69
|
Aligns the gem with the published API v2 contract. **0.1.1 is broken**:
|
|
@@ -338,7 +395,8 @@ published documentation, and is now enforced by
|
|
|
338
395
|
- Charge with settle and PIX methods
|
|
339
396
|
- Pagination support
|
|
340
397
|
|
|
341
|
-
[Unreleased]: https://github.com/guilhermegazzinelli/conexa-ruby/compare/v0.2.
|
|
398
|
+
[Unreleased]: https://github.com/guilhermegazzinelli/conexa-ruby/compare/v0.2.1...HEAD
|
|
399
|
+
[0.2.1]: https://github.com/guilhermegazzinelli/conexa-ruby/compare/v0.2.0...v0.2.1
|
|
342
400
|
[0.2.0]: https://github.com/guilhermegazzinelli/conexa-ruby/compare/v0.1.1...v0.2.0
|
|
343
401
|
[0.1.1]: https://github.com/guilhermegazzinelli/conexa-ruby/compare/v0.1.0...v0.1.1
|
|
344
402
|
[0.1.0]: https://github.com/guilhermegazzinelli/conexa-ruby/compare/v0.0.9...v0.1.0
|
data/README.md
CHANGED
|
@@ -44,7 +44,7 @@ writing off and let the gem refuse instead of trusting yourself to be careful.
|
|
|
44
44
|
```ruby
|
|
45
45
|
Conexa.configure { |config| config.read_only = true }
|
|
46
46
|
|
|
47
|
-
Conexa::Charge.all(status: '
|
|
47
|
+
Conexa::Charge.all(status: 'unpaid') # fine
|
|
48
48
|
Conexa::Charge.settle(789) # raises Conexa::ReadOnlyError
|
|
49
49
|
```
|
|
50
50
|
|
|
@@ -272,7 +272,7 @@ charge.due_date # => "2024-02-10"
|
|
|
272
272
|
# List charges
|
|
273
273
|
charges = Conexa::Charge.all(
|
|
274
274
|
customer_id: [127],
|
|
275
|
-
status: '
|
|
275
|
+
status: 'unpaid',
|
|
276
276
|
due_date_from: '2024-01-01',
|
|
277
277
|
due_date_to: '2024-12-31'
|
|
278
278
|
)
|
data/README_pt-BR.md
CHANGED
|
@@ -49,7 +49,7 @@ confiar na própria atenção.
|
|
|
49
49
|
```ruby
|
|
50
50
|
Conexa.configure { |config| config.read_only = true }
|
|
51
51
|
|
|
52
|
-
Conexa::Charge.all(status: '
|
|
52
|
+
Conexa::Charge.all(status: 'unpaid') # ok
|
|
53
53
|
Conexa::Charge.settle(789) # levanta Conexa::ReadOnlyError
|
|
54
54
|
```
|
|
55
55
|
|
|
@@ -200,7 +200,7 @@ Conexa::Company.all(
|
|
|
200
200
|
)
|
|
201
201
|
|
|
202
202
|
# Filtrar faturas por status
|
|
203
|
-
Conexa::Bill.all(status: "
|
|
203
|
+
Conexa::Bill.all(status: "unpaid", limit: 20)
|
|
204
204
|
|
|
205
205
|
# Filtrar vendas
|
|
206
206
|
Conexa::Sale.all(page: 2, size: 6)
|
|
@@ -528,7 +528,7 @@ Conexa::Bill.destroy(bill_id)
|
|
|
528
528
|
##### Listando Faturas
|
|
529
529
|
|
|
530
530
|
```ruby
|
|
531
|
-
faturas = Conexa::Bill.
|
|
531
|
+
faturas = Conexa::Bill.find_by({ status: 'unpaid', limit: 20 })
|
|
532
532
|
```
|
|
533
533
|
|
|
534
534
|
#### Cobranças (Charges)
|
data/REFERENCE.md
CHANGED
|
@@ -75,7 +75,7 @@ else warns and is treated as off.
|
|
|
75
75
|
Conexa.configure { |c| c.read_only = true } # or CONEXA_READ_ONLY=1
|
|
76
76
|
|
|
77
77
|
Conexa.read_only do # block-scoped, thread-local
|
|
78
|
-
Conexa::Charge.all(status: '
|
|
78
|
+
Conexa::Charge.all(status: 'unpaid')
|
|
79
79
|
end
|
|
80
80
|
```
|
|
81
81
|
|
|
@@ -339,10 +339,18 @@ contract = Conexa::Contract.create_with_products(
|
|
|
339
339
|
|
|
340
340
|
# Find contract
|
|
341
341
|
contract = Conexa::Contract.find(456)
|
|
342
|
-
contract.
|
|
342
|
+
contract.is_active # => true (contracts have no `status` field)
|
|
343
343
|
contract.active? # => true
|
|
344
344
|
contract.ended? # => false
|
|
345
345
|
|
|
346
|
+
# An ACTIVE contract may carry a future end_date — a scheduled close is not a
|
|
347
|
+
# close. Do not derive "ended" from end_date.
|
|
348
|
+
contract.end_date # => "2026-11-30" while still active?
|
|
349
|
+
|
|
350
|
+
# active?/ended? return nil when the response did not carry is_active, rather
|
|
351
|
+
# than guessing. Prefer ended? over !active?: !nil is true, which would read an
|
|
352
|
+
# unknown contract as closed.
|
|
353
|
+
|
|
346
354
|
# List contracts
|
|
347
355
|
contracts = Conexa::Contract.all(
|
|
348
356
|
customer_id: [127],
|
|
@@ -396,7 +404,9 @@ contract.destroy
|
|
|
396
404
|
|
|
397
405
|
**Read-only attributes:**
|
|
398
406
|
- `contract_id` - ID
|
|
399
|
-
- `
|
|
407
|
+
- `is_active` - whether the contract is open (there is **no** `status` field)
|
|
408
|
+
- `end_date` - closing date; may be in the future on an active contract
|
|
409
|
+
- `due_day`, `amount`, `payment_frequency`, `end_reason_id`, `first_due_date`
|
|
400
410
|
|
|
401
411
|
**Helper methods:**
|
|
402
412
|
- `active?` - Check if active
|
|
@@ -419,17 +429,19 @@ charge = Conexa::Charge.create(
|
|
|
419
429
|
|
|
420
430
|
# Find charge
|
|
421
431
|
charge = Conexa::Charge.find(789)
|
|
422
|
-
charge.status # => "
|
|
432
|
+
charge.status # => "unpaid"
|
|
423
433
|
charge.amount # => 199.90
|
|
424
434
|
charge.due_date # => "2024-02-10"
|
|
425
435
|
charge.paid? # => false
|
|
426
|
-
charge.
|
|
427
|
-
charge.
|
|
436
|
+
charge.unpaid? # => true (the open state is `unpaid`, not `pending`)
|
|
437
|
+
charge.cancelled? # => false
|
|
438
|
+
Conexa::Charge::STATUSES # every value the field can take
|
|
439
|
+
Conexa::Charge::FILTERABLE_STATUSES # what ?status= accepts — not the same list
|
|
428
440
|
|
|
429
441
|
# List charges
|
|
430
442
|
charges = Conexa::Charge.all(
|
|
431
443
|
customer_id: [127],
|
|
432
|
-
status: '
|
|
444
|
+
status: 'unpaid',
|
|
433
445
|
due_date_from: '2024-01-01',
|
|
434
446
|
due_date_to: '2024-01-31'
|
|
435
447
|
)
|
|
@@ -486,8 +498,11 @@ Conexa::Charge.cancel(789)
|
|
|
486
498
|
|
|
487
499
|
**Helper methods:**
|
|
488
500
|
- `paid?` - Check if paid
|
|
489
|
-
- `
|
|
490
|
-
- `
|
|
501
|
+
- `unpaid?` - Check if still open
|
|
502
|
+
- `cancelled?` - Check if cancelled
|
|
503
|
+
- `pending?` - **deprecated** alias of `unpaid?`; the API has no `pending`
|
|
504
|
+
- `overdue?` - **deprecated**, always false. The API has no `overdue`: an overdue
|
|
505
|
+
charge is `unpaid` with a `due_date` in the past, so compare the date yourself
|
|
491
506
|
|
|
492
507
|
**Special methods:**
|
|
493
508
|
- `settle(params)` / `Charge.settle(id, params)` - Mark as paid
|
|
@@ -1250,7 +1265,7 @@ Conexa::Sale.all(status: 'notBilled')
|
|
|
1250
1265
|
# Combined
|
|
1251
1266
|
Conexa::Charge.all(
|
|
1252
1267
|
customer_id: [127],
|
|
1253
|
-
status: '
|
|
1268
|
+
status: 'unpaid',
|
|
1254
1269
|
due_date_from: '2024-01-01',
|
|
1255
1270
|
page: 1,
|
|
1256
1271
|
size: 100
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Conexa
|
|
4
|
+
# Emits each deprecation once per process.
|
|
5
|
+
#
|
|
6
|
+
# The warnings exist to be read once and acted on. Emitting per call turns them
|
|
7
|
+
# into noise a caller learns to filter — `charges.select(&:pending?)` over one
|
|
8
|
+
# page of results produced a hundred identical lines, which is how a warning
|
|
9
|
+
# stops being read.
|
|
10
|
+
module Deprecation
|
|
11
|
+
@seen = {}
|
|
12
|
+
@mutex = Mutex.new
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
# @param key [Object] identifies the deprecation, not the call site
|
|
16
|
+
# @param message [String] what changed and what to do instead
|
|
17
|
+
# @return [nil]
|
|
18
|
+
def warn_once(key, message)
|
|
19
|
+
@mutex.synchronize do
|
|
20
|
+
return nil if @seen[key]
|
|
21
|
+
|
|
22
|
+
@seen[key] = true
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
Kernel.warn("DEPRECATION WARNING: #{message}")
|
|
26
|
+
nil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Only for tests: lets a spec observe a warning that another example
|
|
30
|
+
# already consumed.
|
|
31
|
+
# @api private
|
|
32
|
+
def reset!
|
|
33
|
+
@mutex.synchronize { @seen = {} }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Mixed into the classes that carry deprecated methods.
|
|
39
|
+
module Deprecatable
|
|
40
|
+
def deprecate(key, message)
|
|
41
|
+
Deprecation.warn_once([self, key], message)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
data/lib/conexa/model.rb
CHANGED
|
@@ -35,6 +35,8 @@ module Conexa
|
|
|
35
35
|
# instead of "recurring_sale_id". Explicit declaration ensures correctness.
|
|
36
36
|
#
|
|
37
37
|
class Model < ConexaObject
|
|
38
|
+
extend Deprecatable
|
|
39
|
+
|
|
38
40
|
def create
|
|
39
41
|
created = Conexa::Request.post(self.class.show_url, params: to_hash).call(class_name)
|
|
40
42
|
|
|
@@ -227,10 +229,11 @@ module Conexa
|
|
|
227
229
|
raise RequestError, "size must be a positive integer"
|
|
228
230
|
end
|
|
229
231
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
232
|
+
deprecate(:page_size,
|
|
233
|
+
"page/size foi substituído por limit/offset e será removido em " \
|
|
234
|
+
"conexa 0.3.0. A API v2 valida `page` e depois o ignora, devolvendo " \
|
|
235
|
+
"sempre a primeira página; os valores são convertidos para " \
|
|
236
|
+
"limit=size, offset=(page-1)*size.")
|
|
234
237
|
|
|
235
238
|
params[:limit] = size
|
|
236
239
|
params[:offset] = (page - 1) * size
|
|
@@ -29,22 +29,64 @@ module Conexa
|
|
|
29
29
|
class Charge < Model
|
|
30
30
|
primary_key_attribute :charge_id
|
|
31
31
|
|
|
32
|
-
#
|
|
32
|
+
# The values `status` can take on a charge, per the collection's field table
|
|
33
|
+
# for `GET /charge/:id`.
|
|
34
|
+
#
|
|
35
|
+
# **`excluded` is here but not in {FILTERABLE_STATUSES}.** The two lists are
|
|
36
|
+
# not the same thing: a charge can hold a status you cannot query by. This
|
|
37
|
+
# constant shipped with nine values in 0.2.1 because it was built from the
|
|
38
|
+
# filter's rejection message rather than from the field table.
|
|
39
|
+
STATUSES = %w[unpaid paid negotiated generatedByNegotiation cancelled
|
|
40
|
+
denied thirdPartyCompany protested juridical excluded].freeze
|
|
41
|
+
|
|
42
|
+
# What `GET /charges?status=` accepts. The API names them in the 400 it
|
|
43
|
+
# returns for an unrecognised value, so this list is the API's own:
|
|
44
|
+
#
|
|
45
|
+
# status=zzz -> 400 "Status is not on the list (unpaid, negotiated,
|
|
46
|
+
# generatedByNegotiation, cancelled, paid, denied,
|
|
47
|
+
# thirdPartyCompany, protested, juridical)"
|
|
48
|
+
#
|
|
49
|
+
# `pending` and `overdue` are in neither list, which is why the predicates
|
|
50
|
+
# built on them never matched.
|
|
51
|
+
FILTERABLE_STATUSES = (STATUSES - %w[excluded]).freeze
|
|
52
|
+
|
|
33
53
|
# @return [Boolean]
|
|
34
54
|
def paid?
|
|
35
55
|
status == 'paid'
|
|
36
56
|
end
|
|
37
57
|
|
|
38
|
-
#
|
|
58
|
+
# Is this charge still open?
|
|
39
59
|
# @return [Boolean]
|
|
40
|
-
def
|
|
41
|
-
status == '
|
|
60
|
+
def unpaid?
|
|
61
|
+
status == 'unpaid'
|
|
42
62
|
end
|
|
43
63
|
|
|
44
|
-
# Check if charge is overdue
|
|
45
64
|
# @return [Boolean]
|
|
65
|
+
def cancelled?
|
|
66
|
+
status == 'cancelled'
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# @deprecated The API has no `pending` status; the open state is `unpaid`.
|
|
70
|
+
# This alias only exists so callers written against the old, never-matching
|
|
71
|
+
# predicate keep working while they migrate.
|
|
72
|
+
# @return [Boolean]
|
|
73
|
+
def pending?
|
|
74
|
+
self.class.deprecate(:pending?,
|
|
75
|
+
"`Charge#pending?` foi renomeado para `unpaid?` em conexa 0.2.1 — " \
|
|
76
|
+
"a API v2 não tem status `pending`, o estado em aberto chama-se " \
|
|
77
|
+
"`unpaid`. O alias será removido em 0.3.0.")
|
|
78
|
+
unpaid?
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# @deprecated The API has no `overdue` status. An overdue charge is `unpaid`
|
|
82
|
+
# with a `due_date` in the past; compare the date yourself.
|
|
83
|
+
# @return [Boolean] always false
|
|
46
84
|
def overdue?
|
|
47
|
-
|
|
85
|
+
self.class.deprecate(:overdue?,
|
|
86
|
+
"`Charge#overdue?` sempre devolveu false — a API v2 não tem status " \
|
|
87
|
+
"`overdue`. Use `unpaid?` e compare `due_date`. O método será " \
|
|
88
|
+
"removido em 0.3.0.")
|
|
89
|
+
false
|
|
48
90
|
end
|
|
49
91
|
|
|
50
92
|
# Settle (pay) this charge
|
|
@@ -60,38 +60,81 @@ module Conexa
|
|
|
60
60
|
# @example End a contract
|
|
61
61
|
# Conexa::Contract.set_end_date(456, date: '2026-12-31')
|
|
62
62
|
#
|
|
63
|
+
# == Attributes
|
|
64
|
+
#
|
|
65
|
+
# Checked against a live response, not only the collection — which omits
|
|
66
|
+
# +isActive+, +extraFields+ and +firstDueDate+ from its `GET /contract/:id`
|
|
67
|
+
# examples even though the API returns them.
|
|
68
|
+
#
|
|
69
|
+
# **There is no +status+ field on a contract.** +is_active+ is how you tell an
|
|
70
|
+
# open contract from a closed one.
|
|
71
|
+
#
|
|
63
72
|
# @!attribute [r] contract_id
|
|
64
73
|
# @return [Integer] Contract ID (also accessible as #id)
|
|
65
74
|
# @!attribute [r] customer_id
|
|
66
75
|
# @return [Integer] Customer ID
|
|
67
76
|
# @!attribute [r] plan_id
|
|
68
77
|
# @return [Integer, nil] Plan ID
|
|
69
|
-
# @!attribute [r]
|
|
70
|
-
# @return [
|
|
78
|
+
# @!attribute [r] is_active
|
|
79
|
+
# @return [Boolean] whether the contract is open
|
|
71
80
|
# @!attribute [r] start_date
|
|
72
81
|
# @return [String] Start date
|
|
73
82
|
# @!attribute [r] end_date
|
|
74
|
-
# @return [String, nil]
|
|
75
|
-
#
|
|
76
|
-
#
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
#
|
|
83
|
+
# @return [String, nil] closing date. May be in the future on an **active**
|
|
84
|
+
# contract — a scheduled close is not a closed contract.
|
|
85
|
+
# @!attribute [r] end_reason_id
|
|
86
|
+
# @return [Integer, nil] closing-reason id
|
|
87
|
+
# @!attribute [r] due_day
|
|
88
|
+
# @return [Integer] day of the month the contract falls due
|
|
89
|
+
# @!attribute [r] first_due_date
|
|
90
|
+
# @return [String, nil] due date of the first instalment
|
|
91
|
+
# @!attribute [r] amount
|
|
92
|
+
# @return [Float] contract value
|
|
93
|
+
# @!attribute [r] payment_frequency
|
|
94
|
+
# @return [String] monthly, bimonthly, quarterly, semester or yearly
|
|
95
|
+
# @!attribute [r] date_sales_generation
|
|
96
|
+
# @return [String, nil] when sales are generated from the contract
|
|
97
|
+
# @!attribute [r] cost_center_id
|
|
98
|
+
# @return [Integer, nil] cost centre — present on read, rejected on create
|
|
99
|
+
# @!attribute [r] seller_id
|
|
100
|
+
# @return [Integer, nil] seller (user) id
|
|
101
|
+
# @!attribute [r] contract_summary
|
|
102
|
+
# @return [String, nil] short description
|
|
103
|
+
# @!attribute [r] fidelity_date
|
|
104
|
+
# @return [String, nil] loyalty date
|
|
105
|
+
# @!attribute [r] had_prorata
|
|
106
|
+
# @return [Boolean] whether pro rata was applied
|
|
81
107
|
#
|
|
82
108
|
class Contract < Model
|
|
83
109
|
primary_key_attribute :contract_id
|
|
84
110
|
|
|
85
|
-
#
|
|
86
|
-
#
|
|
111
|
+
# Is this contract open?
|
|
112
|
+
#
|
|
113
|
+
# Reads +is_active+, which is what the API sends. It used to compare a
|
|
114
|
+
# +status+ field that contracts have never had, so it answered +false+ for an
|
|
115
|
+
# active contract — the answer that makes a caller create a second one.
|
|
116
|
+
#
|
|
117
|
+
# Deliberately not derived from +end_date+: an active contract can carry a
|
|
118
|
+
# future closing date, so a present +end_date+ does not mean closed.
|
|
119
|
+
#
|
|
120
|
+
# **Prefer {#ended?} over `!active?`.** Ruby cannot tell +nil+ from +false+
|
|
121
|
+
# through `!`, so `!active?` reads an *unknown* contract as closed — the
|
|
122
|
+
# same "treat unknown as inactive" that this fix exists to remove. `ended?`
|
|
123
|
+
# preserves the nil.
|
|
124
|
+
#
|
|
125
|
+
# @return [Boolean, nil] nil when the response did not carry +is_active+,
|
|
126
|
+
# rather than a guess
|
|
87
127
|
def active?
|
|
88
|
-
|
|
128
|
+
value = is_active
|
|
129
|
+
value.nil? ? nil : !!value
|
|
89
130
|
end
|
|
90
131
|
|
|
91
|
-
#
|
|
92
|
-
# @
|
|
132
|
+
# Is this contract closed?
|
|
133
|
+
# @see #active?
|
|
134
|
+
# @return [Boolean, nil] nil when the response did not carry +is_active+
|
|
93
135
|
def ended?
|
|
94
|
-
|
|
136
|
+
value = active?
|
|
137
|
+
value.nil? ? nil : !value
|
|
95
138
|
end
|
|
96
139
|
|
|
97
140
|
# Set this contract's end date — closing it, or amending an existing closure.
|
data/lib/conexa/util.rb
CHANGED
|
@@ -68,10 +68,7 @@ module Conexa
|
|
|
68
68
|
legacy = [params.delete(:end_date), params.delete("end_date")].compact.first
|
|
69
69
|
explicit = [params.delete(:date), params.delete("date")].compact.first
|
|
70
70
|
|
|
71
|
-
if legacy
|
|
72
|
-
warn "DEPRECATION WARNING: `end_date:` foi renomeado para `date:` em conexa 0.2.0 " \
|
|
73
|
-
"(a API v2 rejeita `endDate`). O alias será removido em 0.3.0."
|
|
74
|
-
end
|
|
71
|
+
warn_end_date_renamed if legacy
|
|
75
72
|
|
|
76
73
|
# An explicit date wins; a key present with a nil value is not one.
|
|
77
74
|
date = explicit || legacy
|
|
@@ -84,6 +81,12 @@ module Conexa
|
|
|
84
81
|
end
|
|
85
82
|
|
|
86
83
|
|
|
84
|
+
def warn_end_date_renamed
|
|
85
|
+
Deprecation.warn_once(:end_date_param,
|
|
86
|
+
"`end_date:` foi renomeado para `date:` em conexa 0.2.0 " \
|
|
87
|
+
"(a API v2 rejeita `endDate`). O alias será removido em 0.3.0.")
|
|
88
|
+
end
|
|
89
|
+
|
|
87
90
|
# Convert a payload's keys to the camelCase the API expects, all the way
|
|
88
91
|
# down. Arrays of objects matter as much as nested hashes: ten documented
|
|
89
92
|
# endpoints take them (complementaryServices, productQuotas, devices,
|
data/lib/conexa/version.rb
CHANGED
data/lib/conexa.rb
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "conexa/version"
|
|
4
|
+
# No dependencies of its own, and Model extends it at load time.
|
|
5
|
+
require_relative "conexa/deprecation"
|
|
4
6
|
require_relative "conexa/request"
|
|
5
7
|
require_relative "conexa/object"
|
|
6
8
|
require_relative "conexa/model"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: conexa
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Guilherme Gazzinelli
|
|
@@ -109,6 +109,7 @@ files:
|
|
|
109
109
|
- lib/conexa.rb
|
|
110
110
|
- lib/conexa/configuration.rb
|
|
111
111
|
- lib/conexa/core_ext.rb
|
|
112
|
+
- lib/conexa/deprecation.rb
|
|
112
113
|
- lib/conexa/errors.rb
|
|
113
114
|
- lib/conexa/generators/install_generator.rb
|
|
114
115
|
- lib/conexa/model.rb
|