conexa 0.0.6 → 0.0.8
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 +68 -26
- data/Gemfile +0 -2
- data/Gemfile.lock +9 -41
- data/README.md +297 -533
- data/README_pt-BR.md +7 -7
- data/REFERENCE.md +1152 -0
- data/docs/postman-collection.json +30785 -0
- data/lib/conexa/authenticator.rb +2 -0
- data/lib/conexa/model.rb +53 -2
- data/lib/conexa/object.rb +17 -0
- data/lib/conexa/resources/address.rb +16 -0
- data/lib/conexa/resources/auth.rb +38 -0
- data/lib/conexa/resources/charge.rb +82 -7
- data/lib/conexa/resources/contract.rb +58 -3
- data/lib/conexa/resources/credit_card.rb +2 -0
- data/lib/conexa/resources/customer.rb +93 -1
- data/lib/conexa/resources/invoicing_method.rb +2 -0
- data/lib/conexa/resources/person.rb +0 -14
- data/lib/conexa/resources/recurring_sale.rb +2 -0
- data/lib/conexa/resources/sale.rb +75 -1
- data/lib/conexa/version.rb +1 -1
- data/lib/conexa.rb +1 -0
- data/scripts/extract_fixtures.rb +35 -0
- metadata +8 -8
- data/.tool-versions +0 -1
- data/lib/conexa/resources/addres.rb +0 -4
data/REFERENCE.md
ADDED
|
@@ -0,0 +1,1152 @@
|
|
|
1
|
+
# Conexa Ruby - LLM Reference
|
|
2
|
+
|
|
3
|
+
> Ruby client for the Conexa API - Brazilian billing and subscription management platform.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Conexa is a Brazilian SaaS platform for **recurring billing**, **subscription management**, and **financial operations**. This gem provides a Ruby interface to their REST API v2.
|
|
8
|
+
|
|
9
|
+
**Key concepts:**
|
|
10
|
+
- **Auth** - Username/password authentication (JWT)
|
|
11
|
+
- **Customer** - Client (PF or PJ) who receives invoices
|
|
12
|
+
- **Contract** - Recurring billing agreement with a plan
|
|
13
|
+
- **Charge** - Individual invoice/boleto generated for payment
|
|
14
|
+
- **Sale** - One-time sale (not recurring)
|
|
15
|
+
- **RecurringSale** - Recurring sale item within a contract
|
|
16
|
+
- **Plan** - Pricing plan with products and periodicities
|
|
17
|
+
- **Product** - Billable item/service
|
|
18
|
+
- **InvoicingMethod** - Payment method configuration (boleto, PIX, credit card)
|
|
19
|
+
- **Person** - Requester (solicitante) linked to a customer
|
|
20
|
+
- **Bill** - Financial bill (conta a pagar)
|
|
21
|
+
- **Supplier** - Supplier with PF/PJ data
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
# Gemfile
|
|
27
|
+
gem 'conexa', '~> 0.0.7'
|
|
28
|
+
|
|
29
|
+
# Or install directly
|
|
30
|
+
gem install conexa
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Configuration
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
Conexa.configure do |config|
|
|
37
|
+
config.api_host = 'https://api.conexa.com.br' # or sandbox URL
|
|
38
|
+
config.api_token = 'your_api_token_here'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Rails: use generator
|
|
42
|
+
rails generate conexa:install
|
|
43
|
+
# Creates config/initializers/conexa.rb
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Convention: snake_case
|
|
47
|
+
|
|
48
|
+
This gem follows Ruby/Rails conventions. Use **snake_case** for all parameters - the gem automatically converts to camelCase for the API.
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
# Correct - snake_case
|
|
52
|
+
Conexa::Customer.create(
|
|
53
|
+
company_id: 3,
|
|
54
|
+
legal_person: { cnpj: '99.557.155/0001-90' }
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# Avoid - camelCase (works but not idiomatic)
|
|
58
|
+
Conexa::Customer.create(
|
|
59
|
+
companyId: 3,
|
|
60
|
+
legalPerson: { cnpj: '99.557.155/0001-90' }
|
|
61
|
+
)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Response attributes are also accessible in snake_case:
|
|
65
|
+
```ruby
|
|
66
|
+
customer = Conexa::Customer.find(127)
|
|
67
|
+
customer.customer_id # => 127
|
|
68
|
+
customer.company_id # => 3
|
|
69
|
+
customer.is_active # => true
|
|
70
|
+
customer.legal_person # => { cnpj: '...' }
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Resources
|
|
74
|
+
|
|
75
|
+
### Auth
|
|
76
|
+
|
|
77
|
+
Authenticates with username/password and returns a JWT token. Does not require a pre-configured `api_token`.
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
# Authenticate
|
|
81
|
+
auth = Conexa::Auth.login(username: 'admin', password: 'secret')
|
|
82
|
+
# or
|
|
83
|
+
auth = Conexa::Auth.authenticate(username: 'admin', password: 'secret')
|
|
84
|
+
|
|
85
|
+
auth.access_token # => "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
|
|
86
|
+
auth.token_type # => "Bearer"
|
|
87
|
+
auth.expires_in # => 28800 (8 hours in seconds)
|
|
88
|
+
auth.user.id # => 1
|
|
89
|
+
auth.user.type # => "admin" or "employee"
|
|
90
|
+
auth.user.name # => "Luke Skywalker"
|
|
91
|
+
|
|
92
|
+
# Use the token for subsequent requests
|
|
93
|
+
Conexa.configure { |c| c.api_token = auth.access_token }
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**API endpoint:** `POST /auth`
|
|
97
|
+
|
|
98
|
+
**Request body:**
|
|
99
|
+
- `username` - Login username (admin login or employee email)
|
|
100
|
+
- `password` - Password
|
|
101
|
+
|
|
102
|
+
**Response attributes:**
|
|
103
|
+
- `user` - User object with `id`, `type`, `name`
|
|
104
|
+
- `token_type` - Always "Bearer"
|
|
105
|
+
- `access_token` - JWT token for subsequent requests
|
|
106
|
+
- `expires_in` - Token expiration in seconds (28800 = 8 hours)
|
|
107
|
+
|
|
108
|
+
**Errors:**
|
|
109
|
+
- `Conexa::ResponseError` - Invalid credentials (401), validation errors (400)
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### Customer
|
|
114
|
+
|
|
115
|
+
Manages clients (pessoas fisicas ou juridicas).
|
|
116
|
+
|
|
117
|
+
```ruby
|
|
118
|
+
# Create customer (Pessoa Juridica)
|
|
119
|
+
customer = Conexa::Customer.create(
|
|
120
|
+
company_id: 3,
|
|
121
|
+
name: 'Empresa ABC Ltda',
|
|
122
|
+
trade_name: 'ABC',
|
|
123
|
+
field_of_activity: 'Tecnologia',
|
|
124
|
+
notes: 'Cliente VIP',
|
|
125
|
+
cell_number: '31999998888',
|
|
126
|
+
phones: ['3133334444', '3144445555'],
|
|
127
|
+
website: 'https://www.abc.com.br',
|
|
128
|
+
has_login_access: true,
|
|
129
|
+
login: 'empresa@abc.com.br',
|
|
130
|
+
password: 'SecurePass123',
|
|
131
|
+
legal_person: {
|
|
132
|
+
cnpj: '99.557.155/0001-90',
|
|
133
|
+
foundation_date: '2020-01-15',
|
|
134
|
+
state_inscription: '123456789',
|
|
135
|
+
municipal_inscription: '98765432'
|
|
136
|
+
},
|
|
137
|
+
address: {
|
|
138
|
+
zip_code: '30130000',
|
|
139
|
+
state: 'MG',
|
|
140
|
+
city: 'Belo Horizonte',
|
|
141
|
+
street: 'Av. Afonso Pena',
|
|
142
|
+
number: '1000',
|
|
143
|
+
neighborhood: 'Centro',
|
|
144
|
+
additional_details: 'Sala 501'
|
|
145
|
+
},
|
|
146
|
+
emails_message: ['contato@abc.com.br'],
|
|
147
|
+
emails_financial_messages: ['financeiro@abc.com.br'],
|
|
148
|
+
default_due_day: 10,
|
|
149
|
+
tax_deductions: {
|
|
150
|
+
iss: 0, ir: 0, pis: 0, inss: 0, csll: 0, cofins: 0
|
|
151
|
+
},
|
|
152
|
+
extra_fields: [
|
|
153
|
+
{ id: 1, value: 'Valor 1' }
|
|
154
|
+
]
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Create customer (Pessoa Fisica)
|
|
158
|
+
customer = Conexa::Customer.create(
|
|
159
|
+
company_id: 3,
|
|
160
|
+
name: 'Joao Silva',
|
|
161
|
+
natural_person: {
|
|
162
|
+
cpf: '123.456.789-00',
|
|
163
|
+
rg: '123456789',
|
|
164
|
+
birth_date: '1990-05-15',
|
|
165
|
+
issuing_authority: 'SSP/MG',
|
|
166
|
+
profession: 'Desenvolvedor',
|
|
167
|
+
marital_status: 'single' # single, married, divorced, widowed, not informed
|
|
168
|
+
}
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# Create customer (Estrangeiro)
|
|
172
|
+
customer = Conexa::Customer.create(
|
|
173
|
+
company_id: 3,
|
|
174
|
+
name: 'John Smith',
|
|
175
|
+
foreign: {
|
|
176
|
+
document: 'ABC123456',
|
|
177
|
+
birth_date: '1985-03-20',
|
|
178
|
+
profession: 'Engineer'
|
|
179
|
+
}
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Find by ID
|
|
183
|
+
customer = Conexa::Customer.find(127)
|
|
184
|
+
customer.name # => "Empresa ABC Ltda"
|
|
185
|
+
customer.customer_id # => 127
|
|
186
|
+
customer.is_active # => true
|
|
187
|
+
customer.address # => Address object or nil
|
|
188
|
+
|
|
189
|
+
# List with filters
|
|
190
|
+
customers = Conexa::Customer.all(
|
|
191
|
+
company_id: [3],
|
|
192
|
+
is_active: true,
|
|
193
|
+
page: 1,
|
|
194
|
+
size: 50
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
# Update
|
|
198
|
+
customer.name = 'Novo Nome'
|
|
199
|
+
customer.save
|
|
200
|
+
|
|
201
|
+
# Delete
|
|
202
|
+
customer.destroy
|
|
203
|
+
# or
|
|
204
|
+
Conexa::Customer.destroy(127)
|
|
205
|
+
|
|
206
|
+
# Sub-resources
|
|
207
|
+
Conexa::Customer.persons(127) # List persons for customer
|
|
208
|
+
Conexa::Customer.contracts(127) # List contracts for customer
|
|
209
|
+
Conexa::Customer.charges(127) # List charges for customer
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**API endpoints:** `POST /customer`, `GET /customer/:id`, `PATCH /customer/:id`, `DELETE /customer/:id`, `GET /customers`
|
|
213
|
+
|
|
214
|
+
**Create/update attributes:**
|
|
215
|
+
- `company_id` - Unit/company ID (required on create)
|
|
216
|
+
- `name` - Full name (required on create)
|
|
217
|
+
- `trade_name` - Trade name (optional)
|
|
218
|
+
- `pronunciation` - Name pronunciation (optional)
|
|
219
|
+
- `field_of_activity` - Field of activity
|
|
220
|
+
- `notes` - General notes
|
|
221
|
+
- `cell_number` - Cell phone number
|
|
222
|
+
- `phones` - Array of phone numbers
|
|
223
|
+
- `website` - Website URL
|
|
224
|
+
- `has_login_access` - Has portal access (boolean)
|
|
225
|
+
- `login` - Login email (when has_login_access is true)
|
|
226
|
+
- `password` - Login password (when has_login_access is true)
|
|
227
|
+
- `legal_person` - PJ data: `cnpj`, `foundation_date`, `state_inscription`, `municipal_inscription`
|
|
228
|
+
- `natural_person` - PF data: `cpf`, `rg`, `birth_date`, `issuing_authority`, `profession`, `marital_status`
|
|
229
|
+
- `foreign` - Foreign data: `document`, `birth_date`, `profession`
|
|
230
|
+
- `address` - Address: `zip_code`, `state`, `city`, `street`, `number`, `neighborhood`, `additional_details`
|
|
231
|
+
- `mailing_address` - Mailing address (same structure as address)
|
|
232
|
+
- `emails_message` - Array of general emails
|
|
233
|
+
- `emails_financial_messages` - Array of financial emails
|
|
234
|
+
- `tags_id` - Array of tag IDs
|
|
235
|
+
- `default_due_day` - Default due day for charges
|
|
236
|
+
- `tax_deductions` - Tax deductions: `iss`, `ir`, `pis`, `inss`, `csll`, `cofins`
|
|
237
|
+
- `extra_fields` - Array of `{ id, value }` for custom fields
|
|
238
|
+
- `automatically_issue_nfse` - Auto-generate NFSe (boolean)
|
|
239
|
+
- `notes_nfse` - NFSe notes
|
|
240
|
+
- `extension_numbers` - Extension numbers
|
|
241
|
+
|
|
242
|
+
**Read-only attributes:**
|
|
243
|
+
- `customer_id` - ID
|
|
244
|
+
- `is_active` - Active status
|
|
245
|
+
- `is_blocked` - Blocked status
|
|
246
|
+
- `is_juridical_person` - Is PJ (legal person)
|
|
247
|
+
- `is_foreign` - Is foreigner
|
|
248
|
+
- `created_at` - Creation timestamp
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
### Contract
|
|
253
|
+
|
|
254
|
+
Manages recurring billing contracts.
|
|
255
|
+
|
|
256
|
+
```ruby
|
|
257
|
+
# Create contract with plan
|
|
258
|
+
contract = Conexa::Contract.create(
|
|
259
|
+
customer_id: 127,
|
|
260
|
+
plan_id: 5,
|
|
261
|
+
start_date: '2024-01-01',
|
|
262
|
+
due_day: 10,
|
|
263
|
+
payment_frequency: 'monthly',
|
|
264
|
+
amount: 500.00,
|
|
265
|
+
seller_id: 1,
|
|
266
|
+
contract_summary: 'Contrato mensal',
|
|
267
|
+
notes: 'Observacoes',
|
|
268
|
+
membership_fee: 100.00,
|
|
269
|
+
generate_sales: true,
|
|
270
|
+
prorata_type: 'proportional',
|
|
271
|
+
nfse_description: 'Servicos de coworking',
|
|
272
|
+
refund: {
|
|
273
|
+
amount: 1000.00,
|
|
274
|
+
date_limit: '2025-01-01',
|
|
275
|
+
is_to_generate_refund_billet: false
|
|
276
|
+
},
|
|
277
|
+
complementary_services: [
|
|
278
|
+
{ product_or_service_id: 100, quantity: 1, amount: 50.00, notes: 'Servico extra' }
|
|
279
|
+
],
|
|
280
|
+
service_correspondence_quotas: {
|
|
281
|
+
limited: true,
|
|
282
|
+
messages_limit: 100,
|
|
283
|
+
price_additional_message: 2.50
|
|
284
|
+
}
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
# Create with custom products (no plan)
|
|
288
|
+
contract = Conexa::Contract.create_with_products(
|
|
289
|
+
customer_id: 127,
|
|
290
|
+
start_date: '2024-01-01',
|
|
291
|
+
payment_day: 10,
|
|
292
|
+
items: [
|
|
293
|
+
{ product_id: 100, quantity: 1, amount: 99.90 },
|
|
294
|
+
{ product_id: 101, quantity: 2, amount: 50.00 }
|
|
295
|
+
]
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
# Find contract
|
|
299
|
+
contract = Conexa::Contract.find(456)
|
|
300
|
+
contract.status # => "active"
|
|
301
|
+
contract.active? # => true
|
|
302
|
+
contract.ended? # => false
|
|
303
|
+
|
|
304
|
+
# List contracts
|
|
305
|
+
contracts = Conexa::Contract.all(
|
|
306
|
+
customer_id: [127],
|
|
307
|
+
status: 'active'
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
# End/terminate contract
|
|
311
|
+
contract.end_contract(date: '2024-12-31', reason_id: 1, unlink_customer: false)
|
|
312
|
+
# or
|
|
313
|
+
Conexa::Contract.end_contract(456, date: '2024-12-31')
|
|
314
|
+
|
|
315
|
+
# Update
|
|
316
|
+
contract.due_day = 15
|
|
317
|
+
contract.save
|
|
318
|
+
|
|
319
|
+
# Delete
|
|
320
|
+
contract.destroy
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**API endpoints:** `POST /contract`, `GET /contract/:id`, `PATCH /contract/:id`, `DELETE /contract/:id`, `PATCH /contract/end/:id`, `GET /contracts`
|
|
324
|
+
|
|
325
|
+
**Create attributes:**
|
|
326
|
+
- `customer_id` - Customer ID (required)
|
|
327
|
+
- `plan_id` - Plan ID (optional, alternative to items)
|
|
328
|
+
- `payment_frequency` - monthly, bimonthly, quarterly, semester, yearly
|
|
329
|
+
- `start_date` - Start date
|
|
330
|
+
- `end_date` - End date (optional)
|
|
331
|
+
- `due_day` - Day of month for billing (1-28)
|
|
332
|
+
- `fidelity_date` - Fidelity end date
|
|
333
|
+
- `amount` - Contract value
|
|
334
|
+
- `discount_value` - Discount value
|
|
335
|
+
- `seller_id` - Seller user ID
|
|
336
|
+
- `contract_summary` - Summary text
|
|
337
|
+
- `notes` - Notes
|
|
338
|
+
- `membership_fee` - Membership fee
|
|
339
|
+
- `generate_sales` - Auto-generate sales (boolean)
|
|
340
|
+
- `prorata_type` - Prorata type
|
|
341
|
+
- `nfse_description` - NFSe description
|
|
342
|
+
- `discount_on_rooms` - Room discount percentage
|
|
343
|
+
- `discount_on_workstation` - Workstation discount percentage
|
|
344
|
+
- `private_space_id` - Private space ID
|
|
345
|
+
- `is_sms_enabled` - SMS notifications (boolean)
|
|
346
|
+
- `refund` - Refund config: `amount`, `date_limit`, `is_to_generate_refund_billet`
|
|
347
|
+
- `complementary_services` - Array of: `product_or_service_id`, `quantity`, `amount`, `notes`
|
|
348
|
+
- `service_correspondence_quotas` - Quotas: `limited`, `messages_limit`, `price_additional_message`
|
|
349
|
+
|
|
350
|
+
**End contract params:**
|
|
351
|
+
- `date` - End date
|
|
352
|
+
- `reason_id` - Reason ID
|
|
353
|
+
- `unlink_customer` - Unlink customer (boolean)
|
|
354
|
+
|
|
355
|
+
**Read-only attributes:**
|
|
356
|
+
- `contract_id` - ID
|
|
357
|
+
- `status` - active, ended, cancelled
|
|
358
|
+
|
|
359
|
+
**Helper methods:**
|
|
360
|
+
- `active?` - Check if active
|
|
361
|
+
- `ended?` - Check if ended or cancelled
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
### Charge
|
|
366
|
+
|
|
367
|
+
Manages invoices/boletos. Charges are created from sales.
|
|
368
|
+
|
|
369
|
+
```ruby
|
|
370
|
+
# Create charge from sales
|
|
371
|
+
charge = Conexa::Charge.create(
|
|
372
|
+
sales_ids: [1234, 1235],
|
|
373
|
+
invoicing_method_id: 1,
|
|
374
|
+
due_date: '2024-02-10',
|
|
375
|
+
notes: 'Cobranca mensal'
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
# Find charge
|
|
379
|
+
charge = Conexa::Charge.find(789)
|
|
380
|
+
charge.status # => "pending"
|
|
381
|
+
charge.amount # => 199.90
|
|
382
|
+
charge.due_date # => "2024-02-10"
|
|
383
|
+
charge.paid? # => false
|
|
384
|
+
charge.pending? # => true
|
|
385
|
+
charge.overdue? # => false
|
|
386
|
+
|
|
387
|
+
# List charges
|
|
388
|
+
charges = Conexa::Charge.all(
|
|
389
|
+
customer_id: [127],
|
|
390
|
+
status: 'pending',
|
|
391
|
+
due_date_from: '2024-01-01',
|
|
392
|
+
due_date_to: '2024-01-31'
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
# Settle (mark as paid)
|
|
396
|
+
charge.settle(
|
|
397
|
+
settlement_date: '2024-02-05',
|
|
398
|
+
paid_amount: 199.90,
|
|
399
|
+
account_id: 1,
|
|
400
|
+
send_email: true,
|
|
401
|
+
receiving_method: { id: 1, installments_quantity: 1 }
|
|
402
|
+
)
|
|
403
|
+
# or
|
|
404
|
+
Conexa::Charge.settle(789, settlement_date: '2024-02-05')
|
|
405
|
+
|
|
406
|
+
# Get PIX QR Code
|
|
407
|
+
pix = charge.pix
|
|
408
|
+
# or
|
|
409
|
+
pix = Conexa::Charge.pix(789)
|
|
410
|
+
|
|
411
|
+
# Send email notification
|
|
412
|
+
charge.send_email
|
|
413
|
+
# or
|
|
414
|
+
Conexa::Charge.send_email(789)
|
|
415
|
+
|
|
416
|
+
# Cancel charge
|
|
417
|
+
charge.cancel
|
|
418
|
+
# or
|
|
419
|
+
Conexa::Charge.cancel(789)
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
**API endpoints:** `POST /charge`, `GET /charge/:id`, `GET /charges`, `PATCH /charge/settle/:id`, `GET /charge/pix/:id`
|
|
423
|
+
|
|
424
|
+
**Create attributes:**
|
|
425
|
+
- `sales_ids` - Array of sale IDs to include in charge
|
|
426
|
+
- `invoicing_method_id` - Payment method ID
|
|
427
|
+
- `due_date` - Due date
|
|
428
|
+
- `notes` - Notes
|
|
429
|
+
|
|
430
|
+
**Settle attributes:**
|
|
431
|
+
- `settlement_date` - Payment date
|
|
432
|
+
- `paid_amount` - Amount paid
|
|
433
|
+
- `account_id` - Bank account ID
|
|
434
|
+
- `send_email` - Send confirmation email (boolean)
|
|
435
|
+
- `receiving_method` - Payment method: `id`, `installments_quantity`
|
|
436
|
+
|
|
437
|
+
**Read-only attributes:**
|
|
438
|
+
- `charge_id` - ID
|
|
439
|
+
- `customer_id` - Customer ID
|
|
440
|
+
- `status` - pending, paid, overdue, cancelled
|
|
441
|
+
- `amount` - Amount due
|
|
442
|
+
- `due_date` - Due date
|
|
443
|
+
- `paid_at` - Payment date
|
|
444
|
+
|
|
445
|
+
**Helper methods:**
|
|
446
|
+
- `paid?` - Check if paid
|
|
447
|
+
- `pending?` - Check if pending
|
|
448
|
+
- `overdue?` - Check if overdue
|
|
449
|
+
|
|
450
|
+
**Special methods:**
|
|
451
|
+
- `settle(params)` / `Charge.settle(id, params)` - Mark as paid
|
|
452
|
+
- `pix` / `Charge.pix(id)` - Get PIX payment data
|
|
453
|
+
- `send_email` / `Charge.send_email(id)` - Send notification
|
|
454
|
+
- `cancel` / `Charge.cancel(id)` - Cancel charge
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
### Sale
|
|
459
|
+
|
|
460
|
+
Manages one-time sales.
|
|
461
|
+
|
|
462
|
+
```ruby
|
|
463
|
+
# Create sale
|
|
464
|
+
sale = Conexa::Sale.create(
|
|
465
|
+
customer_id: 450,
|
|
466
|
+
product_id: 2521,
|
|
467
|
+
requester_id: 10,
|
|
468
|
+
seller_id: 1,
|
|
469
|
+
quantity: 1,
|
|
470
|
+
amount: 80.99,
|
|
471
|
+
reference_date: '2024-01-15',
|
|
472
|
+
notes: 'Venda avulsa'
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
# Find sale
|
|
476
|
+
sale = Conexa::Sale.find(1234)
|
|
477
|
+
sale.status # => "notBilled"
|
|
478
|
+
sale.amount # => 80.99
|
|
479
|
+
sale.editable? # => true
|
|
480
|
+
sale.billed? # => false
|
|
481
|
+
sale.paid? # => false
|
|
482
|
+
|
|
483
|
+
# List sales
|
|
484
|
+
sales = Conexa::Sale.all(
|
|
485
|
+
customer_id: [450],
|
|
486
|
+
status: 'notBilled',
|
|
487
|
+
reference_date_from: '2024-01-01',
|
|
488
|
+
reference_date_to: '2024-01-31'
|
|
489
|
+
)
|
|
490
|
+
|
|
491
|
+
# Update (only if notBilled)
|
|
492
|
+
sale.amount = 90.00
|
|
493
|
+
sale.save
|
|
494
|
+
|
|
495
|
+
# Delete
|
|
496
|
+
sale.destroy
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
**API endpoints:** `POST /sale`, `GET /sale/:id`, `PATCH /sale/:id`, `DELETE /sale/:id`, `GET /sales`
|
|
500
|
+
|
|
501
|
+
**Create/update attributes:**
|
|
502
|
+
- `customer_id` - Customer ID (required)
|
|
503
|
+
- `product_id` - Product ID (required)
|
|
504
|
+
- `requester_id` - Requester (person) ID
|
|
505
|
+
- `seller_id` - Seller (user) ID
|
|
506
|
+
- `quantity` - Quantity (required)
|
|
507
|
+
- `amount` - Amount (required)
|
|
508
|
+
- `reference_date` - Reference date
|
|
509
|
+
- `notes` - Notes
|
|
510
|
+
|
|
511
|
+
**Read-only attributes:**
|
|
512
|
+
- `sale_id` - ID
|
|
513
|
+
- `status` - Status string
|
|
514
|
+
- `original_amount` - Original amount before discount
|
|
515
|
+
- `discount_value` - Discount value
|
|
516
|
+
- `created_at` - Creation timestamp
|
|
517
|
+
- `updated_at` - Update timestamp
|
|
518
|
+
|
|
519
|
+
**Sale statuses:**
|
|
520
|
+
- `notBilled` - Not yet billed (editable)
|
|
521
|
+
- `billed` - Included in a charge
|
|
522
|
+
- `paid` - Paid
|
|
523
|
+
- `cancelled` - Cancelled
|
|
524
|
+
- `deductedFromQuota` - Deducted from quota
|
|
525
|
+
- `billedCancelled` - Billing cancelled
|
|
526
|
+
- `billedNegociated` - Negotiated
|
|
527
|
+
- `partiallyPaid` - Partially paid
|
|
528
|
+
|
|
529
|
+
**Helper methods:**
|
|
530
|
+
- `editable?` - Check if status is notBilled
|
|
531
|
+
- `billed?` - Check if billed
|
|
532
|
+
- `paid?` - Check if paid
|
|
533
|
+
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
### RecurringSale
|
|
537
|
+
|
|
538
|
+
Manages recurring items within contracts.
|
|
539
|
+
|
|
540
|
+
```ruby
|
|
541
|
+
# Create recurring sale
|
|
542
|
+
rs = Conexa::RecurringSale.create(
|
|
543
|
+
customer_id: 127,
|
|
544
|
+
type: 'product', # 'package' or 'product'
|
|
545
|
+
reference_id: 100, # product or package ID
|
|
546
|
+
requester_id: 10,
|
|
547
|
+
seller_id: 1,
|
|
548
|
+
is_repeat: true,
|
|
549
|
+
occurrence_quantity: 12,
|
|
550
|
+
frequency: 'monthly',
|
|
551
|
+
start_date: '2024-01-01',
|
|
552
|
+
quantity: 1,
|
|
553
|
+
amount: 99.90,
|
|
554
|
+
notes: 'Venda recorrente'
|
|
555
|
+
)
|
|
556
|
+
|
|
557
|
+
# Find recurring sale
|
|
558
|
+
rs = Conexa::RecurringSale.find(555)
|
|
559
|
+
|
|
560
|
+
# List recurring sales
|
|
561
|
+
recurring = Conexa::RecurringSale.all(
|
|
562
|
+
contract_id: [456],
|
|
563
|
+
status: 'active'
|
|
564
|
+
)
|
|
565
|
+
|
|
566
|
+
# Update
|
|
567
|
+
rs.amount = 109.90
|
|
568
|
+
rs.save
|
|
569
|
+
|
|
570
|
+
# End recurring sale
|
|
571
|
+
rs.end_recurring_sale(date: '2024-12-31')
|
|
572
|
+
# or
|
|
573
|
+
Conexa::RecurringSale.end_recurring_sale(555, date: '2024-12-31')
|
|
574
|
+
|
|
575
|
+
# Delete
|
|
576
|
+
rs.destroy
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
**API endpoints:** `POST /recurringSale`, `GET /recurringSale/:id`, `PATCH /recurringSale/:id`, `DELETE /recurringSale/:id`, `PATCH /recurringSale/end/:id`, `GET /recurringSales`
|
|
580
|
+
|
|
581
|
+
**Create attributes:**
|
|
582
|
+
- `customer_id` - Customer ID
|
|
583
|
+
- `type` - 'package' or 'product'
|
|
584
|
+
- `reference_id` - Product or package ID
|
|
585
|
+
- `requester_id` - Requester ID
|
|
586
|
+
- `seller_id` - Seller ID
|
|
587
|
+
- `is_repeat` - Is repeating (boolean)
|
|
588
|
+
- `occurrence_quantity` - Number of occurrences
|
|
589
|
+
- `frequency` - Frequency string
|
|
590
|
+
- `start_date` - Start date
|
|
591
|
+
- `last_adjustment_date` - Last price adjustment date
|
|
592
|
+
- `quantity` - Quantity
|
|
593
|
+
- `amount` - Amount
|
|
594
|
+
- `notes` - Notes
|
|
595
|
+
- `is_discount_previous_reservations` - Discount previous reservations (boolean)
|
|
596
|
+
- `is_calculate_pro_rata` - Calculate pro rata (boolean)
|
|
597
|
+
|
|
598
|
+
**Update attributes:**
|
|
599
|
+
- `requester_id`, `amount`, `quantity`, `last_adjustment_date`, `notes`
|
|
600
|
+
|
|
601
|
+
---
|
|
602
|
+
|
|
603
|
+
### Plan
|
|
604
|
+
|
|
605
|
+
Pricing plans with products and periodicities.
|
|
606
|
+
|
|
607
|
+
```ruby
|
|
608
|
+
# Create plan
|
|
609
|
+
plan = Conexa::Plan.create(
|
|
610
|
+
company_id: 1,
|
|
611
|
+
name: 'Plano Basico',
|
|
612
|
+
service_category_id: 1,
|
|
613
|
+
cost_center_id: 10,
|
|
614
|
+
description: 'Plano com todos os recursos',
|
|
615
|
+
membership_fee: 200.00,
|
|
616
|
+
refund_value: 1500.00,
|
|
617
|
+
fidelity_months: 12,
|
|
618
|
+
due_day: 10,
|
|
619
|
+
nfse_description: 'Servicos de coworking',
|
|
620
|
+
receipt_description: 'Recibo mensal',
|
|
621
|
+
discount_on_rooms: 15.5,
|
|
622
|
+
discount_on_workstation: 10.0,
|
|
623
|
+
is_sms_enabled: true,
|
|
624
|
+
payment_periodicities: [
|
|
625
|
+
{ periodicity: 'monthly', amount: 500.00 },
|
|
626
|
+
{ periodicity: 'quarterly', amount: 1400.00 },
|
|
627
|
+
{ periodicity: 'yearly', amount: 5000.00 }
|
|
628
|
+
],
|
|
629
|
+
product_quotas: [
|
|
630
|
+
{ product_id: 100, quantity: 10 },
|
|
631
|
+
{ product_id: 101, quantity: 5 }
|
|
632
|
+
],
|
|
633
|
+
service_correspondence_quotas: {
|
|
634
|
+
limited: true,
|
|
635
|
+
messages_limit: 100,
|
|
636
|
+
price_additional_message: 2.50
|
|
637
|
+
},
|
|
638
|
+
booking_models: [
|
|
639
|
+
{ id: 1, stations: 2 }
|
|
640
|
+
],
|
|
641
|
+
private_space_ids: [10, 11, 12],
|
|
642
|
+
hour_quotas: [
|
|
643
|
+
{ hours: 10, periodicity: 'daily', space_id: 5 },
|
|
644
|
+
{ hours: 40, periodicity: 'weekly', group_id: 3 }
|
|
645
|
+
]
|
|
646
|
+
)
|
|
647
|
+
|
|
648
|
+
# Find plan
|
|
649
|
+
plan = Conexa::Plan.find(5)
|
|
650
|
+
plan.name # => "Plano Basico"
|
|
651
|
+
|
|
652
|
+
# List plans
|
|
653
|
+
plans = Conexa::Plan.all(company_id: [3])
|
|
654
|
+
|
|
655
|
+
# Delete
|
|
656
|
+
plan.destroy
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
**API endpoints:** `POST /plan`, `GET /plan/:id`, `PATCH /plan/:id`, `DELETE /plan/:id`, `GET /plans`
|
|
660
|
+
|
|
661
|
+
**Note:** `save` (update) raises `NoMethodError` in the gem. Use `Conexa::Request` directly if needed.
|
|
662
|
+
|
|
663
|
+
**Create attributes:**
|
|
664
|
+
- `company_id` - Company ID (required)
|
|
665
|
+
- `name` - Plan name (required, must be unique)
|
|
666
|
+
- `service_category_id` - Service category ID (required)
|
|
667
|
+
- `cost_center_id` - Cost center ID
|
|
668
|
+
- `description` - Description
|
|
669
|
+
- `membership_fee` - Membership fee
|
|
670
|
+
- `refund_value` - Refund value
|
|
671
|
+
- `fidelity_months` - Fidelity period in months
|
|
672
|
+
- `due_day` - Default due day
|
|
673
|
+
- `nfse_description` - NFSe description
|
|
674
|
+
- `receipt_description` - Receipt description
|
|
675
|
+
- `discount_on_rooms` - Room discount percentage
|
|
676
|
+
- `discount_on_workstation` - Workstation discount percentage
|
|
677
|
+
- `is_sms_enabled` - SMS enabled (boolean)
|
|
678
|
+
- `payment_periodicities` - Array of: `periodicity` (monthly, bimonthly, quarterly, semester, yearly), `amount`
|
|
679
|
+
- `product_quotas` - Array of: `product_id`, `quantity`
|
|
680
|
+
- `service_correspondence_quotas` - `limited`, `messages_limit`, `price_additional_message`
|
|
681
|
+
- `booking_models` - Array of: `id`, `stations`
|
|
682
|
+
- `private_space_ids` - Array of space IDs
|
|
683
|
+
- `hour_quotas` - Array of: `hours`, `periodicity`, `group_id`, `space_id`
|
|
684
|
+
|
|
685
|
+
---
|
|
686
|
+
|
|
687
|
+
### Product
|
|
688
|
+
|
|
689
|
+
Read-only resource for billable products/services.
|
|
690
|
+
|
|
691
|
+
```ruby
|
|
692
|
+
# Find product
|
|
693
|
+
product = Conexa::Product.find(100)
|
|
694
|
+
product.name # => "Mensalidade"
|
|
695
|
+
|
|
696
|
+
# List products
|
|
697
|
+
products = Conexa::Product.all(company_id: [3])
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
**API endpoints:** `GET /product/:id`, `GET /products`
|
|
701
|
+
|
|
702
|
+
**Note:** Products cannot be created/updated via this gem. `save` raises `NoMethodError`.
|
|
703
|
+
|
|
704
|
+
---
|
|
705
|
+
|
|
706
|
+
### InvoicingMethod
|
|
707
|
+
|
|
708
|
+
Manages payment method configurations (boleto, PIX, credit card, etc.).
|
|
709
|
+
|
|
710
|
+
```ruby
|
|
711
|
+
# Find invoicing method
|
|
712
|
+
method = Conexa::InvoicingMethod.find(1)
|
|
713
|
+
method.invoicing_method_id # => 1
|
|
714
|
+
|
|
715
|
+
# List invoicing methods
|
|
716
|
+
methods = Conexa::InvoicingMethod.all
|
|
717
|
+
|
|
718
|
+
# Create
|
|
719
|
+
method = Conexa::InvoicingMethod.create(
|
|
720
|
+
name: 'Boleto Bancario'
|
|
721
|
+
)
|
|
722
|
+
|
|
723
|
+
# Update
|
|
724
|
+
method.save
|
|
725
|
+
|
|
726
|
+
# Delete
|
|
727
|
+
method.destroy
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
**API endpoints:** `GET /invoicingMethod/:id`, `GET /invoicingMethods`, `POST /invoicingMethod`, `PATCH /invoicingMethod/:id`, `DELETE /invoicingMethod/:id`
|
|
731
|
+
|
|
732
|
+
---
|
|
733
|
+
|
|
734
|
+
### Bill
|
|
735
|
+
|
|
736
|
+
Financial bills (contas a pagar).
|
|
737
|
+
|
|
738
|
+
```ruby
|
|
739
|
+
# Create bill
|
|
740
|
+
bill = Conexa::Bill.create(
|
|
741
|
+
company_id: 1,
|
|
742
|
+
due_date: '2024-03-15',
|
|
743
|
+
amount: 500.00,
|
|
744
|
+
subcategory_id: 1,
|
|
745
|
+
supplier_id: 50,
|
|
746
|
+
description: 'Aluguel escritorio',
|
|
747
|
+
account_id: 1,
|
|
748
|
+
document_date: '2024-03-01',
|
|
749
|
+
competence_date: '2024-03-01',
|
|
750
|
+
document_number: 'NF-001',
|
|
751
|
+
digitable_line: '23793.38128 60000.000003 00000.000400 1 84340000050000',
|
|
752
|
+
cost_centers: [
|
|
753
|
+
{ id: 1, percentage: 100 }
|
|
754
|
+
],
|
|
755
|
+
cac: { is_included: true, percentage: 5.0 }
|
|
756
|
+
)
|
|
757
|
+
|
|
758
|
+
# Find bill
|
|
759
|
+
bill = Conexa::Bill.find(321)
|
|
760
|
+
|
|
761
|
+
# List bills
|
|
762
|
+
bills = Conexa::Bill.all(company_id: [3])
|
|
763
|
+
```
|
|
764
|
+
|
|
765
|
+
**API endpoints:** `POST /bill`, `GET /bill/:id`, `GET /bills`
|
|
766
|
+
|
|
767
|
+
**Note:** `save` (update) raises `NoMethodError` in the gem.
|
|
768
|
+
|
|
769
|
+
**Create attributes:**
|
|
770
|
+
- `company_id` - Company ID
|
|
771
|
+
- `due_date` - Due date
|
|
772
|
+
- `amount` - Amount
|
|
773
|
+
- `subcategory_id` - Subcategory ID
|
|
774
|
+
- `supplier_id` - Supplier ID
|
|
775
|
+
- `description` - Description
|
|
776
|
+
- `account_id` - Bank account ID
|
|
777
|
+
- `document_date` - Document date
|
|
778
|
+
- `competence_date` - Competence date
|
|
779
|
+
- `document_number` - Document number
|
|
780
|
+
- `digitable_line` - Barcode digitable line
|
|
781
|
+
- `cost_centers` - Array of: `id`, `percentage`
|
|
782
|
+
- `cac` - CAC config: `is_included`, `percentage`
|
|
783
|
+
|
|
784
|
+
---
|
|
785
|
+
|
|
786
|
+
### Company
|
|
787
|
+
|
|
788
|
+
Manages units/companies within the account.
|
|
789
|
+
|
|
790
|
+
```ruby
|
|
791
|
+
# Find company
|
|
792
|
+
company = Conexa::Company.find(3)
|
|
793
|
+
|
|
794
|
+
# List companies
|
|
795
|
+
companies = Conexa::Company.all
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
**API endpoints:** `GET /company/:id`, `GET /companies`
|
|
799
|
+
|
|
800
|
+
---
|
|
801
|
+
|
|
802
|
+
### Supplier
|
|
803
|
+
|
|
804
|
+
Manages suppliers (fornecedores) with PF/PJ data.
|
|
805
|
+
|
|
806
|
+
```ruby
|
|
807
|
+
# Create supplier (PJ)
|
|
808
|
+
supplier = Conexa::Supplier.create(
|
|
809
|
+
name: 'Fornecedor XYZ Ltda',
|
|
810
|
+
field_of_activity: 'Servicos',
|
|
811
|
+
notes: 'Fornecedor principal',
|
|
812
|
+
cell_number: '31999998888',
|
|
813
|
+
phones: ['3133334444'],
|
|
814
|
+
emails: ['contato@xyz.com.br'],
|
|
815
|
+
website: 'https://www.xyz.com.br',
|
|
816
|
+
contact_person_names: ['Joao', 'Maria'],
|
|
817
|
+
legal_person: {
|
|
818
|
+
legal_name: 'Fornecedor XYZ Servicos Ltda',
|
|
819
|
+
cnpj: '12.345.678/0001-90',
|
|
820
|
+
state_inscription: '123456789',
|
|
821
|
+
municipal_inscription: '98765432'
|
|
822
|
+
},
|
|
823
|
+
address: {
|
|
824
|
+
zip_code: '30130000',
|
|
825
|
+
state: 'MG',
|
|
826
|
+
city: 'Belo Horizonte',
|
|
827
|
+
street: 'Rua da Bahia',
|
|
828
|
+
number: '500',
|
|
829
|
+
neighborhood: 'Centro',
|
|
830
|
+
additional_details: 'Sala 10'
|
|
831
|
+
}
|
|
832
|
+
)
|
|
833
|
+
|
|
834
|
+
# Create supplier (PF)
|
|
835
|
+
supplier = Conexa::Supplier.create(
|
|
836
|
+
name: 'Joao Fornecedor',
|
|
837
|
+
natural_person: {
|
|
838
|
+
cpf: '123.456.789-00',
|
|
839
|
+
rg: '123456789',
|
|
840
|
+
issuing_authority: 'SSP/MG'
|
|
841
|
+
}
|
|
842
|
+
)
|
|
843
|
+
|
|
844
|
+
# Find supplier
|
|
845
|
+
supplier = Conexa::Supplier.find(50)
|
|
846
|
+
|
|
847
|
+
# List suppliers
|
|
848
|
+
suppliers = Conexa::Supplier.all(company_id: [3])
|
|
849
|
+
|
|
850
|
+
# Update
|
|
851
|
+
supplier.name = 'Novo Nome'
|
|
852
|
+
supplier.save
|
|
853
|
+
|
|
854
|
+
# Delete
|
|
855
|
+
supplier.destroy
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
**API endpoints:** `POST /supplier`, `GET /supplier/:id`, `PATCH /supplier/:id`, `DELETE /supplier/:id`, `GET /supplier` (list)
|
|
859
|
+
|
|
860
|
+
**Create attributes:**
|
|
861
|
+
- `name` - Supplier name (required)
|
|
862
|
+
- `field_of_activity` - Field of activity
|
|
863
|
+
- `notes` - Notes
|
|
864
|
+
- `cell_number` - Cell phone
|
|
865
|
+
- `phones` - Array of phones
|
|
866
|
+
- `emails` - Array of emails
|
|
867
|
+
- `website` - Website URL
|
|
868
|
+
- `contact_person_names` - Array of contact names
|
|
869
|
+
- `legal_person` - PJ data: `legal_name`, `cnpj`, `state_inscription`, `municipal_inscription`
|
|
870
|
+
- `natural_person` - PF data: `cpf`, `rg`, `issuing_authority`
|
|
871
|
+
- `address` - Address: `zip_code`, `state`, `city`, `street`, `number`, `neighborhood`, `additional_details`
|
|
872
|
+
|
|
873
|
+
---
|
|
874
|
+
|
|
875
|
+
### CreditCard
|
|
876
|
+
|
|
877
|
+
Manages customer credit cards.
|
|
878
|
+
|
|
879
|
+
```ruby
|
|
880
|
+
# Create credit card
|
|
881
|
+
card = Conexa::CreditCard.create(
|
|
882
|
+
customer_id: 127,
|
|
883
|
+
number: '4111111111111111',
|
|
884
|
+
name: 'JOAO DA SILVA',
|
|
885
|
+
expiration_date: '12/2026',
|
|
886
|
+
cvc: '123',
|
|
887
|
+
brand: 'visa',
|
|
888
|
+
default: true,
|
|
889
|
+
enable_recurring: true
|
|
890
|
+
)
|
|
891
|
+
|
|
892
|
+
# Find credit card
|
|
893
|
+
card = Conexa::CreditCard.find(99)
|
|
894
|
+
|
|
895
|
+
# Update
|
|
896
|
+
card.default = true
|
|
897
|
+
card.save
|
|
898
|
+
|
|
899
|
+
# Delete
|
|
900
|
+
card.destroy
|
|
901
|
+
```
|
|
902
|
+
|
|
903
|
+
**API endpoints:** `POST /creditCard`, `GET /creditCard/:id`, `PATCH /creditCard/:id`, `DELETE /creditCard/:id`
|
|
904
|
+
|
|
905
|
+
**Note:** `all` (listing) is not available for credit cards.
|
|
906
|
+
|
|
907
|
+
**Create attributes:**
|
|
908
|
+
- `customer_id` - Customer ID (required)
|
|
909
|
+
- `number` - Card number
|
|
910
|
+
- `name` - Cardholder name
|
|
911
|
+
- `expiration_date` - Expiration date (MM/YYYY)
|
|
912
|
+
- `cvc` - CVC code
|
|
913
|
+
- `brand` - Card brand
|
|
914
|
+
- `default` - Set as default (boolean)
|
|
915
|
+
- `enable_recurring` - Enable for recurring charges (boolean)
|
|
916
|
+
|
|
917
|
+
---
|
|
918
|
+
|
|
919
|
+
### Person
|
|
920
|
+
|
|
921
|
+
Manages requesters (solicitantes) linked to a customer. The API supports full CRUD.
|
|
922
|
+
|
|
923
|
+
```ruby
|
|
924
|
+
# Create person for customer
|
|
925
|
+
person = Conexa::Person.create(
|
|
926
|
+
customer_id: 127,
|
|
927
|
+
name: 'Maria Solicitante',
|
|
928
|
+
nationality: 'Brasileira',
|
|
929
|
+
place_of_birth: 'Belo Horizonte',
|
|
930
|
+
marital_status: 'single',
|
|
931
|
+
is_foreign: false,
|
|
932
|
+
is_company_partner: true,
|
|
933
|
+
is_guarantor: false,
|
|
934
|
+
cpf: '123.456.789-00',
|
|
935
|
+
rg: '123456789',
|
|
936
|
+
issuing_authority: 'SSP/MG',
|
|
937
|
+
birth_date: '1990-05-15',
|
|
938
|
+
cell_number: '31999998888',
|
|
939
|
+
phones: ['3133334444'],
|
|
940
|
+
emails: ['maria@empresa.com'],
|
|
941
|
+
sex: 'female',
|
|
942
|
+
job_title: 'Gerente',
|
|
943
|
+
profession: 'Administradora',
|
|
944
|
+
resume: 'Profissional experiente',
|
|
945
|
+
notes: 'Contato principal',
|
|
946
|
+
address: {
|
|
947
|
+
zip_code: '30130000',
|
|
948
|
+
state: 'MG',
|
|
949
|
+
city: 'Belo Horizonte',
|
|
950
|
+
street: 'Av. Afonso Pena',
|
|
951
|
+
number: '1000',
|
|
952
|
+
neighborhood: 'Centro',
|
|
953
|
+
additional_details: 'Sala 501'
|
|
954
|
+
},
|
|
955
|
+
devices: [
|
|
956
|
+
{ nickname: 'Notebook', mac_address: 'AA:BB:CC:DD:EE:FF' }
|
|
957
|
+
],
|
|
958
|
+
has_login_access: true,
|
|
959
|
+
login: 'maria@empresa.com',
|
|
960
|
+
password: 'SecurePass123',
|
|
961
|
+
permissions: ['finance', 'orders', 'rooms'],
|
|
962
|
+
can_receive_mail: true,
|
|
963
|
+
color: '#FF5733',
|
|
964
|
+
url_linkedin: 'https://linkedin.com/in/maria',
|
|
965
|
+
url_instagram: '@maria',
|
|
966
|
+
url_facebook: 'maria.fb',
|
|
967
|
+
url_twitter: '@maria'
|
|
968
|
+
)
|
|
969
|
+
|
|
970
|
+
# Update
|
|
971
|
+
person.name = 'Maria Silva'
|
|
972
|
+
person.save
|
|
973
|
+
|
|
974
|
+
# Delete
|
|
975
|
+
person.destroy
|
|
976
|
+
```
|
|
977
|
+
|
|
978
|
+
**API endpoints:** `POST /person`, `GET /person/:id`, `PATCH /person/:id`, `DELETE /person/:id`, `GET /persons`
|
|
979
|
+
|
|
980
|
+
**Note:** In the gem, `find`, `all`, and `find_by` raise `NoMethodError`. Use `Conexa::Request` directly if you need to retrieve or list persons.
|
|
981
|
+
|
|
982
|
+
**Create/update attributes:**
|
|
983
|
+
- `customer_id` - Customer ID (required)
|
|
984
|
+
- `name` - Full name (required)
|
|
985
|
+
- `nationality` - Nationality
|
|
986
|
+
- `place_of_birth` - Place of birth
|
|
987
|
+
- `marital_status` - Marital status
|
|
988
|
+
- `is_foreign` - Is foreigner (boolean)
|
|
989
|
+
- `foreign_data` - Foreign data object
|
|
990
|
+
- `is_company_partner` - Is company partner (boolean)
|
|
991
|
+
- `is_guarantor` - Is guarantor (boolean)
|
|
992
|
+
- `cpf` - CPF number
|
|
993
|
+
- `rg` - RG number
|
|
994
|
+
- `issuing_authority` - RG issuing authority
|
|
995
|
+
- `birth_date` - Birth date
|
|
996
|
+
- `cell_number` - Cell phone
|
|
997
|
+
- `phones` - Array of phones
|
|
998
|
+
- `emails` - Array of emails
|
|
999
|
+
- `sex` - Gender (male, female)
|
|
1000
|
+
- `job_title` - Job title
|
|
1001
|
+
- `profession` - Profession
|
|
1002
|
+
- `resume` - Resume/bio
|
|
1003
|
+
- `notes` - Notes
|
|
1004
|
+
- `address` - Address object
|
|
1005
|
+
- `devices` - Array of: `nickname`, `mac_address`
|
|
1006
|
+
- `has_login_access` - Has portal access (boolean)
|
|
1007
|
+
- `login` - Login email
|
|
1008
|
+
- `password` - Login password
|
|
1009
|
+
- `permissions` - Array of: finance, orders, rooms, shared_spaces, assistance, correspondences, printing
|
|
1010
|
+
- `access_id` - Access ID
|
|
1011
|
+
- `can_receive_mail` - Can receive mail (boolean)
|
|
1012
|
+
- `color` - Color code
|
|
1013
|
+
- `print_fee_id` - Print fee ID
|
|
1014
|
+
- `extension_numbers` - Extension numbers
|
|
1015
|
+
- `url_linkedin`, `url_instagram`, `url_facebook`, `url_twitter` - Social URLs
|
|
1016
|
+
|
|
1017
|
+
---
|
|
1018
|
+
|
|
1019
|
+
## Common Patterns
|
|
1020
|
+
|
|
1021
|
+
### Pagination
|
|
1022
|
+
|
|
1023
|
+
All `#all` and `#find_by` methods support pagination:
|
|
1024
|
+
|
|
1025
|
+
```ruby
|
|
1026
|
+
# Page 1, 50 items per page
|
|
1027
|
+
result = Conexa::Customer.all(page: 1, size: 50)
|
|
1028
|
+
|
|
1029
|
+
result.data # => Array of customers
|
|
1030
|
+
result.pagination # => { "page" => 1, "size" => 50, "total" => 150 }
|
|
1031
|
+
result.empty? # => false
|
|
1032
|
+
|
|
1033
|
+
# Iterate all pages
|
|
1034
|
+
page = 1
|
|
1035
|
+
loop do
|
|
1036
|
+
result = Conexa::Customer.all(page: page, size: 100)
|
|
1037
|
+
break if result.empty?
|
|
1038
|
+
|
|
1039
|
+
result.each { |customer| process(customer) }
|
|
1040
|
+
page += 1
|
|
1041
|
+
end
|
|
1042
|
+
```
|
|
1043
|
+
|
|
1044
|
+
### Result Object
|
|
1045
|
+
|
|
1046
|
+
API calls return `Conexa::Result` objects:
|
|
1047
|
+
|
|
1048
|
+
```ruby
|
|
1049
|
+
result = Conexa::Customer.all
|
|
1050
|
+
result.data # Array of objects
|
|
1051
|
+
result.pagination # Pagination info
|
|
1052
|
+
result.empty? # Check if no results
|
|
1053
|
+
result.each { } # Iterate (delegates to data)
|
|
1054
|
+
result.first # First item
|
|
1055
|
+
result.count # Number of items
|
|
1056
|
+
```
|
|
1057
|
+
|
|
1058
|
+
### Error Handling
|
|
1059
|
+
|
|
1060
|
+
```ruby
|
|
1061
|
+
begin
|
|
1062
|
+
customer = Conexa::Customer.find(999999)
|
|
1063
|
+
rescue Conexa::NotFound => e
|
|
1064
|
+
puts "Customer not found: #{e.message}"
|
|
1065
|
+
rescue Conexa::ValidationError => e
|
|
1066
|
+
puts "Validation failed: #{e.errors}"
|
|
1067
|
+
rescue Conexa::ConnectionError => e
|
|
1068
|
+
puts "Connection failed: #{e.message}"
|
|
1069
|
+
rescue Conexa::ResponseError => e
|
|
1070
|
+
puts "API error: #{e.message}"
|
|
1071
|
+
end
|
|
1072
|
+
```
|
|
1073
|
+
|
|
1074
|
+
**Error classes:**
|
|
1075
|
+
- `Conexa::NotFound` - Resource not found (404)
|
|
1076
|
+
- `Conexa::ValidationError` - Validation failed (response without `message` key)
|
|
1077
|
+
- `Conexa::ResponseError` - API error with `message` key (400, 401, 422, 500)
|
|
1078
|
+
- `Conexa::ConnectionError` - Network error
|
|
1079
|
+
- `Conexa::RequestError` - Invalid request parameters (e.g., nil ID)
|
|
1080
|
+
- `Conexa::MissingCredentialsError` - Token not configured
|
|
1081
|
+
|
|
1082
|
+
### Filters
|
|
1083
|
+
|
|
1084
|
+
Common filter parameters across resources:
|
|
1085
|
+
|
|
1086
|
+
```ruby
|
|
1087
|
+
# Date ranges
|
|
1088
|
+
Conexa::Charge.all(
|
|
1089
|
+
due_date_from: '2024-01-01',
|
|
1090
|
+
due_date_to: '2024-01-31'
|
|
1091
|
+
)
|
|
1092
|
+
|
|
1093
|
+
# Multiple IDs
|
|
1094
|
+
Conexa::Customer.all(company_id: [1, 2, 3])
|
|
1095
|
+
|
|
1096
|
+
# Status filters
|
|
1097
|
+
Conexa::Contract.all(status: 'active')
|
|
1098
|
+
Conexa::Sale.all(status: 'notBilled')
|
|
1099
|
+
|
|
1100
|
+
# Combined
|
|
1101
|
+
Conexa::Charge.all(
|
|
1102
|
+
customer_id: [127],
|
|
1103
|
+
status: 'pending',
|
|
1104
|
+
due_date_from: '2024-01-01',
|
|
1105
|
+
page: 1,
|
|
1106
|
+
size: 100
|
|
1107
|
+
)
|
|
1108
|
+
```
|
|
1109
|
+
|
|
1110
|
+
### Rate Limiting
|
|
1111
|
+
|
|
1112
|
+
The API enforces a limit of 100 requests per minute. Response headers:
|
|
1113
|
+
- `X-Rate-Limit-Limit` - Maximum requests per minute
|
|
1114
|
+
- `X-Rate-Limit-Remaining` - Remaining requests
|
|
1115
|
+
- `X-Rate-Limit-Reset` - Seconds until limit resets
|
|
1116
|
+
|
|
1117
|
+
---
|
|
1118
|
+
|
|
1119
|
+
## Model Methods Summary
|
|
1120
|
+
|
|
1121
|
+
| Resource | find | all | create | save | destroy | Special Methods |
|
|
1122
|
+
|----------|------|-----|--------|------|---------|-----------------|
|
|
1123
|
+
| Auth | - | - | - | - | - | login, authenticate |
|
|
1124
|
+
| Customer | yes | yes | yes | yes | yes | persons, contracts, charges |
|
|
1125
|
+
| Contract | yes | yes | yes | yes | yes | end_contract, create_with_products |
|
|
1126
|
+
| Charge | yes | yes | yes | - | - | settle, pix, cancel, send_email |
|
|
1127
|
+
| Sale | yes | yes | yes | yes | yes | billed?, paid?, editable? |
|
|
1128
|
+
| RecurringSale | yes | yes | yes | yes | yes | end_recurring_sale |
|
|
1129
|
+
| Plan | yes | yes | yes | - | yes | - |
|
|
1130
|
+
| Product | yes | yes | - | - | - | - |
|
|
1131
|
+
| InvoicingMethod | yes | yes | yes | yes | yes | - |
|
|
1132
|
+
| Bill | yes | yes | yes | - | - | - |
|
|
1133
|
+
| Company | yes | yes | yes | yes | yes | - |
|
|
1134
|
+
| Supplier | yes | yes | yes | yes | yes | - |
|
|
1135
|
+
| CreditCard | yes | - | yes | yes | yes | - |
|
|
1136
|
+
| Person | - | - | yes | yes | yes | - |
|
|
1137
|
+
|
|
1138
|
+
**Legend:** `yes` = available, `-` = not available (raises NoMethodError or not implemented)
|
|
1139
|
+
|
|
1140
|
+
---
|
|
1141
|
+
|
|
1142
|
+
## Version History
|
|
1143
|
+
|
|
1144
|
+
- **v0.0.7** - Add Auth resource, fix Auth.login, add test suite with VCR
|
|
1145
|
+
- **v0.0.6** - Fix nil guard in camelize_hash, fix Result#empty? delegation
|
|
1146
|
+
- **v0.0.5** - Initial public release
|
|
1147
|
+
|
|
1148
|
+
## Links
|
|
1149
|
+
|
|
1150
|
+
- **RubyGems:** https://rubygems.org/gems/conexa
|
|
1151
|
+
- **GitHub:** https://github.com/guilhermegazzinelli/conexa-ruby
|
|
1152
|
+
- **Conexa API Docs:** https://documenter.getpostman.com/view/25182821/2s93RZMpcB
|