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/lib/conexa/authenticator.rb
CHANGED
data/lib/conexa/model.rb
CHANGED
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
module Conexa
|
|
2
|
+
# Base class for all API resources (Customer, Charge, Contract, etc.)
|
|
3
|
+
#
|
|
4
|
+
# == Attribute Access
|
|
5
|
+
#
|
|
6
|
+
# Attributes are automatically accessible via method_missing:
|
|
7
|
+
# customer.name # => "Empresa ABC"
|
|
8
|
+
# customer.company_id # => 3
|
|
9
|
+
# customer.is_active # => true
|
|
10
|
+
#
|
|
11
|
+
# The API returns camelCase (companyId), ConexaObject converts to snake_case
|
|
12
|
+
# (company_id), and method_missing handles the lookup transparently.
|
|
13
|
+
#
|
|
14
|
+
# == Primary Key
|
|
15
|
+
#
|
|
16
|
+
# Each resource needs primary_key_attribute for :id alias and operations
|
|
17
|
+
# that require the resource ID (destroy, save, fetch, etc.):
|
|
18
|
+
#
|
|
19
|
+
# class Charge < Model
|
|
20
|
+
# primary_key_attribute :charge_id
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# charge.id # => 123 (alias for charge_id)
|
|
24
|
+
# charge.charge_id # => 123
|
|
25
|
+
# charge.chargeId # => 123 (camelCase alias for backwards compat)
|
|
26
|
+
#
|
|
27
|
+
# == Why explicit primary_key_attribute?
|
|
28
|
+
#
|
|
29
|
+
# The default primary_key_name generates "classname_id" (e.g., "charge_id"),
|
|
30
|
+
# but compound names like RecurringSale would generate "recurringsale_id"
|
|
31
|
+
# instead of "recurring_sale_id". Explicit declaration ensures correctness.
|
|
32
|
+
#
|
|
2
33
|
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
|
+
|
|
3
51
|
def create
|
|
4
52
|
set_primary_key Conexa::Request.post(self.class.show_url, params: to_hash).call(class_name).attributes['id']
|
|
5
53
|
fetch
|
|
@@ -29,7 +77,7 @@ module Conexa
|
|
|
29
77
|
end
|
|
30
78
|
|
|
31
79
|
def primary_key_name
|
|
32
|
-
class_name
|
|
80
|
+
Util.to_snake_case(class_name) + "_id"
|
|
33
81
|
end
|
|
34
82
|
|
|
35
83
|
def class_name
|
|
@@ -39,6 +87,7 @@ module Conexa
|
|
|
39
87
|
def destroy
|
|
40
88
|
raise RequestError.new('Invalid ID') unless id.present?
|
|
41
89
|
update Conexa::Request.delete( self.class.show_url(primary_key) ).call(class_name)
|
|
90
|
+
self
|
|
42
91
|
end
|
|
43
92
|
|
|
44
93
|
class << self
|
|
@@ -68,7 +117,9 @@ module Conexa
|
|
|
68
117
|
alias :where :all
|
|
69
118
|
|
|
70
119
|
def destroy id
|
|
71
|
-
self.new
|
|
120
|
+
instance = self.new
|
|
121
|
+
instance.set_primary_key(id)
|
|
122
|
+
instance.destroy
|
|
72
123
|
end
|
|
73
124
|
|
|
74
125
|
def url(*params)
|
data/lib/conexa/object.rb
CHANGED
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
module Conexa
|
|
2
|
+
# Base class for all Conexa objects with dynamic attribute access
|
|
3
|
+
#
|
|
4
|
+
# == Attribute Access via method_missing
|
|
5
|
+
#
|
|
6
|
+
# Attributes can be accessed using either snake_case or camelCase:
|
|
7
|
+
# customer.company_id # => 3
|
|
8
|
+
# customer.companyId # => 3 (converted to snake_case internally)
|
|
9
|
+
#
|
|
10
|
+
# The API returns camelCase attributes which are stored as snake_case.
|
|
11
|
+
# method_missing automatically converts any camelCase calls to snake_case.
|
|
12
|
+
#
|
|
13
|
+
# == Attribute Assignment
|
|
14
|
+
#
|
|
15
|
+
# Attributes can be set using snake_case:
|
|
16
|
+
# customer.name = "New Name"
|
|
17
|
+
# customer.save
|
|
18
|
+
#
|
|
2
19
|
class ConexaObject
|
|
3
20
|
attr_reader :attributes
|
|
4
21
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Conexa
|
|
4
|
+
# Represents an address object (embedded in Customer, etc.)
|
|
5
|
+
# Not a standalone API resource - used for serialization/deserialization
|
|
6
|
+
class Address < ConexaObject
|
|
7
|
+
# @return [String, nil] CEP/ZIP code
|
|
8
|
+
# @return [String, nil] Street name
|
|
9
|
+
# @return [String, nil] Street number
|
|
10
|
+
# @return [String, nil] Neighborhood
|
|
11
|
+
# @return [String, nil] City
|
|
12
|
+
# @return [String, nil] State abbreviation (UF)
|
|
13
|
+
# @return [String, nil] Country (for foreigners)
|
|
14
|
+
# @return [String, nil] Additional details (complement)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Conexa
|
|
4
|
+
# Authentication resource for username/password authentication
|
|
5
|
+
#
|
|
6
|
+
# @example Authenticate with credentials
|
|
7
|
+
# auth = Conexa::Auth.login(username: 'admin', password: 'secret')
|
|
8
|
+
# auth.access_token # => "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
|
|
9
|
+
# auth.expires_in # => 28800
|
|
10
|
+
#
|
|
11
|
+
# @note For most cases, use Application Token instead (configured in Conexa.configure)
|
|
12
|
+
class Auth < ConexaObject
|
|
13
|
+
class << self
|
|
14
|
+
# Authenticate with username and password
|
|
15
|
+
#
|
|
16
|
+
# @param username [String] Login username (admin or employee email)
|
|
17
|
+
# @param password [String] Password
|
|
18
|
+
# @return [Auth] Authentication result with access_token
|
|
19
|
+
# @raise [Conexa::AuthenticationError] if credentials are invalid
|
|
20
|
+
#
|
|
21
|
+
# @example
|
|
22
|
+
# auth = Conexa::Auth.login(username: 'admin', password: 'mypassword')
|
|
23
|
+
# # Use the token for subsequent requests
|
|
24
|
+
# Conexa.configure { |c| c.api_token = auth.access_token }
|
|
25
|
+
def login(username:, password:)
|
|
26
|
+
Conexa::Request.auth('/auth', params: {
|
|
27
|
+
username: username,
|
|
28
|
+
password: password
|
|
29
|
+
}).call('auth')
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
alias_method :authenticate, :login
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# All attributes (user, token_type, access_token, expires_in)
|
|
36
|
+
# are accessible via method_missing
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -1,31 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Conexa
|
|
4
|
+
# Charge resource for billing/invoices
|
|
5
|
+
#
|
|
6
|
+
# @example Retrieve a charge
|
|
7
|
+
# charge = Conexa::Charge.find(789)
|
|
8
|
+
# charge.status # => "pending"
|
|
9
|
+
#
|
|
10
|
+
# @example List charges
|
|
11
|
+
# charges = Conexa::Charge.all(customer_id: [127], status: 'pending')
|
|
12
|
+
#
|
|
13
|
+
# @example Settle (pay) a charge
|
|
14
|
+
# Conexa::Charge.settle(789)
|
|
15
|
+
#
|
|
16
|
+
# @!attribute [r] charge_id
|
|
17
|
+
# @return [Integer] Charge ID (also accessible as #id)
|
|
18
|
+
# @!attribute [r] customer_id
|
|
19
|
+
# @return [Integer] Customer ID
|
|
20
|
+
# @!attribute [r] status
|
|
21
|
+
# @return [String] Status: pending, paid, overdue, cancelled
|
|
22
|
+
# @!attribute [r] amount
|
|
23
|
+
# @return [Float] Charge amount
|
|
24
|
+
# @!attribute [r] due_date
|
|
25
|
+
# @return [String] Due date
|
|
26
|
+
# @!attribute [r] paid_at
|
|
27
|
+
# @return [String, nil] Payment date
|
|
28
|
+
#
|
|
2
29
|
class Charge < Model
|
|
3
|
-
|
|
4
|
-
|
|
30
|
+
primary_key_attribute :charge_id
|
|
31
|
+
|
|
32
|
+
# Check if charge is paid
|
|
33
|
+
# @return [Boolean]
|
|
34
|
+
def paid?
|
|
35
|
+
status == 'paid'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Check if charge is pending
|
|
39
|
+
# @return [Boolean]
|
|
40
|
+
def pending?
|
|
41
|
+
status == 'pending'
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Check if charge is overdue
|
|
45
|
+
# @return [Boolean]
|
|
46
|
+
def overdue?
|
|
47
|
+
status == 'overdue'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Settle (pay) this charge
|
|
51
|
+
# @param params [Hash] optional payment details
|
|
5
52
|
# @return [self]
|
|
6
53
|
def settle(params = {})
|
|
7
54
|
Conexa::Request.post(self.class.show_url("settle", primary_key), params: params).call(class_name)
|
|
8
55
|
self
|
|
9
56
|
end
|
|
10
57
|
|
|
11
|
-
# Get PIX QR Code for
|
|
12
|
-
# @return [ConexaObject] PIX data including
|
|
58
|
+
# Get PIX QR Code for this charge
|
|
59
|
+
# @return [ConexaObject] PIX data including qr_code and qr_code_base64
|
|
13
60
|
def pix
|
|
14
61
|
Conexa::Request.get(self.class.show_url("pix", primary_key)).call("pix")
|
|
15
62
|
end
|
|
16
63
|
|
|
64
|
+
# Cancel this charge
|
|
65
|
+
# @return [self]
|
|
66
|
+
def cancel
|
|
67
|
+
Conexa::Request.post(self.class.show_url("cancel", primary_key)).call(class_name)
|
|
68
|
+
self
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Send charge notification by email
|
|
72
|
+
# @return [self]
|
|
73
|
+
def send_email
|
|
74
|
+
Conexa::Request.post(self.class.show_url("sendEmail", primary_key)).call(class_name)
|
|
75
|
+
self
|
|
76
|
+
end
|
|
77
|
+
|
|
17
78
|
class << self
|
|
18
79
|
# Settle a charge by ID
|
|
19
80
|
# @param id [Integer, String] charge ID
|
|
20
|
-
# @param params [Hash] optional
|
|
81
|
+
# @param params [Hash] optional payment details
|
|
21
82
|
# @return [Charge]
|
|
22
83
|
def settle(id, params = {})
|
|
23
84
|
find(id).settle(params)
|
|
24
85
|
end
|
|
25
86
|
|
|
26
|
-
#
|
|
87
|
+
# Cancel a charge by ID
|
|
88
|
+
# @param id [Integer, String] charge ID
|
|
89
|
+
# @return [Charge]
|
|
90
|
+
def cancel(id)
|
|
91
|
+
find(id).cancel
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Send email for a charge by ID
|
|
95
|
+
# @param id [Integer, String] charge ID
|
|
96
|
+
# @return [Charge]
|
|
97
|
+
def send_email(id)
|
|
98
|
+
find(id).send_email
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Get PIX for a charge by ID
|
|
27
102
|
# @param id [Integer, String] charge ID
|
|
28
|
-
# @return [ConexaObject]
|
|
103
|
+
# @return [ConexaObject]
|
|
29
104
|
def pix(id)
|
|
30
105
|
find(id).pix
|
|
31
106
|
end
|
|
@@ -1,7 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Conexa
|
|
4
|
+
# Contract resource for recurring billing contracts
|
|
5
|
+
#
|
|
6
|
+
# @example Create a contract
|
|
7
|
+
# contract = Conexa::Contract.create(
|
|
8
|
+
# customer_id: 127,
|
|
9
|
+
# plan_id: 5,
|
|
10
|
+
# start_date: '2024-01-01',
|
|
11
|
+
# payment_day: 10
|
|
12
|
+
# )
|
|
13
|
+
#
|
|
14
|
+
# @example End a contract
|
|
15
|
+
# Conexa::Contract.end_contract(456, end_date: '2024-12-31')
|
|
16
|
+
#
|
|
17
|
+
# @!attribute [r] contract_id
|
|
18
|
+
# @return [Integer] Contract ID (also accessible as #id)
|
|
19
|
+
# @!attribute [r] customer_id
|
|
20
|
+
# @return [Integer] Customer ID
|
|
21
|
+
# @!attribute [r] plan_id
|
|
22
|
+
# @return [Integer, nil] Plan ID
|
|
23
|
+
# @!attribute [r] status
|
|
24
|
+
# @return [String] Status: active, ended, cancelled
|
|
25
|
+
# @!attribute [r] start_date
|
|
26
|
+
# @return [String] Start date
|
|
27
|
+
# @!attribute [r] end_date
|
|
28
|
+
# @return [String, nil] End date
|
|
29
|
+
# @!attribute [r] payment_day
|
|
30
|
+
# @return [Integer] Payment day (1-28)
|
|
31
|
+
# @!attribute [r] value
|
|
32
|
+
# @return [Float] Contract value
|
|
33
|
+
# @!attribute [r] billing_day
|
|
34
|
+
# @return [Integer] Billing day
|
|
35
|
+
#
|
|
2
36
|
class Contract < Model
|
|
3
|
-
|
|
4
|
-
|
|
37
|
+
primary_key_attribute :contract_id
|
|
38
|
+
|
|
39
|
+
# Check if contract is active
|
|
40
|
+
# @return [Boolean]
|
|
41
|
+
def active?
|
|
42
|
+
status == 'active'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Check if contract is cancelled/ended
|
|
46
|
+
# @return [Boolean]
|
|
47
|
+
def ended?
|
|
48
|
+
status == 'ended' || status == 'cancelled'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# End/terminate this contract
|
|
52
|
+
# @param params [Hash] options including :end_date, :reason
|
|
5
53
|
# @return [self]
|
|
6
54
|
def end_contract(params = {})
|
|
7
55
|
Conexa::Request.post(self.class.show_url("end", primary_key), params: params).call(class_name)
|
|
@@ -11,11 +59,18 @@ module Conexa
|
|
|
11
59
|
class << self
|
|
12
60
|
# End a contract by ID
|
|
13
61
|
# @param id [Integer, String] contract ID
|
|
14
|
-
# @param params [Hash]
|
|
62
|
+
# @param params [Hash] options including :end_date, :reason
|
|
15
63
|
# @return [Contract]
|
|
16
64
|
def end_contract(id, params = {})
|
|
17
65
|
find(id).end_contract(params)
|
|
18
66
|
end
|
|
67
|
+
|
|
68
|
+
# Create contract with custom product items
|
|
69
|
+
# @param params [Hash] contract params including :items array
|
|
70
|
+
# @return [Contract]
|
|
71
|
+
def create_with_products(params = {})
|
|
72
|
+
create(params)
|
|
73
|
+
end
|
|
19
74
|
end
|
|
20
75
|
end
|
|
21
76
|
end
|
|
@@ -1,5 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Conexa
|
|
2
|
-
|
|
4
|
+
# Customer resource for managing clients in Conexa
|
|
5
|
+
#
|
|
6
|
+
# @example Create a customer (Legal Person - PJ)
|
|
7
|
+
# customer = Conexa::Customer.create(
|
|
8
|
+
# company_id: 3,
|
|
9
|
+
# name: 'Empresa ABC Ltda',
|
|
10
|
+
# legal_person: { cnpj: '99.557.155/0001-90' }
|
|
11
|
+
# )
|
|
12
|
+
#
|
|
13
|
+
# @example Retrieve a customer
|
|
14
|
+
# customer = Conexa::Customer.find(127)
|
|
15
|
+
# customer.name # => "Empresa ABC Ltda"
|
|
16
|
+
#
|
|
17
|
+
# @example List customers
|
|
18
|
+
# customers = Conexa::Customer.all(company_id: [3], is_active: true)
|
|
19
|
+
#
|
|
20
|
+
# @!attribute [r] customer_id
|
|
21
|
+
# @return [Integer] Customer ID (also accessible as #id)
|
|
22
|
+
# @!attribute [r] company_id
|
|
23
|
+
# @return [Integer] Company/Unit ID
|
|
24
|
+
# @!attribute [r] name
|
|
25
|
+
# @return [String] Customer name
|
|
26
|
+
# @!attribute [r] trade_name
|
|
27
|
+
# @return [String, nil] Trade name
|
|
28
|
+
# @!attribute [r] has_login_access
|
|
29
|
+
# @return [Boolean] Whether customer has login access
|
|
30
|
+
# @!attribute [r] is_active
|
|
31
|
+
# @return [Boolean] Whether customer is active
|
|
32
|
+
# @!attribute [r] is_blocked
|
|
33
|
+
# @return [Boolean] Whether customer is blocked
|
|
34
|
+
# @!attribute [r] is_juridical_person
|
|
35
|
+
# @return [Boolean] Whether customer is a legal person (PJ)
|
|
36
|
+
# @!attribute [r] is_foreign
|
|
37
|
+
# @return [Boolean] Whether customer is a foreigner
|
|
38
|
+
# @!attribute [r] legal_person
|
|
39
|
+
# @return [Hash, nil] Legal person data (cnpj, foundation_date, etc.)
|
|
40
|
+
# @!attribute [r] natural_person
|
|
41
|
+
# @return [Hash, nil] Natural person data (cpf, birth_date, etc.)
|
|
42
|
+
# @!attribute [r] created_at
|
|
43
|
+
# @return [String, nil] Created at timestamp (W3C format)
|
|
44
|
+
#
|
|
45
|
+
class Customer < Model
|
|
46
|
+
primary_key_attribute :customer_id
|
|
47
|
+
|
|
48
|
+
# @return [Array<String>] Phone numbers (empty array if null)
|
|
49
|
+
def phones
|
|
50
|
+
@attributes['phones'] || []
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# @return [Array<String>] Message emails (empty array if null)
|
|
54
|
+
def emails_message
|
|
55
|
+
@attributes['emails_message'] || []
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @return [Array<String>] Financial emails (empty array if null)
|
|
59
|
+
def emails_financial_messages
|
|
60
|
+
@attributes['emails_financial_messages'] || []
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @return [Array<Integer>] Tag IDs (empty array if null)
|
|
64
|
+
def tags_id
|
|
65
|
+
@attributes['tags_id'] || []
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# @return [Address, nil] Customer address
|
|
69
|
+
def address
|
|
70
|
+
return nil unless @attributes['address']
|
|
71
|
+
Address.new(@attributes['address'])
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
class << self
|
|
75
|
+
# List persons (requesters) for a customer
|
|
76
|
+
# @param customer_id [Integer] Customer ID
|
|
77
|
+
# @return [Result] List of persons
|
|
78
|
+
def persons(customer_id)
|
|
79
|
+
Conexa::Person.all(customer_id: customer_id)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# List contracts for a customer
|
|
83
|
+
# @param customer_id [Integer] Customer ID
|
|
84
|
+
# @return [Result] List of contracts
|
|
85
|
+
def contracts(customer_id)
|
|
86
|
+
Conexa::Contract.all(customer_id: [customer_id])
|
|
87
|
+
end
|
|
3
88
|
|
|
89
|
+
# List charges for a customer
|
|
90
|
+
# @param customer_id [Integer] Customer ID
|
|
91
|
+
# @return [Result] List of charges
|
|
92
|
+
def charges(customer_id)
|
|
93
|
+
Conexa::Charge.all(customer_id: [customer_id])
|
|
94
|
+
end
|
|
95
|
+
end
|
|
4
96
|
end
|
|
5
97
|
end
|
|
@@ -1,18 +1,4 @@
|
|
|
1
1
|
module Conexa
|
|
2
2
|
class Person < Model
|
|
3
|
-
class << self
|
|
4
|
-
def all(*args, **params)
|
|
5
|
-
raise NoMethodError
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def find_by_id(id, **options)
|
|
9
|
-
raise NoMethodError
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def find_by(params = Hash.new, page = nil, size = nil)
|
|
14
|
-
raise NoMethodError
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
3
|
end
|
|
18
4
|
end
|
|
@@ -1,4 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Conexa
|
|
2
|
-
|
|
4
|
+
# Sale resource for one-time sales
|
|
5
|
+
#
|
|
6
|
+
# @example Create a sale
|
|
7
|
+
# sale = Conexa::Sale.create(
|
|
8
|
+
# customer_id: 450,
|
|
9
|
+
# product_id: 2521,
|
|
10
|
+
# quantity: 1,
|
|
11
|
+
# amount: 80.99
|
|
12
|
+
# )
|
|
13
|
+
#
|
|
14
|
+
# @example List sales
|
|
15
|
+
# sales = Conexa::Sale.all(customer_id: [450], status: 'notBilled')
|
|
16
|
+
#
|
|
17
|
+
# @!attribute [r] sale_id
|
|
18
|
+
# @return [Integer] Sale ID (also accessible as #id)
|
|
19
|
+
# @!attribute [r] customer_id
|
|
20
|
+
# @return [Integer] Customer ID
|
|
21
|
+
# @!attribute [r] requester_id
|
|
22
|
+
# @return [Integer, nil] Requester ID
|
|
23
|
+
# @!attribute [r] product_id
|
|
24
|
+
# @return [Integer] Product ID
|
|
25
|
+
# @!attribute [r] seller_id
|
|
26
|
+
# @return [Integer, nil] Seller (user) ID
|
|
27
|
+
# @!attribute [r] status
|
|
28
|
+
# @return [String] Status: paid, billed, cancelled, notBilled,
|
|
29
|
+
# deductedFromQuota, billedCancelled, billedNegociated, partiallyPaid
|
|
30
|
+
# @!attribute [r] quantity
|
|
31
|
+
# @return [Integer] Quantity
|
|
32
|
+
# @!attribute [r] amount
|
|
33
|
+
# @return [Float] Final amount
|
|
34
|
+
# @!attribute [r] original_amount
|
|
35
|
+
# @return [Float] Original amount before discount
|
|
36
|
+
# @!attribute [r] discount_value
|
|
37
|
+
# @return [Float] Discount value
|
|
38
|
+
# @!attribute [r] reference_date
|
|
39
|
+
# @return [String] Reference date (W3C format)
|
|
40
|
+
# @!attribute [r] notes
|
|
41
|
+
# @return [String, nil] Notes
|
|
42
|
+
# @!attribute [r] created_at
|
|
43
|
+
# @return [String, nil] Created at timestamp
|
|
44
|
+
# @!attribute [r] updated_at
|
|
45
|
+
# @return [String] Updated at timestamp
|
|
46
|
+
#
|
|
47
|
+
class Sale < Model
|
|
48
|
+
primary_key_attribute :sale_id
|
|
49
|
+
|
|
50
|
+
# Check if sale is billed
|
|
51
|
+
# @return [Boolean]
|
|
52
|
+
def billed?
|
|
53
|
+
status == 'billed'
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Check if sale is paid
|
|
57
|
+
# @return [Boolean]
|
|
58
|
+
def paid?
|
|
59
|
+
status == 'paid'
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Check if sale can be edited
|
|
63
|
+
# @return [Boolean]
|
|
64
|
+
def editable?
|
|
65
|
+
status == 'notBilled'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
class << self
|
|
69
|
+
def url(*params)
|
|
70
|
+
["/sales", *params].join '/'
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def show_url(*params)
|
|
74
|
+
["/sale", *params].join '/'
|
|
75
|
+
end
|
|
76
|
+
end
|
|
3
77
|
end
|
|
4
78
|
end
|
data/lib/conexa/version.rb
CHANGED
data/lib/conexa.rb
CHANGED
|
@@ -10,6 +10,7 @@ require_relative "conexa/errors"
|
|
|
10
10
|
require_relative "conexa/util"
|
|
11
11
|
require_relative "conexa/configuration"
|
|
12
12
|
require_relative "conexa/order_commom"
|
|
13
|
+
require_relative "conexa/token_manager"
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
Dir[File.expand_path('../conexa/resources/*.rb', __FILE__)].map do |path|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
collection = JSON.parse(File.read('docs/postman-collection.json'))
|
|
4
|
+
|
|
5
|
+
fixtures_dir = 'spec/fixtures'
|
|
6
|
+
Dir.mkdir(fixtures_dir) unless Dir.exist?(fixtures_dir)
|
|
7
|
+
|
|
8
|
+
count = 0
|
|
9
|
+
|
|
10
|
+
collection['item'].each do |section|
|
|
11
|
+
section_name = section['name'].downcase.gsub(' ', '_').gsub(/[^a-z0-9_]/, '')
|
|
12
|
+
next if section_name.include?('desenvolvimento')
|
|
13
|
+
|
|
14
|
+
(section['item'] || []).each do |endpoint|
|
|
15
|
+
method = endpoint.dig('request', 'method') || 'UNKNOWN'
|
|
16
|
+
responses = endpoint['response'] || []
|
|
17
|
+
|
|
18
|
+
responses.each_with_index do |resp, idx|
|
|
19
|
+
next unless resp['code'] && resp['code'] < 300
|
|
20
|
+
next unless resp['body']
|
|
21
|
+
|
|
22
|
+
begin
|
|
23
|
+
body = JSON.parse(resp['body'])
|
|
24
|
+
key = "#{section_name}_#{method.downcase}_#{idx}"
|
|
25
|
+
File.write("#{fixtures_dir}/#{key}.json", JSON.pretty_generate(body))
|
|
26
|
+
puts "Created: #{key}.json"
|
|
27
|
+
count += 1
|
|
28
|
+
rescue JSON::ParserError
|
|
29
|
+
# skip
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
puts "\nTotal: #{count} fixtures"
|