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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +64 -1
  3. data/Gemfile.lock +1 -1
  4. data/README.md +211 -56
  5. data/README_pt-BR.md +116 -12
  6. data/REFERENCE.md +138 -14
  7. data/lib/conexa/authenticator.rb +2 -0
  8. data/lib/conexa/configuration.rb +2 -0
  9. data/lib/conexa/core_ext.rb +11 -6
  10. data/lib/conexa/errors.rb +5 -3
  11. data/lib/conexa/model.rb +64 -28
  12. data/lib/conexa/object.rb +12 -17
  13. data/lib/conexa/{order_commom.rb → order_common.rb} +5 -5
  14. data/lib/conexa/request.rb +9 -8
  15. data/lib/conexa/resources/account.rb +33 -0
  16. data/lib/conexa/resources/bill.rb +3 -1
  17. data/lib/conexa/resources/bill_category.rb +33 -0
  18. data/lib/conexa/resources/bill_subcategory.rb +35 -0
  19. data/lib/conexa/resources/charge.rb +1 -1
  20. data/lib/conexa/resources/company.rb +2 -0
  21. data/lib/conexa/resources/cost_center.rb +33 -0
  22. data/lib/conexa/resources/credit_card.rb +2 -0
  23. data/lib/conexa/resources/customer.rb +3 -3
  24. data/lib/conexa/resources/invoicing_method.rb +2 -0
  25. data/lib/conexa/resources/legal_person.rb +2 -0
  26. data/lib/conexa/resources/pagination.rb +2 -0
  27. data/lib/conexa/resources/payment_method.rb +33 -0
  28. data/lib/conexa/resources/person.rb +2 -0
  29. data/lib/conexa/resources/plan.rb +2 -0
  30. data/lib/conexa/resources/product.rb +28 -4
  31. data/lib/conexa/resources/receiving_method.rb +55 -0
  32. data/lib/conexa/resources/recurring_sale.rb +2 -0
  33. data/lib/conexa/resources/result.rb +32 -5
  34. data/lib/conexa/resources/room_booking.rb +87 -0
  35. data/lib/conexa/resources/sale.rb +1 -1
  36. data/lib/conexa/resources/service_category.rb +33 -0
  37. data/lib/conexa/resources/supplier.rb +24 -1
  38. data/lib/conexa/token_manager.rb +3 -1
  39. data/lib/conexa/util.rb +37 -50
  40. data/lib/conexa/version.rb +1 -1
  41. data/lib/conexa.rb +1 -1
  42. 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.7'
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
- **API endpoints:** `GET /product/:id`, `GET /products`
710
+ # Delete product
711
+ Conexa::Product.destroy(100)
712
+ ```
701
713
 
702
- **Note:** Products cannot be created/updated via this gem. `save` raises `NoMethodError`.
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 /supplier` (list)
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
- All `#all` and `#find_by` methods support pagination:
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
- # Page 1, 50 items per page
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
- # Iterate all pages
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
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'jwt'
2
4
 
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Conexa
2
4
  class Configuration
3
5
  attr_accessor :api_token, :api_host
@@ -1,9 +1,14 @@
1
- class Object
2
- def blank?
3
- respond_to?(:empty?) ? !!empty? : !self
4
- end
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
- def present?
7
- !blank?
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 |message|
42
- params = error.values_at('message', 'parameter_name', 'type', 'url')
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).join(', ')
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( self.class.show_url(primary_key) ).call(class_name)
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 underscored_class_name
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 = extract_page_size_or_params(*args, **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.downcase
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
- params[:page] ||= args[0] || 1
143
- params[:size] ||= args[1] || 100
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 respond_to?(name, include_all = false)
61
- return true if name.to_s.end_with? '='
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.has_key?(name.to_s) || super
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
- return self[name] || self[name.to_sym]
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
- module Conexa
2
- class OrderCommom < Model
1
+ # frozen_string_literal: true
3
2
 
4
- # def self.url(*params)
5
- # ["/#{ CGI.escape underscored_class_name }", *params].join '/'
6
- # end
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
@@ -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(ressource_name)
62
+ def call(resource_name, query_context: nil)
64
63
  dt = run
65
64
 
66
65
  if dt[:pagination]
67
- return ConexaObject.convert({
68
- data: ConexaObject.convert(dt[:data], ressource_name),
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], ressource_name)
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
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Conexa
2
4
  class Bill < Model
3
5
  def save
4
- raise NoMethodError
6
+ raise NoMethodError, "Bill does not support save"
5
7
  end
6
8
  end
7
9
  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