colppy 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -2
- data/lib/colppy.rb +2 -0
- data/lib/colppy/core/services.rb +6 -0
- data/lib/colppy/resource.rb +24 -2
- data/lib/colppy/resources/company.rb +41 -10
- data/lib/colppy/resources/customer.rb +40 -17
- data/lib/colppy/resources/invoice.rb +287 -0
- data/lib/colppy/resources/product.rb +77 -53
- data/lib/colppy/resources/sell_invoice.rb +185 -200
- data/lib/colppy/utils.rb +21 -0
- data/lib/colppy/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56924725187f03b328b0305020b7acee209863df
|
4
|
+
data.tar.gz: d22d27f9c912065931f93142177e2ce38eb6b3fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 474bfe2dbb9a742e729752bad31a3aa99c240529bb9c86d5a956f3e6159cc21c3a9e7ed1de8f7d7f575e6429fd4928aa6809c76e592844713a754287ee387742
|
7
|
+
data.tar.gz: 823a5176e7bc75a6dc83f0d2e9eaff0227e1399f08be15408a40898fa430f1bb3e5ddc1e006fdc48e5e3763125241c4fe5d446b6eea266452e79fad3355f4596
|
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
#Colppy
|
2
|
-
|
1
|
+
# Colppy [](https://travis-ci.org/goodpeople/colppy)
|
2
|
+
|
3
|
+
> **Still unstable version and prone to change here and there ;)**
|
3
4
|
|
4
5
|
## Installation
|
5
6
|
|
data/lib/colppy.rb
CHANGED
@@ -4,6 +4,7 @@ require 'multi_json'
|
|
4
4
|
|
5
5
|
require "colppy/version"
|
6
6
|
require "colppy/digest"
|
7
|
+
require "colppy/utils"
|
7
8
|
# CORE
|
8
9
|
require "colppy/core/services"
|
9
10
|
require "colppy/core/gateway"
|
@@ -11,6 +12,7 @@ require "colppy/core/gateway"
|
|
11
12
|
require "colppy/resource"
|
12
13
|
require "colppy/resources/customer"
|
13
14
|
require "colppy/resources/company"
|
15
|
+
require "colppy/resources/invoice"
|
14
16
|
require "colppy/resources/product"
|
15
17
|
require "colppy/resources/sell_invoice"
|
16
18
|
require "colppy/resources/user"
|
data/lib/colppy/core/services.rb
CHANGED
data/lib/colppy/resource.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Colppy
|
2
2
|
class Resource
|
3
|
-
|
3
|
+
attr_reader :data
|
4
|
+
include Utils
|
4
5
|
|
5
6
|
class << self
|
6
7
|
protected
|
@@ -28,6 +29,14 @@ module Colppy
|
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
32
|
+
def initialize(params)
|
33
|
+
@data = rename_params_hash(
|
34
|
+
params,
|
35
|
+
self.class::ATTRIBUTES_MAPPER,
|
36
|
+
self.class::DATA_KEYS_SETTERS
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
31
40
|
def inspect
|
32
41
|
formatted_attrs = attr_inspect.map do |attr|
|
33
42
|
"#{attr}: #{send(attr).inspect}"
|
@@ -35,6 +44,20 @@ module Colppy
|
|
35
44
|
"#<#{self.class.name} #{formatted_attrs.join(", ")}>"
|
36
45
|
end
|
37
46
|
|
47
|
+
def []=(key, value)
|
48
|
+
key_sym = key.to_sym
|
49
|
+
if PROTECTED_DATA_KEYS.include?(key_sym)
|
50
|
+
raise ResourceError.new("You cannot change any of this values: #{PROTECTED_DATA_KEYS.join(", ")} manually")
|
51
|
+
end
|
52
|
+
if DATA_KEYS_SETTERS.include?[key]
|
53
|
+
@data[key_sym] = value
|
54
|
+
elsif new_key = ATTRIBUTES_MAPPER[key_sym]
|
55
|
+
@data[new_key] = value if DATA_KEYS_SETTERS.include?(new_key)
|
56
|
+
else
|
57
|
+
raise DataError.new("There is no attribute named :#{key_sym}, or you cannot change it manually this way. Try initializing another #{self.class.name} with that attribute as the argument")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
38
61
|
private
|
39
62
|
|
40
63
|
def attr_inspect
|
@@ -78,6 +101,5 @@ module Colppy
|
|
78
101
|
)
|
79
102
|
end
|
80
103
|
end
|
81
|
-
|
82
104
|
end
|
83
105
|
end
|
@@ -11,6 +11,13 @@ module Colppy
|
|
11
11
|
class Company < Resource
|
12
12
|
attr_reader :id, :name
|
13
13
|
|
14
|
+
ATTRIBUTES_MAPPER = {
|
15
|
+
idPlan: :plan_id,
|
16
|
+
activa: :active,
|
17
|
+
fechaVencimiento: :expiration_date
|
18
|
+
}.freeze
|
19
|
+
PROTECTED_DATA_KEYS = ATTRIBUTES_MAPPER.values
|
20
|
+
|
14
21
|
class << self
|
15
22
|
def all(client)
|
16
23
|
list(client)
|
@@ -35,9 +42,10 @@ module Colppy
|
|
35
42
|
|
36
43
|
def initialize(client: nil, **params)
|
37
44
|
@client = client if client && client.is_a?(Colppy::Client)
|
38
|
-
|
39
|
-
@
|
40
|
-
@
|
45
|
+
|
46
|
+
@id = params.delete(:IdEmpresa) || params.delete(:id)
|
47
|
+
@name = params.delete(:razonSocial) || params.delete(:name)
|
48
|
+
super(params)
|
41
49
|
end
|
42
50
|
|
43
51
|
def customers(params = {})
|
@@ -49,12 +57,12 @@ module Colppy
|
|
49
57
|
Customer.list(@client, self, params)
|
50
58
|
end
|
51
59
|
end
|
52
|
-
|
53
60
|
def customer_by_id(id)
|
54
61
|
ensure_client_valid!
|
55
62
|
|
56
63
|
Customer.get(@client, self, id)
|
57
64
|
end
|
65
|
+
alias :customer :customer_by_id
|
58
66
|
|
59
67
|
def products(params = {})
|
60
68
|
ensure_client_valid!
|
@@ -65,20 +73,17 @@ module Colppy
|
|
65
73
|
Product.list(@client, self, params)
|
66
74
|
end
|
67
75
|
end
|
68
|
-
|
69
|
-
|
70
|
-
def product_by_sku(sku)
|
76
|
+
def product_by_code(code)
|
71
77
|
ensure_client_valid!
|
72
78
|
|
73
79
|
params = {
|
74
80
|
filter: [
|
75
|
-
{ field: "codigo", op: "=", value:
|
81
|
+
{ field: "codigo", op: "=", value: code }
|
76
82
|
]
|
77
83
|
}
|
78
84
|
response = Product.list(@client, self, params)
|
79
85
|
response[:results].last
|
80
86
|
end
|
81
|
-
|
82
87
|
def product_by_id(id)
|
83
88
|
ensure_client_valid!
|
84
89
|
|
@@ -101,7 +106,6 @@ module Colppy
|
|
101
106
|
SellInvoice.list(@client, self, params)
|
102
107
|
end
|
103
108
|
end
|
104
|
-
|
105
109
|
def sell_invoice_by_id(id)
|
106
110
|
ensure_client_valid!
|
107
111
|
|
@@ -109,6 +113,33 @@ module Colppy
|
|
109
113
|
end
|
110
114
|
alias :sell_invoice :sell_invoice_by_id
|
111
115
|
|
116
|
+
def available_accounts
|
117
|
+
return @available_accounts unless @available_accounts.nil? || @available_accounts.empty?
|
118
|
+
|
119
|
+
response = @client.call(
|
120
|
+
:inventory,
|
121
|
+
:accounts_list,
|
122
|
+
params.merge(@client.session_params)
|
123
|
+
)
|
124
|
+
if response[:success]
|
125
|
+
@available_accounts = response[:cuentas].map do |account|
|
126
|
+
{
|
127
|
+
id: account[:Id],
|
128
|
+
account_id: account[:idPlanCuenta],
|
129
|
+
full_name: account[:Descripcion],
|
130
|
+
name: account[:Descripcion].split(' - ')[1]
|
131
|
+
}
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
def account_name(account_id)
|
136
|
+
return if available_accounts.nil? || available_accounts.empty?
|
137
|
+
|
138
|
+
if account = available_accounts.detect{ |a| a[:account_id].to_s == account_id.to_s }
|
139
|
+
account[:name]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
112
143
|
def params
|
113
144
|
{ idEmpresa: @id }
|
114
145
|
end
|
@@ -1,6 +1,36 @@
|
|
1
1
|
module Colppy
|
2
2
|
class Customer < Resource
|
3
|
-
attr_reader :id, :name
|
3
|
+
attr_reader :id, :name
|
4
|
+
|
5
|
+
ATTRIBUTES_MAPPER = {
|
6
|
+
RazonSocial: :name,
|
7
|
+
NombreFantasia: :fantasy_name,
|
8
|
+
DirPostal: :address,
|
9
|
+
DirPostalCiudad: :address_city,
|
10
|
+
DirPostalCodigoPostal: :address_zipcode,
|
11
|
+
DirPostalProvincia: :address_state,
|
12
|
+
DirPostalPais: :address_country,
|
13
|
+
DirFiscal: :legal_address,
|
14
|
+
DirFiscalCiudad: :legal_address_city,
|
15
|
+
DirFiscalCodigoPostal: :legal_address_zipcode,
|
16
|
+
DirFiscalProvincia: :legal_address_state,
|
17
|
+
DirFiscalPais: :legal_address_country,
|
18
|
+
Telefono: :phone_number,
|
19
|
+
Fax: :fax_number,
|
20
|
+
Activo: :active,
|
21
|
+
idCondicionPago: :payment_condition_id,
|
22
|
+
idCondicionIva: :tax_condition_id,
|
23
|
+
CUIT: :cuit,
|
24
|
+
idTipoPercepcion: :tax_perception_id,
|
25
|
+
NroCuenta: :account_number,
|
26
|
+
CBU: :cbu,
|
27
|
+
Banco: :bank,
|
28
|
+
porcentajeIVA: :tax,
|
29
|
+
Email: :email,
|
30
|
+
Saldo: :balance
|
31
|
+
}.freeze
|
32
|
+
PROTECTED_DATA_KEYS = [:id, :company_id, :name].freeze
|
33
|
+
DATA_KEYS_SETTERS = (ATTRIBUTES_MAPPER.values - PROTECTED_DATA_KEYS).freeze
|
4
34
|
|
5
35
|
class << self
|
6
36
|
def all(client, company)
|
@@ -55,15 +85,20 @@ module Colppy
|
|
55
85
|
}]
|
56
86
|
}
|
57
87
|
end
|
58
|
-
|
59
88
|
end
|
60
89
|
|
61
90
|
def initialize(client: nil, company: nil, **params)
|
62
91
|
@client = client if client && client.is_a?(Colppy::Client)
|
63
92
|
@company = company if company && company.is_a?(Colppy::Company)
|
64
|
-
|
65
|
-
@
|
66
|
-
@
|
93
|
+
|
94
|
+
@id = params.delete(:idCliente) || params.delete(:id)
|
95
|
+
@name = params.delete(:RazonSocial) || params.delete(:name)
|
96
|
+
super(params)
|
97
|
+
end
|
98
|
+
DATA_KEYS_SETTERS.each do |data_key|
|
99
|
+
define_method("#{data_key}=") do |value|
|
100
|
+
@data[data_key.to_sym] = value
|
101
|
+
end
|
67
102
|
end
|
68
103
|
|
69
104
|
def new?
|
@@ -96,24 +131,12 @@ module Colppy
|
|
96
131
|
@name = new_name
|
97
132
|
end
|
98
133
|
|
99
|
-
def []=(key, value)
|
100
|
-
key_sym = key.to_sym
|
101
|
-
if protected_data_keys.include?(key_sym)
|
102
|
-
raise ResourceError.new("You cannot change any of this values: #{protected_data_keys.join(", ")} manually")
|
103
|
-
end
|
104
|
-
@data[key_sym] = value
|
105
|
-
end
|
106
|
-
|
107
134
|
private
|
108
135
|
|
109
136
|
def attr_inspect
|
110
137
|
[:id, :name]
|
111
138
|
end
|
112
139
|
|
113
|
-
def protected_data_keys
|
114
|
-
[:idUsuario, :idCliente, :idEmpresa]
|
115
|
-
end
|
116
|
-
|
117
140
|
def operation
|
118
141
|
new? ? :create : :update
|
119
142
|
end
|
@@ -0,0 +1,287 @@
|
|
1
|
+
module Colppy
|
2
|
+
class Invoice < Resource
|
3
|
+
VALID_PAYMENT_CONDITIONS = ["Contado", "a 15 Dias", "a 30 Dias", "a 60 Dias"]
|
4
|
+
VALID_STATUS_ID = [ "Borrador", "Aprobada", "Anulada", "Cobrada" ]
|
5
|
+
VALID_INVOICE_TYPES = %w(A B C E Z I M X)
|
6
|
+
|
7
|
+
def add_item(params)
|
8
|
+
if item = Item.new(params, @company)
|
9
|
+
@items << item
|
10
|
+
end
|
11
|
+
end
|
12
|
+
def remove_item(key, value)
|
13
|
+
@items.delete_if do |item|
|
14
|
+
item.send(key.to_sym).to_s == value.to_s
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_payment(params)
|
19
|
+
if payment = Payment.new(params)
|
20
|
+
@payments << payment
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def parse_items(new_items)
|
27
|
+
return [] if new_items.nil? || new_items.empty?
|
28
|
+
|
29
|
+
new_items.map do |item_data|
|
30
|
+
Item.new(item_data, @company)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def parse_payments(new_payments)
|
35
|
+
return [] if new_payments.nil? || new_payments.empty?
|
36
|
+
|
37
|
+
new_payments.map do |payment_data|
|
38
|
+
Payment.new(payment_data)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse_taxes_totals(new_taxes_totals)
|
43
|
+
return [] if new_taxes_totals.nil? || new_taxes_totals.empty?
|
44
|
+
|
45
|
+
new_taxes_totals.map do |tax_total_data|
|
46
|
+
TaxTotal.new(tax_total_data)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def invoice_status
|
51
|
+
type = @data[:idEstadoFactura]
|
52
|
+
if type && VALID_INVOICE_STATUS.include?(type)
|
53
|
+
type
|
54
|
+
else
|
55
|
+
raise DataError.new("The value of idEstadoFactura=#{type} is invalid. The value should be any of this ones: #{VALID_INVOICE_STATUS.join(", ")}")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def invoice_type
|
60
|
+
type = @data[:idTipoFactura]
|
61
|
+
if type && VALID_INVOICE_TYPES.include?(type)
|
62
|
+
type
|
63
|
+
else
|
64
|
+
raise DataError.new("The idTipoFactura=#{type} is invalid. The value should be any of this ones: #{VALID_INVOICE_TYPES.join(", ")}")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class Invoice::Item
|
70
|
+
attr_reader :id, :data
|
71
|
+
include Utils
|
72
|
+
|
73
|
+
ATTRIBUTES_MAPPER = {
|
74
|
+
idItem: :product_id,
|
75
|
+
minimo: :minimum_stock,
|
76
|
+
tipoItem: :item_type,
|
77
|
+
codigo: :codigo,
|
78
|
+
Descripcion: :name,
|
79
|
+
unidadMedida: :measure_unit,
|
80
|
+
Cantidad: :quantity, # required
|
81
|
+
ImporteUnitario: :unit_price,
|
82
|
+
IVA: :tax,
|
83
|
+
subtotal: :subtotal,
|
84
|
+
idPlanCuenta: :sales_account_id,
|
85
|
+
Comentario: :comment
|
86
|
+
}.freeze
|
87
|
+
PROTECTED_DATA_KEYS = [:product_id].freeze
|
88
|
+
DATA_KEYS_SETTERS = (ATTRIBUTES_MAPPER.values - PROTECTED_DATA_KEYS).freeze
|
89
|
+
|
90
|
+
def initialize(params, company = nil)
|
91
|
+
@company = company if company.is_a?(Colppy::Company)
|
92
|
+
|
93
|
+
@id = params.delete(:id)
|
94
|
+
@product = params.delete(:product)
|
95
|
+
@data = rename_params_hash(params, ATTRIBUTES_MAPPER, DATA_KEYS_SETTERS)
|
96
|
+
|
97
|
+
if @product && @product.is_a?(Colppy::Product)
|
98
|
+
@data[:product_id] = @product.id
|
99
|
+
else
|
100
|
+
@product = nil
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
DATA_KEYS_SETTERS.each do |data_key|
|
105
|
+
define_method("#{data_key}") do
|
106
|
+
@data[data_key.to_sym]
|
107
|
+
end
|
108
|
+
define_method("#{data_key}=") do |value|
|
109
|
+
@data[data_key.to_sym] = value
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def unhandle_data
|
114
|
+
@data[:unhandle] || {}
|
115
|
+
end
|
116
|
+
|
117
|
+
def product
|
118
|
+
@product ||= @company.product(@data[:product_id])
|
119
|
+
end
|
120
|
+
|
121
|
+
def product_id=(value)
|
122
|
+
@product = nil
|
123
|
+
@data[:product_id] = value
|
124
|
+
end
|
125
|
+
def product_id
|
126
|
+
@data[:product_id]
|
127
|
+
end
|
128
|
+
|
129
|
+
def tax
|
130
|
+
(@data[:tax] || product.tax || 0).to_f
|
131
|
+
end
|
132
|
+
def charged
|
133
|
+
(unit_price || product.sell_price || 0).to_f
|
134
|
+
end
|
135
|
+
def quantity
|
136
|
+
@data[:quantity] || 0
|
137
|
+
end
|
138
|
+
def total_charged
|
139
|
+
( charged * quantity ).round(2)
|
140
|
+
end
|
141
|
+
def minimum_stock
|
142
|
+
(@data[:minimum_stock] || product.minimum_stock || 0)
|
143
|
+
end
|
144
|
+
def item_type
|
145
|
+
(@data[:item_type] || product.item_type || "P")
|
146
|
+
end
|
147
|
+
def code
|
148
|
+
(@data[:code] || product.code || "")
|
149
|
+
end
|
150
|
+
def name
|
151
|
+
(@data[:name] || product.name || "")
|
152
|
+
end
|
153
|
+
def measure_unit
|
154
|
+
(@data[:measure_unit] || product.measure_unit || "u")
|
155
|
+
end
|
156
|
+
def sales_account_id
|
157
|
+
(@data[:sales_account_id] || product.sales_account || "")
|
158
|
+
end
|
159
|
+
def comment
|
160
|
+
(@data[:comment] || "#{product.name}, #{product.detail}" || "")
|
161
|
+
end
|
162
|
+
|
163
|
+
def save_parameters
|
164
|
+
{
|
165
|
+
idItem: product_id.to_s,
|
166
|
+
minimo: minimum_stock.to_s,
|
167
|
+
tipoItem: item_type,
|
168
|
+
codigo: code,
|
169
|
+
Descripcion: name,
|
170
|
+
ccosto1: unhandle_data[:ccosto1] || "",
|
171
|
+
ccosto2: unhandle_data[:ccosto2] || "",
|
172
|
+
almacen: unhandle_data[:almacen] || "",
|
173
|
+
unidadMedida: measure_unit,
|
174
|
+
Cantidad: quantity,
|
175
|
+
ImporteUnitario: charged,
|
176
|
+
porcDesc: unhandle_data[:porcDesc] || 0,
|
177
|
+
IVA: tax.to_s,
|
178
|
+
subtotal: total_charged,
|
179
|
+
idPlanCuenta: sales_account_id,
|
180
|
+
Comentario: comment
|
181
|
+
}
|
182
|
+
end
|
183
|
+
|
184
|
+
def inspect; end
|
185
|
+
end
|
186
|
+
class Invoice::Payment
|
187
|
+
include Utils
|
188
|
+
|
189
|
+
VALID_PAYMENT_TYPES = [
|
190
|
+
"Cheque Recibido Común",
|
191
|
+
"Cheque Recibido Diferido",
|
192
|
+
"Transferencia",
|
193
|
+
"Efectivo",
|
194
|
+
"Tarjeta de Credito"
|
195
|
+
]
|
196
|
+
|
197
|
+
ATTRIBUTES_MAPPER = {
|
198
|
+
idMedioCobro: :payment_type_id, # required
|
199
|
+
idPlanCuenta: :payment_account_id, # required
|
200
|
+
Banco: :bank,
|
201
|
+
nroCheque: :check_number,
|
202
|
+
fechaValidez: :valid_date,
|
203
|
+
importe: :amount, # required
|
204
|
+
VAD: :vad,
|
205
|
+
Conciliado: :conciliated,
|
206
|
+
idTabla: :table_id,
|
207
|
+
idElemento: :element_id,
|
208
|
+
idItem: :item_id
|
209
|
+
}.freeze
|
210
|
+
DATA_KEYS_SETTERS = ATTRIBUTES_MAPPER.values
|
211
|
+
|
212
|
+
def initialize(params)
|
213
|
+
@data = rename_params_hash(params, ATTRIBUTES_MAPPER, DATA_KEYS_SETTERS)
|
214
|
+
end
|
215
|
+
DATA_KEYS_SETTERS.each do |data_key|
|
216
|
+
define_method("#{data_key}=") do |value|
|
217
|
+
@data[data_key.to_sym] = value
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def amount
|
222
|
+
@data[:amount] || 0.0
|
223
|
+
end
|
224
|
+
|
225
|
+
def save_parameters
|
226
|
+
{
|
227
|
+
idMedioCobro: @data[:payment_type_id],
|
228
|
+
idPlanCuenta: @data[:payment_account_id],
|
229
|
+
Banco: @data[:bank] || "",
|
230
|
+
nroCheque: @data[:check_number] || "",
|
231
|
+
fechaValidez: @data[:valid_date] || "",
|
232
|
+
importe: amount,
|
233
|
+
VAD: @data[:vad] || "S",
|
234
|
+
Conciliado: @data[:conciliated] || "",
|
235
|
+
idTabla: @data[:table_id] || 0,
|
236
|
+
idElemento: @data[:element_id] || 0,
|
237
|
+
idItem: @data[:item_id] || 0
|
238
|
+
}
|
239
|
+
end
|
240
|
+
|
241
|
+
def inspect; end
|
242
|
+
end
|
243
|
+
class Invoice::TaxTotal
|
244
|
+
include Utils
|
245
|
+
|
246
|
+
def self.add_to_tax_breakdown(tax, amount, taxed_amount, breakdown = nil)
|
247
|
+
breakdown = breakdown || { tax_factor: tax, tax_amount: 0.0, taxed_amount: 0.0 }
|
248
|
+
breakdown[:tax_amount] += amount
|
249
|
+
breakdown[:taxed_amount] += taxed_amount
|
250
|
+
breakdown
|
251
|
+
end
|
252
|
+
|
253
|
+
ATTRIBUTES_MAPPER = {
|
254
|
+
alicuotaIva: :tax_factor,
|
255
|
+
importeIva: :tax_amount,
|
256
|
+
baseImpIva: :taxed_amount
|
257
|
+
}.freeze
|
258
|
+
DATA_KEYS_SETTERS = ATTRIBUTES_MAPPER.values
|
259
|
+
|
260
|
+
def initialize(params)
|
261
|
+
@data = rename_params_hash(params, ATTRIBUTES_MAPPER, DATA_KEYS_SETTERS)
|
262
|
+
end
|
263
|
+
DATA_KEYS_SETTERS.each do |data_key|
|
264
|
+
define_method("#{data_key}=") do |value|
|
265
|
+
@data[data_key.to_sym] = value
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def tax_name
|
270
|
+
if @data[:tax_factor] % 1 == 0
|
271
|
+
@data[:tax_factor].to_i.to_s
|
272
|
+
else
|
273
|
+
@data[:tax_factor].to_s
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def save_parameters
|
278
|
+
{
|
279
|
+
alicuotaIva: tax_name,
|
280
|
+
importeIva: @data[:tax_amount],
|
281
|
+
baseImpIva: @data[:taxed_amount]
|
282
|
+
}
|
283
|
+
end
|
284
|
+
|
285
|
+
def inspect; end
|
286
|
+
end
|
287
|
+
end
|
@@ -1,6 +1,26 @@
|
|
1
1
|
module Colppy
|
2
2
|
class Product < Resource
|
3
|
-
attr_reader :id, :name, :
|
3
|
+
attr_reader :id, :name, :code
|
4
|
+
|
5
|
+
ATTRIBUTES_MAPPER = {
|
6
|
+
idItem: :id,
|
7
|
+
idEmpresa: :company_id,
|
8
|
+
codigo: :code,
|
9
|
+
descripcion: :name,
|
10
|
+
detalle: :detail,
|
11
|
+
precioVenta: :sell_price,
|
12
|
+
ultimoPrecioCompra: :last_purchase_price,
|
13
|
+
ctaInventario: :inventory_account,
|
14
|
+
ctaCostoVentas: :sales_costs_account,
|
15
|
+
ctaIngresoVentas: :sales_account,
|
16
|
+
iva: :tax,
|
17
|
+
tipoItem: :item_type,
|
18
|
+
unidadMedida: :measure_unit,
|
19
|
+
minimo: :minimum_stock,
|
20
|
+
disponibilidad: :availability
|
21
|
+
}.freeze
|
22
|
+
PROTECTED_DATA_KEYS = [:id, :company_id, :name, :code].freeze
|
23
|
+
DATA_KEYS_SETTERS = (ATTRIBUTES_MAPPER.values - PROTECTED_DATA_KEYS).freeze
|
4
24
|
|
5
25
|
class << self
|
6
26
|
def all(client, company)
|
@@ -48,14 +68,36 @@ module Colppy
|
|
48
68
|
def initialize(client: nil, company: nil, **params)
|
49
69
|
@client = client if client && client.is_a?(Colppy::Client)
|
50
70
|
@company = company if company && company.is_a?(Colppy::Company)
|
51
|
-
|
52
|
-
@
|
53
|
-
@
|
54
|
-
@
|
71
|
+
|
72
|
+
@id = params.delete(:idItem) || params.delete(:id)
|
73
|
+
@name = params.delete(:descripcion) || params.delete(:name)
|
74
|
+
@code = params.delete(:codigo) || params.delete(:code)
|
75
|
+
|
76
|
+
super(params)
|
77
|
+
end
|
78
|
+
DATA_KEYS_SETTERS.each do |data_key|
|
79
|
+
define_method("#{data_key}") do
|
80
|
+
@data[data_key.to_sym]
|
81
|
+
end
|
82
|
+
define_method("#{data_key}=") do |value|
|
83
|
+
@data[data_key.to_sym] = value
|
84
|
+
end
|
55
85
|
end
|
56
86
|
|
57
87
|
def new?
|
58
|
-
id.nil? || id.empty?
|
88
|
+
@id.nil? || @id.empty?
|
89
|
+
end
|
90
|
+
|
91
|
+
def exist?
|
92
|
+
!new?
|
93
|
+
end
|
94
|
+
|
95
|
+
def name=(value)
|
96
|
+
@name = value
|
97
|
+
end
|
98
|
+
|
99
|
+
def code=(value)
|
100
|
+
@code = value
|
59
101
|
end
|
60
102
|
|
61
103
|
def save
|
@@ -78,45 +120,14 @@ module Colppy
|
|
78
120
|
end
|
79
121
|
end
|
80
122
|
|
81
|
-
def
|
82
|
-
|
83
|
-
end
|
84
|
-
|
85
|
-
def sku=(new_sku)
|
86
|
-
@sku = new_sku
|
87
|
-
end
|
88
|
-
|
89
|
-
def []=(key, value)
|
90
|
-
key_sym = key.to_sym
|
91
|
-
if protected_data_keys.include?(key_sym)
|
92
|
-
raise ResourceError.new("You cannot change any of this values: #{protected_data_keys.join(", ")} manually")
|
93
|
-
end
|
94
|
-
@data[key_sym] = value
|
95
|
-
end
|
96
|
-
|
97
|
-
def params_for_invoice
|
98
|
-
{
|
99
|
-
idItem: id || "",
|
100
|
-
minimo: @data[:minimo] || "0",
|
101
|
-
codigo: sku || "",
|
102
|
-
tipoItem: @data[:tipoItem] || "P",
|
103
|
-
unidadMedida: @data[:unidadMedida] || "u",
|
104
|
-
Descripcion: name || "",
|
105
|
-
ImporteUnitario: @data[:precioVenta],
|
106
|
-
IVA: @data[:iva] || "21",
|
107
|
-
Comentario: @data[:detalle] || "",
|
108
|
-
idPlanCuenta: @data[:ctaIngresoVentas]
|
109
|
-
}
|
123
|
+
def sales_account
|
124
|
+
check_mandatory_account!(:sales_account)
|
110
125
|
end
|
111
126
|
|
112
127
|
private
|
113
128
|
|
114
129
|
def attr_inspect
|
115
|
-
[:id, :
|
116
|
-
end
|
117
|
-
|
118
|
-
def protected_data_keys
|
119
|
-
[:idItem, :idEmpresa]
|
130
|
+
[:id, :code, :name]
|
120
131
|
end
|
121
132
|
|
122
133
|
def operation
|
@@ -132,21 +143,34 @@ module Colppy
|
|
132
143
|
|
133
144
|
def params
|
134
145
|
{
|
135
|
-
idItem: id || "",
|
146
|
+
idItem: @id || "",
|
136
147
|
idEmpresa: @company.id,
|
137
|
-
codigo:
|
138
|
-
descripcion: name || "",
|
139
|
-
detalle: @data[:
|
140
|
-
precioVenta: @data[:
|
141
|
-
ultimoPrecioCompra: @data[:
|
142
|
-
ctaInventario:
|
143
|
-
ctaCostoVentas:
|
144
|
-
ctaIngresoVentas:
|
145
|
-
iva: @data[:
|
146
|
-
tipoItem: @data[:
|
147
|
-
unidadMedida: @data[:
|
148
|
-
minimo: @data[:
|
148
|
+
codigo: @code || "",
|
149
|
+
descripcion: @name || "",
|
150
|
+
detalle: @data[:detail] || "",
|
151
|
+
precioVenta: @data[:sell_price] || "0",
|
152
|
+
ultimoPrecioCompra: @data[:last_purchase_price] || "",
|
153
|
+
ctaInventario: check_mandatory_account!(:inventory_account),
|
154
|
+
ctaCostoVentas: check_mandatory_account!(:sales_costs_account),
|
155
|
+
ctaIngresoVentas: check_mandatory_account!(:sales_account),
|
156
|
+
iva: @data[:tax] || "21",
|
157
|
+
tipoItem: @data[:item_type] || "P",
|
158
|
+
unidadMedida: @data[:measure_unit] || "u",
|
159
|
+
minimo: @data[:minimum_stock] || "0"
|
149
160
|
}
|
150
161
|
end
|
162
|
+
|
163
|
+
def check_mandatory_account!(account)
|
164
|
+
if account_name_or_id = @data[account]
|
165
|
+
real_account_name = @company.account_name(account_name_or_id)
|
166
|
+
if real_account_name
|
167
|
+
real_account_name
|
168
|
+
else
|
169
|
+
account_name_or_id
|
170
|
+
end
|
171
|
+
else
|
172
|
+
raise DataError.new("The :#{account} is required for the product. You should specify one via product.#{account} = '', or product[:#{account}] = '', or when you initialize it. You should check the available and valid accounts in Colppy")
|
173
|
+
end
|
174
|
+
end
|
151
175
|
end
|
152
176
|
end
|
@@ -1,9 +1,41 @@
|
|
1
1
|
module Colppy
|
2
|
-
class SellInvoice <
|
3
|
-
attr_reader :id, :number, :cae, :
|
4
|
-
attr_accessor :payments
|
2
|
+
class SellInvoice < Invoice
|
3
|
+
attr_reader :id, :number, :cae, :url, :items
|
5
4
|
|
6
5
|
VALID_RECEIPT_TYPES = %w(4 6 8 NCV)
|
6
|
+
ATTRIBUTES_MAPPER = {
|
7
|
+
descripcion: :description,
|
8
|
+
fechaFactura: :invoice_date,
|
9
|
+
idCondicionPago: :payment_condition_id, # validate
|
10
|
+
fechaPago: :payment_date,
|
11
|
+
idEmpresa: :company_id,
|
12
|
+
idCliente: :customer_id,
|
13
|
+
idEstadoAnterior: :previous_status_id, # validate
|
14
|
+
idEstadoFactura: :status_id, # validate
|
15
|
+
idMoneda: :currency_id,
|
16
|
+
idTipoComprobante: :receipt_type_id, # validate
|
17
|
+
idTipoFactura: :invoice_type_id, # validate
|
18
|
+
idUsuario: :user_id,
|
19
|
+
labelfe: :electronic_bill,
|
20
|
+
netoGravado: :total_taxed,
|
21
|
+
netoNoGravado: :total_nontaxed,
|
22
|
+
nroFactura1: :invoice_number1,
|
23
|
+
nroFactura2: :invoice_number2,
|
24
|
+
percepcionIIBB: :iibb_perception,
|
25
|
+
percepcionIVA: :tax_perception,
|
26
|
+
tipoFactura: :invoice_type, # validate
|
27
|
+
totalFactura: :total,
|
28
|
+
totalIVA: :total_taxes,
|
29
|
+
totalpagadofactura: :total_payed,
|
30
|
+
valorCambio: :exchange_rate,
|
31
|
+
nroRepeticion: :repetition_number,
|
32
|
+
periodoRep: :repetition_period,
|
33
|
+
nroVencimiento: :expiration_number,
|
34
|
+
tipoVencimiento: :expiration_type,
|
35
|
+
fechaFin: :end_date
|
36
|
+
}.freeze
|
37
|
+
PROTECTED_DATA_KEYS = [:id, :company_id, :customer_id, :number, :cae].freeze
|
38
|
+
DATA_KEYS_SETTERS = (ATTRIBUTES_MAPPER.values - PROTECTED_DATA_KEYS).freeze
|
7
39
|
|
8
40
|
class << self
|
9
41
|
def all(client, company)
|
@@ -61,13 +93,12 @@ module Colppy
|
|
61
93
|
|
62
94
|
def extended_response(response, client, company)
|
63
95
|
[ response[:infofactura],
|
64
|
-
|
96
|
+
itemsFactura: response[:itemsFactura],
|
65
97
|
url: response[:UrlFacturaPdf],
|
66
98
|
client: client,
|
67
99
|
company: company
|
68
100
|
].inject(&:merge)
|
69
101
|
end
|
70
|
-
|
71
102
|
end
|
72
103
|
|
73
104
|
def initialize(client: nil, company: nil, customer: nil, **params)
|
@@ -75,15 +106,20 @@ module Colppy
|
|
75
106
|
@company = company if company && company.is_a?(Colppy::Company)
|
76
107
|
@customer = customer if customer && customer.is_a?(Colppy::Customer)
|
77
108
|
|
78
|
-
@id = params.delete(:idFactura)
|
79
|
-
@number = params.delete(:nroFactura)
|
109
|
+
@id = params.delete(:idFactura) || params.delete(:id)
|
110
|
+
@number = params.delete(:nroFactura) || params.delete(:number)
|
80
111
|
@cae = params.delete(:cae)
|
81
112
|
|
82
|
-
@items = parse_items(params.delete(:
|
83
|
-
@payments = params.delete(:ItemsCobro)
|
113
|
+
@items = parse_items(params.delete(:itemsFactura))
|
114
|
+
@payments = parse_payments(params.delete(:ItemsCobro))
|
115
|
+
@taxes_totals = parse_taxes_totals(params.delete(:totalesiva))
|
84
116
|
|
85
|
-
|
86
|
-
|
117
|
+
super(params)
|
118
|
+
end
|
119
|
+
DATA_KEYS_SETTERS.each do |data_key|
|
120
|
+
define_method("#{data_key}=") do |value|
|
121
|
+
@data[data_key.to_sym] = value
|
122
|
+
end
|
87
123
|
end
|
88
124
|
|
89
125
|
def new?
|
@@ -94,250 +130,199 @@ module Colppy
|
|
94
130
|
cae.nil? || cae.empty?
|
95
131
|
end
|
96
132
|
|
133
|
+
def url
|
134
|
+
return if @data[:url].nil? || @data[:url].empty?
|
135
|
+
|
136
|
+
"#{@data[:url]}?usuario=#{@client.username}&claveSesion=#{@client.session_key}&idEmpresa=#{company_id}&idFactura=#{id}&idCliente=#{customer_id}"
|
137
|
+
end
|
138
|
+
|
139
|
+
def total_charged
|
140
|
+
@items.map(&:total_charged).inject(0,:+)
|
141
|
+
end
|
142
|
+
|
143
|
+
def []=(key, value)
|
144
|
+
ensure_editability!
|
145
|
+
|
146
|
+
super
|
147
|
+
end
|
148
|
+
|
149
|
+
def customer=(new_customer)
|
150
|
+
@customer = new_customer if new_customer.is_a?(Colppy::Customer)
|
151
|
+
end
|
152
|
+
|
97
153
|
def save
|
98
|
-
ensure_editability!
|
154
|
+
ensure_editability!
|
155
|
+
ensure_client_valid!
|
156
|
+
ensure_payment_setup!
|
99
157
|
|
100
158
|
response = @client.call(
|
101
159
|
:sell_invoice,
|
102
160
|
:create,
|
103
161
|
save_parameters
|
104
162
|
)
|
105
|
-
binding.pry
|
106
163
|
if response[:success]
|
107
|
-
@
|
164
|
+
@cae = response[:cae]
|
165
|
+
@id = response[:idfactura]
|
166
|
+
@number = response[:nroFactura]
|
167
|
+
@data[:invoice_date] = response[:fechaFactura]
|
168
|
+
@data[:url] = response[:UrlFacturaPdf]
|
108
169
|
self
|
109
170
|
else
|
110
171
|
false
|
111
172
|
end
|
112
173
|
end
|
113
174
|
|
114
|
-
def []=(key, value)
|
115
|
-
ensure_editability!
|
116
|
-
|
117
|
-
key_sym = key.to_sym
|
118
|
-
if protected_data_keys.include?(key_sym)
|
119
|
-
raise ResourceError.new("You cannot change any of this values: #{protected_data_keys.join(", ")} manually")
|
120
|
-
end
|
121
|
-
@data[key_sym] = value
|
122
|
-
end
|
123
|
-
|
124
|
-
def items=(new_items)
|
125
|
-
@charged_details = nil
|
126
|
-
@items = parse_items(new_items)
|
127
|
-
end
|
128
|
-
|
129
175
|
private
|
130
176
|
|
131
177
|
def attr_inspect
|
132
178
|
[:id, :number, :cae]
|
133
179
|
end
|
134
180
|
|
135
|
-
def
|
136
|
-
|
137
|
-
end
|
181
|
+
def customer_id
|
182
|
+
return @customer.id if @customer
|
138
183
|
|
139
|
-
|
140
|
-
|
184
|
+
@data[:customer_id] || ""
|
185
|
+
end
|
186
|
+
def company_id
|
187
|
+
return @company.id if @company
|
141
188
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
189
|
+
@data[:company_id] || ""
|
190
|
+
end
|
191
|
+
def payment_condition_id
|
192
|
+
validate_type!(:payment_condition_id, VALID_PAYMENT_CONDITIONS)
|
193
|
+
end
|
194
|
+
def previous_status_id
|
195
|
+
if status = @data[:previous_status_id]
|
196
|
+
validate_type!(status, VALID_STATUS_ID)
|
197
|
+
else
|
198
|
+
""
|
148
199
|
end
|
149
200
|
end
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
201
|
+
def status_id
|
202
|
+
validate_type!(:status_id, VALID_STATUS_ID)
|
203
|
+
end
|
204
|
+
def receipt_type_id
|
205
|
+
validate_type!(:receipt_type_id, VALID_RECEIPT_TYPES)
|
206
|
+
end
|
207
|
+
def invoice_type_id
|
208
|
+
validate_type!(:invoice_type_id, VALID_INVOICE_TYPES)
|
209
|
+
end
|
210
|
+
def invoice_type
|
211
|
+
if receipt_type_id == "8"
|
212
|
+
"Contado"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
def validate_type!(data_key, valid_types)
|
216
|
+
type = @data[data_key]
|
217
|
+
if type && valid_types.include?(type)
|
218
|
+
type
|
219
|
+
else
|
220
|
+
raise DataError.new("The #{data_key} is invalid. The value should be any of this ones: #{valid_types.join(", ")}")
|
221
|
+
""
|
222
|
+
end
|
155
223
|
end
|
156
224
|
|
157
225
|
def save_parameters
|
226
|
+
charged_amounts = calculate_charged_amounts
|
158
227
|
[
|
159
228
|
@client.session_params,
|
160
|
-
general_params,
|
161
|
-
|
162
|
-
|
163
|
-
totalesiva:
|
229
|
+
general_params(charged_amounts),
|
230
|
+
itemsFactura: @items.map(&:save_parameters),
|
231
|
+
ItemsCobro: @payments.map(&:save_parameters),
|
232
|
+
totalesiva: @taxes_totals.map(&:save_parameters)
|
164
233
|
].inject(&:merge)
|
165
234
|
end
|
166
235
|
|
167
|
-
def general_params
|
236
|
+
def general_params(charged_amounts)
|
168
237
|
{
|
169
|
-
idCliente:
|
170
|
-
idEmpresa:
|
238
|
+
idCliente: customer_id,
|
239
|
+
idEmpresa: company_id,
|
240
|
+
idUsuario: @client.username,
|
171
241
|
descripcion: @data[:descripcion] || "",
|
172
|
-
fechaFactura: valid_date(@data[:
|
173
|
-
idCondicionPago:
|
174
|
-
fechaPago: valid_date(@data[:
|
175
|
-
idEstadoAnterior:
|
176
|
-
idEstadoFactura:
|
177
|
-
idFactura: id || "",
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
242
|
+
fechaFactura: valid_date(@data[:invoice_date]),
|
243
|
+
idCondicionPago: payment_condition_id,
|
244
|
+
fechaPago: valid_date(@data[:payment_date]),
|
245
|
+
idEstadoAnterior: previous_status_id,
|
246
|
+
idEstadoFactura: status_id,
|
247
|
+
idFactura: @id || "",
|
248
|
+
idMoneda: @data[:currency_id] || "1",
|
249
|
+
idTipoComprobante: receipt_type_id,
|
250
|
+
idTipoFactura: invoice_type_id,
|
251
|
+
netoGravado: charged_amounts[:total_taxed] || 0.00,
|
252
|
+
netoNoGravado: charged_amounts[:total_non_taxed] || 0.00,
|
253
|
+
nroFactura1: @data[:invoice_number1] || "0001",
|
254
|
+
nroFactura2: @data[:invoice_number2] || "00000000",
|
255
|
+
percepcionIVA: @data[:tax_perception] || 0.00,
|
256
|
+
percepcionIIBB: @data[:iibb_perception] || 0.00,
|
257
|
+
totalFactura: charged_amounts[:total] || 0.00,
|
258
|
+
totalIVA: charged_amounts[:tax_total] || 0.00,
|
259
|
+
valorCambio: @data[:exchange_rate] || "1",
|
260
|
+
nroRepeticion: @data[:repetition_number] || "1",
|
261
|
+
periodoRep: @data[:repetition_period] || "1",
|
262
|
+
nroVencimiento: @data[:expiration_number] || "0",
|
263
|
+
tipoVencimiento: @data[:expiration_type] || "1",
|
264
|
+
fechaFin: @data[:end_date] || ""
|
191
265
|
}.tap do |params|
|
192
|
-
params[:
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
def invoice_items_params
|
197
|
-
items.map do |item|
|
198
|
-
if item[:product] && item[:product].is_a?(Colppy::Product)
|
199
|
-
product = item[:product]
|
200
|
-
[
|
201
|
-
product.params_for_invoice,
|
202
|
-
item_params(item, false)
|
203
|
-
].inject(&:merge)
|
204
|
-
elsif item.is_a?(Hash)
|
205
|
-
item_params(item)
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
def item_params(item, fill_empty = true)
|
211
|
-
{
|
212
|
-
Cantidad: item[:Cantidad],
|
213
|
-
porcDesc: item[:porcDesc] || "0.00"
|
214
|
-
}.tap do |params|
|
215
|
-
if value = item[:ImporteUnitario] || fill_empty
|
216
|
-
params[:ImporteUnitario] = value || ""
|
217
|
-
end
|
218
|
-
if value = item[:idPlanCuenta] || fill_empty
|
219
|
-
params[:idPlanCuenta] = value || ""
|
220
|
-
end
|
221
|
-
if value = item[:IVA] || fill_empty
|
222
|
-
params[:IVA] = value || "21"
|
223
|
-
end
|
224
|
-
if value = item[:Comentario] || fill_empty
|
225
|
-
params[:Comentario] = value || ""
|
266
|
+
params[:tipoFactura] = invoice_type if invoice_type
|
267
|
+
if status_id == "Cobrada"
|
268
|
+
params[:totalpagadofactura] = @payments.map(&:amount).inject(0,:+)
|
226
269
|
end
|
270
|
+
params[:labelfe] = "Factura Electrónica" if @data[:electronic_bill]
|
227
271
|
end
|
228
272
|
end
|
229
273
|
|
230
|
-
def
|
231
|
-
|
232
|
-
|
233
|
-
{
|
234
|
-
idMedioCobro: payment[:idMedioCobro] || "Efectivo",
|
235
|
-
idPlanCuenta: payment[:idPlanCuenta] || "Caja en pesos",
|
236
|
-
Banco: payment[:Banco] || "",
|
237
|
-
nroCheque: payment[:nroCheque] || "",
|
238
|
-
fechaValidez: payment[:fechaValidez] || "",
|
239
|
-
importe: payment[:importe] || "0",
|
240
|
-
VAD: payment[:VAD] || "S"
|
241
|
-
}
|
242
|
-
end
|
243
|
-
{ ItemsCobro: payment_items }
|
244
|
-
end
|
245
|
-
|
246
|
-
def total_taxes_params
|
247
|
-
charged_details[:tax_details].map do |tax, values|
|
248
|
-
{
|
249
|
-
alicuotaIva: tax.to_s,
|
250
|
-
baseImpIva: values[:total_taxed].to_s,
|
251
|
-
importeIva: values[:tax_total].to_s
|
252
|
-
}
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
def charged_details
|
257
|
-
return @charged_details unless @charged_details.nil? || @charged_details.empty?
|
258
|
-
|
259
|
-
if items.nil? || items.empty?
|
260
|
-
raise DataError.new("In order to save an SellInvoice you should at least have one item in it")
|
274
|
+
def calculate_charged_amounts
|
275
|
+
if @items.nil? || @items.empty?
|
276
|
+
raise DataError.new("In order to save an SellInvoice you should at least have one item in it. Add one with .add_item()")
|
261
277
|
else
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
result[:
|
280
|
-
tax_total: result[:tax_total],
|
281
|
-
total_taxed: result[:total_taxed]
|
282
|
-
}
|
278
|
+
charged_details = @items.each_with_object(base_charged_amounts) do |item, result|
|
279
|
+
tax = item.tax
|
280
|
+
total = item.total_charged
|
281
|
+
if tax > 0
|
282
|
+
dividend = tax.to_f
|
283
|
+
divisor = (100.0 + dividend).to_f
|
284
|
+
|
285
|
+
item_tax_amount = (( total * dividend ) / divisor).round(2)
|
286
|
+
item_taxed_amount = (total - item_tax_amount).round(2)
|
287
|
+
result[:tax_total] += item_tax_amount
|
288
|
+
result[:total_taxed] += item_taxed_amount
|
289
|
+
tax_breakdown_data = TaxTotal.add_to_tax_breakdown(
|
290
|
+
tax,
|
291
|
+
item_tax_amount,
|
292
|
+
item_taxed_amount,
|
293
|
+
result[:tax_breakdown][tax]
|
294
|
+
)
|
295
|
+
result[:tax_breakdown][tax] = tax_breakdown_data
|
283
296
|
else
|
284
297
|
result[:total_nontaxed] += total
|
285
298
|
end
|
286
299
|
result[:total] += total
|
287
300
|
end
|
301
|
+
@taxes_totals = parse_taxes_totals(charged_details[:tax_breakdown].values)
|
302
|
+
charged_details
|
288
303
|
end
|
289
304
|
end
|
290
305
|
|
306
|
+
def base_charged_amounts
|
307
|
+
{
|
308
|
+
total_taxed: 0.00,
|
309
|
+
total_nontaxed: 0.00,
|
310
|
+
total: 0.00,
|
311
|
+
tax_total: 0.00,
|
312
|
+
tax_breakdown: {}
|
313
|
+
}
|
314
|
+
end
|
315
|
+
|
291
316
|
def ensure_editability!
|
292
317
|
unless editable?
|
293
318
|
raise ResourceError.new("You cannot change any value of this invoice, because it's already processed by AFIP. You should create a new one instead")
|
294
319
|
end
|
295
320
|
end
|
296
321
|
|
297
|
-
def
|
298
|
-
|
299
|
-
|
300
|
-
type
|
301
|
-
else
|
302
|
-
raise DataError.new("The value of idEstadoFactura:#{type} is invalid. The value should be any of this ones: #{VALID_INVOICE_STATUS.join(", ")}")
|
303
|
-
end
|
304
|
-
end
|
305
|
-
|
306
|
-
def invoice_type
|
307
|
-
type = @data[:idTipoFactura]
|
308
|
-
if type && VALID_INVOICE_TYPES.include?(type)
|
309
|
-
type
|
310
|
-
else
|
311
|
-
raise DataError.new("The idTipoFactura:#{type} is invalid. The value should be any of this ones: #{VALID_INVOICE_TYPES.join(", ")}")
|
312
|
-
end
|
313
|
-
end
|
314
|
-
|
315
|
-
def receipt_type
|
316
|
-
type = @data[:idTipoComprobante]
|
317
|
-
if type && VALID_RECEIPT_TYPES.include?(type)
|
318
|
-
type
|
319
|
-
else
|
320
|
-
raise DataError.new("The idTipoComprobante:#{type} is invalid. The value should be any of this ones: #{VALID_RECEIPT_TYPES.join(", ")}")
|
321
|
-
""
|
322
|
+
def ensure_payment_setup!
|
323
|
+
if status_id == "Cobrada" && (@payments.nil? || @payments.empty?)
|
324
|
+
raise ResourceError.new("You cannot save this invoice, because it's doesn't have any payment associated to it and the status is #{@data[:status_id]}. Add one calling .add_payment({})")
|
322
325
|
end
|
323
326
|
end
|
324
327
|
end
|
325
328
|
end
|
326
|
-
|
327
|
-
# "totalesiva":[
|
328
|
-
# {
|
329
|
-
# alicuotaIva: "0",
|
330
|
-
# baseImpIva: "0.00",
|
331
|
-
# importeIva: "0.00"
|
332
|
-
# },
|
333
|
-
# {
|
334
|
-
# alicuotaIva: "21",
|
335
|
-
# baseImpIva: "101.65",
|
336
|
-
# importeIva: "21.35"
|
337
|
-
# },
|
338
|
-
# {
|
339
|
-
# alicuotaIva: "27",
|
340
|
-
# baseImpIva: "0.00",
|
341
|
-
# importeIva: "0.00"
|
342
|
-
# }
|
343
|
-
# ]
|
data/lib/colppy/utils.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Colppy
|
2
|
+
module Utils
|
3
|
+
module_function
|
4
|
+
|
5
|
+
ATTRIBUTES_MAPPER = {}
|
6
|
+
DATA_KEYS_SETTERS = []
|
7
|
+
|
8
|
+
def rename_params_hash(params, mapper, setter)
|
9
|
+
params.each_with_object({}) do |(key, value), hash|
|
10
|
+
if new_key = mapper[key]
|
11
|
+
hash[new_key] = value
|
12
|
+
elsif setter.include?(key)
|
13
|
+
hash[key] = value
|
14
|
+
else
|
15
|
+
hash[:unhandle] ||= {}
|
16
|
+
hash[:unhandle][key] = value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/colppy/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: colppy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Agustin Cavilliotti
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -143,9 +143,11 @@ files:
|
|
143
143
|
- lib/colppy/resource.rb
|
144
144
|
- lib/colppy/resources/company.rb
|
145
145
|
- lib/colppy/resources/customer.rb
|
146
|
+
- lib/colppy/resources/invoice.rb
|
146
147
|
- lib/colppy/resources/product.rb
|
147
148
|
- lib/colppy/resources/sell_invoice.rb
|
148
149
|
- lib/colppy/resources/user.rb
|
150
|
+
- lib/colppy/utils.rb
|
149
151
|
- lib/colppy/version.rb
|
150
152
|
homepage: https://github.com/goodpeople/colppy
|
151
153
|
licenses:
|