conexa 0.0.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +64 -1
- data/Gemfile.lock +1 -1
- data/README.md +211 -56
- data/README_pt-BR.md +116 -12
- data/REFERENCE.md +138 -14
- 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 +64 -28
- data/lib/conexa/object.rb +12 -17
- data/lib/conexa/{order_commom.rb → order_common.rb} +5 -5
- data/lib/conexa/request.rb +9 -8
- data/lib/conexa/resources/account.rb +33 -0
- data/lib/conexa/resources/bill.rb +3 -1
- data/lib/conexa/resources/bill_category.rb +33 -0
- data/lib/conexa/resources/bill_subcategory.rb +35 -0
- data/lib/conexa/resources/charge.rb +1 -1
- data/lib/conexa/resources/company.rb +2 -0
- data/lib/conexa/resources/cost_center.rb +33 -0
- data/lib/conexa/resources/credit_card.rb +2 -0
- data/lib/conexa/resources/customer.rb +3 -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/payment_method.rb +33 -0
- data/lib/conexa/resources/person.rb +2 -0
- data/lib/conexa/resources/plan.rb +2 -0
- data/lib/conexa/resources/product.rb +28 -4
- data/lib/conexa/resources/receiving_method.rb +55 -0
- data/lib/conexa/resources/recurring_sale.rb +2 -0
- data/lib/conexa/resources/result.rb +32 -5
- data/lib/conexa/resources/room_booking.rb +87 -0
- data/lib/conexa/resources/sale.rb +1 -1
- data/lib/conexa/resources/service_category.rb +33 -0
- data/lib/conexa/resources/supplier.rb +24 -1
- 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 +10 -2
data/REFERENCE.md
CHANGED
|
@@ -14,17 +14,25 @@ Conexa is a Brazilian SaaS platform for **recurring billing**, **subscription ma
|
|
|
14
14
|
- **Sale** - One-time sale (not recurring)
|
|
15
15
|
- **RecurringSale** - Recurring sale item within a contract
|
|
16
16
|
- **Plan** - Pricing plan with products and periodicities
|
|
17
|
-
- **Product** - Billable item/service
|
|
17
|
+
- **Product** - Billable item/service (now supports full CRUD)
|
|
18
18
|
- **InvoicingMethod** - Payment method configuration (boleto, PIX, credit card)
|
|
19
|
+
- **ReceivingMethod** - Receiving method configuration (cash, transfer, card machine)
|
|
20
|
+
- **PaymentMethod** - Payment method type (boleto, PIX, cartão)
|
|
21
|
+
- **BillCategory** - Bill expense category
|
|
22
|
+
- **BillSubcategory** - Bill expense subcategory
|
|
23
|
+
- **CostCenter** - Cost center for expense allocation
|
|
24
|
+
- **Account** - Bank account
|
|
25
|
+
- **ServiceCategory** - Service category for plans
|
|
19
26
|
- **Person** - Requester (solicitante) linked to a customer
|
|
20
27
|
- **Bill** - Financial bill (conta a pagar)
|
|
21
28
|
- **Supplier** - Supplier with PF/PJ data
|
|
29
|
+
- **RoomBooking** - Room booking with checkin/checkout (Conexa Coworking)
|
|
22
30
|
|
|
23
31
|
## Installation
|
|
24
32
|
|
|
25
33
|
```ruby
|
|
26
34
|
# Gemfile
|
|
27
|
-
gem 'conexa', '~> 0.0
|
|
35
|
+
gem 'conexa', '~> 0.1.0'
|
|
28
36
|
|
|
29
37
|
# Or install directly
|
|
30
38
|
gem install conexa
|
|
@@ -694,12 +702,16 @@ product = Conexa::Product.find(100)
|
|
|
694
702
|
product.name # => "Mensalidade"
|
|
695
703
|
|
|
696
704
|
# List products
|
|
697
|
-
products = Conexa::Product.all(company_id: [3])
|
|
698
|
-
|
|
705
|
+
products = Conexa::Product.all(company_id: [3], limit: 50)
|
|
706
|
+
|
|
707
|
+
# Create product
|
|
708
|
+
product = Conexa::Product.create(name: 'Novo Produto', company_id: 3)
|
|
699
709
|
|
|
700
|
-
|
|
710
|
+
# Delete product
|
|
711
|
+
Conexa::Product.destroy(100)
|
|
712
|
+
```
|
|
701
713
|
|
|
702
|
-
**
|
|
714
|
+
**API endpoints:** `GET /product/:id`, `GET /products`, `POST /product`, `DELETE /product/:id`
|
|
703
715
|
|
|
704
716
|
---
|
|
705
717
|
|
|
@@ -855,7 +867,7 @@ supplier.save
|
|
|
855
867
|
supplier.destroy
|
|
856
868
|
```
|
|
857
869
|
|
|
858
|
-
**API endpoints:** `POST /supplier`, `GET /supplier/:id`, `PATCH /supplier/:id`, `DELETE /supplier/:id`, `GET /
|
|
870
|
+
**API endpoints:** `POST /supplier`, `GET /supplier/:id`, `PATCH /supplier/:id`, `DELETE /supplier/:id`, `GET /suppliers`
|
|
859
871
|
|
|
860
872
|
**Create attributes:**
|
|
861
873
|
- `name` - Supplier name (required)
|
|
@@ -1020,27 +1032,131 @@ person.destroy
|
|
|
1020
1032
|
|
|
1021
1033
|
### Pagination
|
|
1022
1034
|
|
|
1023
|
-
|
|
1035
|
+
#### New Pagination (recommended) — `limit`/`offset`/`hasNext`
|
|
1036
|
+
|
|
1037
|
+
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
|
+
|
|
1039
|
+
```ruby
|
|
1040
|
+
# Page 1, 50 items
|
|
1041
|
+
result = Conexa::Customer.all(limit: 50)
|
|
1042
|
+
|
|
1043
|
+
result.data # => Array of customers
|
|
1044
|
+
result.pagination.limit # => 50
|
|
1045
|
+
result.pagination.offset # => 0
|
|
1046
|
+
result.has_next? # => true/false
|
|
1047
|
+
result.empty? # => false
|
|
1048
|
+
|
|
1049
|
+
# Iterate all pages using next_page
|
|
1050
|
+
result = Conexa::Customer.all(limit: 100)
|
|
1051
|
+
loop do
|
|
1052
|
+
result.each { |customer| process(customer) }
|
|
1053
|
+
break unless result.has_next?
|
|
1054
|
+
result = result.next_page
|
|
1055
|
+
end
|
|
1056
|
+
|
|
1057
|
+
# Or manually with offset
|
|
1058
|
+
offset = 0
|
|
1059
|
+
loop do
|
|
1060
|
+
result = Conexa::Customer.all(limit: 100, offset: offset)
|
|
1061
|
+
break if result.empty?
|
|
1062
|
+
result.each { |customer| process(customer) }
|
|
1063
|
+
break unless result.has_next?
|
|
1064
|
+
offset += 100
|
|
1065
|
+
end
|
|
1066
|
+
```
|
|
1067
|
+
|
|
1068
|
+
**`next_page`** — Fetches the next page automatically, preserving all original filter params. Raises `StopIteration` when there are no more pages.
|
|
1069
|
+
|
|
1070
|
+
**`has_next?`** — Returns `true` if more pages are available.
|
|
1071
|
+
|
|
1072
|
+
#### Legacy Pagination (deprecated — removed 2026-08-01)
|
|
1073
|
+
|
|
1074
|
+
If `page:` or `size:` is explicitly passed, the gem uses the old pagination model
|
|
1075
|
+
(emitting a deprecation warning):
|
|
1024
1076
|
|
|
1025
1077
|
```ruby
|
|
1026
|
-
#
|
|
1078
|
+
# Emits: DEPRECATION WARNING: O modelo antigo de paginação...
|
|
1027
1079
|
result = Conexa::Customer.all(page: 1, size: 50)
|
|
1028
1080
|
|
|
1029
1081
|
result.data # => Array of customers
|
|
1030
1082
|
result.pagination # => { "page" => 1, "size" => 50, "total" => 150 }
|
|
1031
1083
|
result.empty? # => false
|
|
1084
|
+
```
|
|
1085
|
+
|
|
1086
|
+
#### Migration Guide: Legacy → New Pagination
|
|
1032
1087
|
|
|
1033
|
-
|
|
1088
|
+
The legacy `page`/`size` pagination is deprecated and will be removed on **2026-08-01**. Follow these steps to migrate:
|
|
1089
|
+
|
|
1090
|
+
**Step 1 — Replace `page`/`size` with `limit`/`offset`:**
|
|
1091
|
+
|
|
1092
|
+
```ruby
|
|
1093
|
+
# BEFORE (legacy)
|
|
1094
|
+
result = Conexa::Customer.all(page: 1, size: 50)
|
|
1095
|
+
result = Conexa::Customer.all(page: 2, size: 50)
|
|
1096
|
+
|
|
1097
|
+
# AFTER (new)
|
|
1098
|
+
result = Conexa::Customer.all(limit: 50) # offset defaults to 0
|
|
1099
|
+
result = Conexa::Customer.all(limit: 50, offset: 50) # second page
|
|
1100
|
+
```
|
|
1101
|
+
|
|
1102
|
+
Conversion formula: `offset = (page - 1) * size`
|
|
1103
|
+
|
|
1104
|
+
**Step 2 — Update pagination metadata access:**
|
|
1105
|
+
|
|
1106
|
+
```ruby
|
|
1107
|
+
# BEFORE
|
|
1108
|
+
result.pagination # => { "page" => 1, "size" => 50, "total" => 150 }
|
|
1109
|
+
total_pages = (result.pagination["total"].to_f / size).ceil
|
|
1110
|
+
|
|
1111
|
+
# AFTER
|
|
1112
|
+
result.pagination.limit # => 50
|
|
1113
|
+
result.pagination.offset # => 0
|
|
1114
|
+
result.pagination.has_next # => true/false
|
|
1115
|
+
```
|
|
1116
|
+
|
|
1117
|
+
**Step 3 — Update iteration loops:**
|
|
1118
|
+
|
|
1119
|
+
```ruby
|
|
1120
|
+
# BEFORE
|
|
1034
1121
|
page = 1
|
|
1035
1122
|
loop do
|
|
1036
1123
|
result = Conexa::Customer.all(page: page, size: 100)
|
|
1037
1124
|
break if result.empty?
|
|
1038
|
-
|
|
1039
|
-
result.each { |customer| process(customer) }
|
|
1125
|
+
result.each { |c| process(c) }
|
|
1040
1126
|
page += 1
|
|
1041
1127
|
end
|
|
1128
|
+
|
|
1129
|
+
# AFTER (using next_page)
|
|
1130
|
+
result = Conexa::Customer.all(limit: 100)
|
|
1131
|
+
loop do
|
|
1132
|
+
result.each { |c| process(c) }
|
|
1133
|
+
break unless result.has_next?
|
|
1134
|
+
result = result.next_page
|
|
1135
|
+
end
|
|
1136
|
+
```
|
|
1137
|
+
|
|
1138
|
+
**Step 4 — Remove positional arguments:**
|
|
1139
|
+
|
|
1140
|
+
```ruby
|
|
1141
|
+
# BEFORE
|
|
1142
|
+
Conexa::Customer.all(2, 50) # page 2, size 50
|
|
1143
|
+
Conexa::Customer.find_by({}, 1, 20) # page 1, size 20
|
|
1144
|
+
|
|
1145
|
+
# AFTER
|
|
1146
|
+
Conexa::Customer.all(limit: 50, offset: 50)
|
|
1147
|
+
Conexa::Customer.find_by(limit: 20)
|
|
1042
1148
|
```
|
|
1043
1149
|
|
|
1150
|
+
**Quick reference:**
|
|
1151
|
+
|
|
1152
|
+
| Legacy | New |
|
|
1153
|
+
|---|---|
|
|
1154
|
+
| `page: 1, size: 50` | `limit: 50` (offset defaults to 0) |
|
|
1155
|
+
| `page: N, size: S` | `limit: S, offset: (N-1)*S` |
|
|
1156
|
+
| `pagination["total"]` | `pagination.has_next` |
|
|
1157
|
+
| `pagination["page"]` | `pagination.offset` |
|
|
1158
|
+
| Positional `(page, size)` | Keyword `limit:`, `offset:` |
|
|
1159
|
+
|
|
1044
1160
|
### Result Object
|
|
1045
1161
|
|
|
1046
1162
|
API calls return `Conexa::Result` objects:
|
|
@@ -1109,7 +1225,7 @@ Conexa::Charge.all(
|
|
|
1109
1225
|
|
|
1110
1226
|
### Rate Limiting
|
|
1111
1227
|
|
|
1112
|
-
The API enforces a limit of 100 requests per minute. Response headers:
|
|
1228
|
+
The API enforces a limit of 100 requests per minute (changing to **60 requests per minute** on 2026-04-27). Response headers:
|
|
1113
1229
|
- `X-Rate-Limit-Limit` - Maximum requests per minute
|
|
1114
1230
|
- `X-Rate-Limit-Remaining` - Remaining requests
|
|
1115
1231
|
- `X-Rate-Limit-Reset` - Seconds until limit resets
|
|
@@ -1127,13 +1243,21 @@ The API enforces a limit of 100 requests per minute. Response headers:
|
|
|
1127
1243
|
| Sale | yes | yes | yes | yes | yes | billed?, paid?, editable? |
|
|
1128
1244
|
| RecurringSale | yes | yes | yes | yes | yes | end_recurring_sale |
|
|
1129
1245
|
| Plan | yes | yes | yes | - | yes | - |
|
|
1130
|
-
| Product | yes | yes |
|
|
1246
|
+
| Product | yes | yes | yes | - | yes | - |
|
|
1131
1247
|
| InvoicingMethod | yes | yes | yes | yes | yes | - |
|
|
1248
|
+
| ReceivingMethod | yes | yes | - | - | - | - |
|
|
1249
|
+
| PaymentMethod | yes | yes | - | - | - | - |
|
|
1250
|
+
| BillCategory | yes | yes | - | - | - | - |
|
|
1251
|
+
| BillSubcategory | yes | yes | - | - | - | - |
|
|
1252
|
+
| CostCenter | yes | yes | - | - | - | - |
|
|
1253
|
+
| Account | yes | yes | - | - | - | - |
|
|
1254
|
+
| ServiceCategory | yes | yes | - | - | - | - |
|
|
1132
1255
|
| Bill | yes | yes | yes | - | - | - |
|
|
1133
1256
|
| Company | yes | yes | yes | yes | yes | - |
|
|
1134
1257
|
| Supplier | yes | yes | yes | yes | yes | - |
|
|
1135
1258
|
| CreditCard | yes | - | yes | yes | yes | - |
|
|
1136
1259
|
| Person | - | - | yes | yes | yes | - |
|
|
1260
|
+
| RoomBooking | yes | yes | yes | - | - | cancel, checkout, checkin |
|
|
1137
1261
|
|
|
1138
1262
|
**Legend:** `yes` = available, `-` = not available (raises NoMethodError or not implemented)
|
|
1139
1263
|
|
data/lib/conexa/authenticator.rb
CHANGED
data/lib/conexa/configuration.rb
CHANGED
data/lib/conexa/core_ext.rb
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Only define blank?/present? if not already provided (e.g., by ActiveSupport)
|
|
4
|
+
unless Object.method_defined?(:blank?)
|
|
5
|
+
class Object
|
|
6
|
+
def blank?
|
|
7
|
+
respond_to?(:empty?) ? !!empty? : !self
|
|
8
|
+
end
|
|
5
9
|
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
def present?
|
|
11
|
+
!blank?
|
|
12
|
+
end
|
|
8
13
|
end
|
|
9
14
|
end
|
data/lib/conexa/errors.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Conexa
|
|
2
4
|
class ConexaError < StandardError
|
|
3
5
|
end
|
|
@@ -38,11 +40,11 @@ module Conexa
|
|
|
38
40
|
|
|
39
41
|
def initialize(response)
|
|
40
42
|
@response = response
|
|
41
|
-
@errors = response['message']&.map do |
|
|
42
|
-
params =
|
|
43
|
+
@errors = response['message']&.map do |msg|
|
|
44
|
+
params = msg.values_at('message', 'parameter_name', 'type', 'url')
|
|
43
45
|
ParamError.new(*params)
|
|
44
46
|
end
|
|
45
|
-
super @errors&.map(&:message)
|
|
47
|
+
super @errors&.map(&:message)&.join(', ')
|
|
46
48
|
end
|
|
47
49
|
|
|
48
50
|
def to_h
|
data/lib/conexa/model.rb
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Conexa
|
|
2
4
|
# Base class for all API resources (Customer, Charge, Contract, etc.)
|
|
3
5
|
#
|
|
4
6
|
# == Attribute Access
|
|
5
|
-
#
|
|
7
|
+
#
|
|
6
8
|
# Attributes are automatically accessible via method_missing:
|
|
7
9
|
# customer.name # => "Empresa ABC"
|
|
8
10
|
# customer.company_id # => 3
|
|
@@ -31,29 +33,11 @@ module Conexa
|
|
|
31
33
|
# instead of "recurring_sale_id". Explicit declaration ensures correctness.
|
|
32
34
|
#
|
|
33
35
|
class Model < ConexaObject
|
|
34
|
-
class << self
|
|
35
|
-
# DSL for primary key attribute with :id alias
|
|
36
|
-
# @example
|
|
37
|
-
# primary_key_attribute :charge_id
|
|
38
|
-
# # Generates: charge_id method + chargeId alias + id alias
|
|
39
|
-
def primary_key_attribute(snake_name)
|
|
40
|
-
camel_name = Util.camelize_str(snake_name.to_s)
|
|
41
|
-
|
|
42
|
-
define_method(snake_name) do
|
|
43
|
-
@attributes[snake_name.to_s]
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
alias_method camel_name.to_sym, snake_name
|
|
47
|
-
alias_method :id, snake_name
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
36
|
def create
|
|
52
37
|
set_primary_key Conexa::Request.post(self.class.show_url, params: to_hash).call(class_name).attributes['id']
|
|
53
38
|
fetch
|
|
54
39
|
end
|
|
55
40
|
|
|
56
|
-
|
|
57
41
|
def save
|
|
58
42
|
update Conexa::Request.patch(self.class.show_url(primary_key), params: unsaved_attributes).call(class_name)
|
|
59
43
|
self
|
|
@@ -86,11 +70,26 @@ module Conexa
|
|
|
86
70
|
|
|
87
71
|
def destroy
|
|
88
72
|
raise RequestError.new('Invalid ID') unless id.present?
|
|
89
|
-
update Conexa::Request.delete(
|
|
73
|
+
update Conexa::Request.delete(self.class.show_url(primary_key)).call(class_name)
|
|
90
74
|
self
|
|
91
75
|
end
|
|
92
76
|
|
|
93
77
|
class << self
|
|
78
|
+
# DSL for primary key attribute with :id alias
|
|
79
|
+
# @example
|
|
80
|
+
# primary_key_attribute :charge_id
|
|
81
|
+
# # Generates: charge_id method + chargeId alias + id alias
|
|
82
|
+
def primary_key_attribute(snake_name)
|
|
83
|
+
camel_name = Util.camelize_str(snake_name.to_s)
|
|
84
|
+
|
|
85
|
+
define_method(snake_name) do
|
|
86
|
+
@attributes[snake_name.to_s]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
alias_method camel_name.to_sym, snake_name
|
|
90
|
+
alias_method :id, snake_name
|
|
91
|
+
end
|
|
92
|
+
|
|
94
93
|
def create(*args)
|
|
95
94
|
self.new(*args).create
|
|
96
95
|
end
|
|
@@ -101,18 +100,19 @@ module Conexa
|
|
|
101
100
|
end
|
|
102
101
|
alias :find :find_by_id
|
|
103
102
|
|
|
104
|
-
|
|
105
103
|
def find_by(params = Hash.new, page = nil, size = nil)
|
|
106
104
|
params = extract_page_size_or_params(page, size, **params)
|
|
107
|
-
raise RequestError.new('Invalid page size') if params[:page] < 1 or params[:size] < 1
|
|
105
|
+
raise RequestError.new('Invalid page size') if (!params.key?(:limit)) && (params[:page] < 1 or params[:size] < 1)
|
|
108
106
|
|
|
109
|
-
Conexa::Request.get(url, params: params).call
|
|
107
|
+
Conexa::Request.get(url, params: params).call(
|
|
108
|
+
underscored_class_name,
|
|
109
|
+
query_context: { resource_class: self, params: params }
|
|
110
|
+
)
|
|
110
111
|
end
|
|
111
112
|
alias :find_by_hash :find_by
|
|
112
113
|
|
|
113
114
|
def all(*args, **params)
|
|
114
|
-
params
|
|
115
|
-
find_by params
|
|
115
|
+
find_by(params, *args)
|
|
116
116
|
end
|
|
117
117
|
alias :where :all
|
|
118
118
|
|
|
@@ -131,7 +131,8 @@ module Conexa
|
|
|
131
131
|
end
|
|
132
132
|
|
|
133
133
|
def class_name
|
|
134
|
-
self.name.split('::').last
|
|
134
|
+
name = self.name.split('::').last
|
|
135
|
+
name[0].downcase + name[1..]
|
|
135
136
|
end
|
|
136
137
|
|
|
137
138
|
def underscored_class_name
|
|
@@ -139,8 +140,43 @@ module Conexa
|
|
|
139
140
|
end
|
|
140
141
|
|
|
141
142
|
def extract_page_size_or_params(*args, **params)
|
|
142
|
-
|
|
143
|
-
|
|
143
|
+
if args[0].is_a?(Hash)
|
|
144
|
+
params = args[0].merge(params)
|
|
145
|
+
page_val = nil
|
|
146
|
+
else
|
|
147
|
+
page_val = args[0]
|
|
148
|
+
end
|
|
149
|
+
size_val = args[1]
|
|
150
|
+
|
|
151
|
+
# Explicit new pagination (limit/offset)
|
|
152
|
+
if params.key?(:limit)
|
|
153
|
+
unless params[:limit].is_a?(Integer) && params[:limit].positive?
|
|
154
|
+
raise RequestError, "limit must be a positive integer"
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
params[:offset] ||= size_val if size_val.is_a?(Integer)
|
|
158
|
+
params[:offset] ||= 0
|
|
159
|
+
|
|
160
|
+
unless params[:offset].is_a?(Integer) && params[:offset] >= 0
|
|
161
|
+
raise RequestError, "offset must be a non-negative integer"
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
params.delete(:page)
|
|
165
|
+
params.delete(:size)
|
|
166
|
+
return params
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Explicit legacy pagination (page/size) — deprecated
|
|
170
|
+
if params.key?(:page) || params.key?(:size) || page_val.is_a?(Integer)
|
|
171
|
+
warn "DEPRECATION WARNING: O modelo antigo de paginação (page/size) será removido em 01 de agosto de 2026. Utilize limit e offset."
|
|
172
|
+
params[:page] ||= page_val || 1
|
|
173
|
+
params[:size] ||= size_val || 100
|
|
174
|
+
return params
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Default: new pagination
|
|
178
|
+
params[:limit] = 100
|
|
179
|
+
params[:offset] = 0
|
|
144
180
|
params
|
|
145
181
|
end
|
|
146
182
|
end
|
data/lib/conexa/object.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Conexa
|
|
2
4
|
# Base class for all Conexa objects with dynamic attribute access
|
|
3
5
|
#
|
|
@@ -24,8 +26,6 @@ module Conexa
|
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
def initialize(response = {})
|
|
27
|
-
# raise MissingCredentialsError.new("Missing :client_key for extra options #{options}") if options && !options[:client_key]
|
|
28
|
-
|
|
29
29
|
@attributes = Hash.new
|
|
30
30
|
@unsaved_attributes = Set.new
|
|
31
31
|
|
|
@@ -57,21 +57,13 @@ module Conexa
|
|
|
57
57
|
end]
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
def
|
|
61
|
-
|
|
60
|
+
def respond_to_missing?(name, include_private = false)
|
|
61
|
+
name_str = Util.to_snake_case(name.to_s)
|
|
62
|
+
return true if name_str.end_with?('=')
|
|
62
63
|
|
|
63
|
-
@attributes.
|
|
64
|
+
@attributes.key?(name_str) || @attributes.key?(name_str.to_sym) || super
|
|
64
65
|
end
|
|
65
66
|
|
|
66
|
-
# def to_s
|
|
67
|
-
# attributes_str = ''
|
|
68
|
-
# (attributes.keys - ['id', 'object']).sort.each do |key|
|
|
69
|
-
# attributes_str += " \033[1;33m#{key}:\033[0m#{self[key].inspect}" unless self[key].nil?
|
|
70
|
-
# end
|
|
71
|
-
# "\033[1;31m#<#{self.class.name}:\033[0;32m#{id}#{attributes_str}\033[0m\033[0m\033[1;31m>\033[0;32m"
|
|
72
|
-
# end
|
|
73
|
-
# # alias :inspect :to_s
|
|
74
|
-
|
|
75
67
|
protected
|
|
76
68
|
def update(attributes)
|
|
77
69
|
removed_attributes = @attributes.keys - attributes.to_hash.keys
|
|
@@ -111,7 +103,12 @@ module Conexa
|
|
|
111
103
|
end
|
|
112
104
|
|
|
113
105
|
if args.size == 0
|
|
114
|
-
|
|
106
|
+
if @attributes.key?(name)
|
|
107
|
+
return @attributes[name]
|
|
108
|
+
elsif @attributes.key?(name.to_sym)
|
|
109
|
+
return @attributes[name.to_sym]
|
|
110
|
+
end
|
|
111
|
+
return nil
|
|
115
112
|
end
|
|
116
113
|
end
|
|
117
114
|
|
|
@@ -122,7 +119,6 @@ module Conexa
|
|
|
122
119
|
super name, *args, &block
|
|
123
120
|
end
|
|
124
121
|
|
|
125
|
-
|
|
126
122
|
class << self
|
|
127
123
|
def convert(response, resource_name = nil, client_key=nil)
|
|
128
124
|
case response
|
|
@@ -149,7 +145,6 @@ module Conexa
|
|
|
149
145
|
|
|
150
146
|
def capitalize_name(name)
|
|
151
147
|
name.split('_').collect(&:capitalize).join
|
|
152
|
-
# name.gsub(/(\A\w|\_\w)/){ |str| str.gsub('_', '').upcase }
|
|
153
148
|
end
|
|
154
149
|
end
|
|
155
150
|
end
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
class OrderCommom < Model
|
|
1
|
+
# frozen_string_literal: true
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
#
|
|
3
|
+
module Conexa
|
|
4
|
+
class OrderCommon < Model
|
|
5
|
+
# Keep old name as alias for backwards compatibility
|
|
6
|
+
OrderCommom = self
|
|
7
7
|
|
|
8
8
|
#
|
|
9
9
|
# Request refund to Conexa api for this order
|
data/lib/conexa/request.rb
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'uri'
|
|
2
4
|
require 'rest_client'
|
|
3
5
|
require 'multi_json'
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
7
|
module Conexa
|
|
8
8
|
class Request
|
|
9
9
|
DEFAULT_HEADERS = {
|
|
@@ -29,7 +29,6 @@ module Conexa
|
|
|
29
29
|
response = MultiJson.decode response.body
|
|
30
30
|
return {data: response.dig("data") || response, pagination: response.dig("pagination")}
|
|
31
31
|
|
|
32
|
-
|
|
33
32
|
rescue RestClient::Exception => error
|
|
34
33
|
begin
|
|
35
34
|
parsed_error = MultiJson.decode error.http_body
|
|
@@ -60,16 +59,18 @@ module Conexa
|
|
|
60
59
|
raise Conexa::ConnectionError.new $!
|
|
61
60
|
end
|
|
62
61
|
|
|
63
|
-
def call(
|
|
62
|
+
def call(resource_name, query_context: nil)
|
|
64
63
|
dt = run
|
|
65
64
|
|
|
66
65
|
if dt[:pagination]
|
|
67
|
-
|
|
68
|
-
data: ConexaObject.convert(dt[:data],
|
|
66
|
+
result = ConexaObject.convert({
|
|
67
|
+
data: ConexaObject.convert(dt[:data], resource_name),
|
|
69
68
|
pagination: ConexaObject.convert(dt[:pagination], "pagination")}, "result")
|
|
69
|
+
result.instance_variable_set(:@query_context, query_context) if query_context
|
|
70
|
+
return result
|
|
70
71
|
end
|
|
71
72
|
|
|
72
|
-
ConexaObject.convert(dt[:data],
|
|
73
|
+
ConexaObject.convert(dt[:data], resource_name)
|
|
73
74
|
end
|
|
74
75
|
|
|
75
76
|
def self.get(url, options={})
|
|
@@ -105,7 +106,7 @@ module Conexa
|
|
|
105
106
|
@parameters = Util.camelize_hash(@parameters)
|
|
106
107
|
aux.merge!({ payload: MultiJson.encode(@parameters)}) unless %w(GET DELETE).include? method
|
|
107
108
|
|
|
108
|
-
extra_headers = DEFAULT_HEADERS
|
|
109
|
+
extra_headers = DEFAULT_HEADERS.dup
|
|
109
110
|
extra_headers[:authorization] = "Bearer #{Conexa.configuration.api_token}" unless @auth
|
|
110
111
|
extra_headers[:params] = @parameters if method == "GET"
|
|
111
112
|
aux.merge!({ headers: extra_headers })
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Conexa
|
|
4
|
+
# Account resource (Conta Bancária)
|
|
5
|
+
#
|
|
6
|
+
# @example Find an account
|
|
7
|
+
# account = Conexa::Account.find(23)
|
|
8
|
+
# account.name # => "Banco do Brasil"
|
|
9
|
+
#
|
|
10
|
+
# @example List accounts
|
|
11
|
+
# accounts = Conexa::Account.all(limit: 50)
|
|
12
|
+
#
|
|
13
|
+
# @!attribute [r] account_id
|
|
14
|
+
# @return [Integer] Account ID (also accessible as #id)
|
|
15
|
+
# @!attribute [r] name
|
|
16
|
+
# @return [String] Account name
|
|
17
|
+
# @!attribute [r] is_active
|
|
18
|
+
# @return [Boolean] Whether the account is active
|
|
19
|
+
#
|
|
20
|
+
class Account < Model
|
|
21
|
+
primary_key_attribute :account_id
|
|
22
|
+
|
|
23
|
+
class << self
|
|
24
|
+
def url(*params)
|
|
25
|
+
["/accounts", *params].join '/'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def show_url(*params)
|
|
29
|
+
["/account", *params].join '/'
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Conexa
|
|
4
|
+
# BillCategory resource (Categoria de Despesa)
|
|
5
|
+
#
|
|
6
|
+
# @example Find a bill category
|
|
7
|
+
# category = Conexa::BillCategory.find(4)
|
|
8
|
+
# category.name # => "Impostos"
|
|
9
|
+
#
|
|
10
|
+
# @example List bill categories
|
|
11
|
+
# categories = Conexa::BillCategory.all(limit: 50)
|
|
12
|
+
#
|
|
13
|
+
# @!attribute [r] bill_category_id
|
|
14
|
+
# @return [Integer] Bill category ID (also accessible as #id)
|
|
15
|
+
# @!attribute [r] name
|
|
16
|
+
# @return [String] Category name
|
|
17
|
+
# @!attribute [r] is_active
|
|
18
|
+
# @return [Boolean] Whether the category is active
|
|
19
|
+
#
|
|
20
|
+
class BillCategory < Model
|
|
21
|
+
primary_key_attribute :bill_category_id
|
|
22
|
+
|
|
23
|
+
class << self
|
|
24
|
+
def url(*params)
|
|
25
|
+
["/billCategories", *params].join '/'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def show_url(*params)
|
|
29
|
+
["/billCategory", *params].join '/'
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Conexa
|
|
4
|
+
# BillSubcategory resource (Subcategoria de Despesa)
|
|
5
|
+
#
|
|
6
|
+
# @example Find a bill subcategory
|
|
7
|
+
# subcategory = Conexa::BillSubcategory.find(29)
|
|
8
|
+
# subcategory.name # => "Taxa de Cartão"
|
|
9
|
+
#
|
|
10
|
+
# @example List bill subcategories
|
|
11
|
+
# subcategories = Conexa::BillSubcategory.all(limit: 50)
|
|
12
|
+
#
|
|
13
|
+
# @!attribute [r] bill_subcategory_id
|
|
14
|
+
# @return [Integer] Bill subcategory ID (also accessible as #id)
|
|
15
|
+
# @!attribute [r] name
|
|
16
|
+
# @return [String] Subcategory name
|
|
17
|
+
# @!attribute [r] bill_category_id
|
|
18
|
+
# @return [Integer] Parent bill category ID
|
|
19
|
+
# @!attribute [r] is_active
|
|
20
|
+
# @return [Boolean] Whether the subcategory is active
|
|
21
|
+
#
|
|
22
|
+
class BillSubcategory < Model
|
|
23
|
+
primary_key_attribute :bill_subcategory_id
|
|
24
|
+
|
|
25
|
+
class << self
|
|
26
|
+
def url(*params)
|
|
27
|
+
["/billSubcategories", *params].join '/'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def show_url(*params)
|
|
31
|
+
["/billSubcategory", *params].join '/'
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|