facturacr 1.0.6 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/facturacr.gemspec +2 -2
  3. data/lib/facturacr.rb +25 -19
  4. data/lib/facturacr/api.rb +5 -4
  5. data/lib/facturacr/builder.rb +4 -4
  6. data/lib/facturacr/configuration.rb +18 -9
  7. data/lib/facturacr/credit_note.rb +24 -13
  8. data/lib/facturacr/data.rb +41 -0
  9. data/lib/facturacr/data_provider.rb +1 -1
  10. data/lib/facturacr/debit_note.rb +25 -13
  11. data/lib/facturacr/document.rb +120 -69
  12. data/lib/facturacr/document/exoneration.rb +17 -12
  13. data/lib/facturacr/document/fax.rb +1 -4
  14. data/lib/facturacr/document/identification_document.rb +7 -10
  15. data/lib/facturacr/document/issuer.rb +31 -32
  16. data/lib/facturacr/document/item.rb +77 -20
  17. data/lib/facturacr/document/location.rb +19 -23
  18. data/lib/facturacr/document/other_charges.rb +56 -0
  19. data/lib/facturacr/document/other_content.rb +30 -0
  20. data/lib/facturacr/document/other_content/price_smart.rb +58 -0
  21. data/lib/facturacr/document/other_text.rb +4 -8
  22. data/lib/facturacr/document/phone.rb +1 -3
  23. data/lib/facturacr/document/phone_type.rb +6 -9
  24. data/lib/facturacr/document/receiver.rb +28 -19
  25. data/lib/facturacr/document/reference.rb +36 -18
  26. data/lib/facturacr/document/regulation.rb +3 -3
  27. data/lib/facturacr/document/summary.rb +54 -22
  28. data/lib/facturacr/document/tax.rb +43 -21
  29. data/lib/facturacr/element.rb +9 -0
  30. data/lib/facturacr/error.rb +11 -0
  31. data/lib/facturacr/export_invoice.rb +38 -0
  32. data/lib/facturacr/invoice.rb +27 -15
  33. data/lib/facturacr/purchase_invoice.rb +39 -0
  34. data/lib/facturacr/reception_message.rb +73 -28
  35. data/lib/facturacr/signed_document.rb +4 -4
  36. data/lib/facturacr/signer/signer.rb +20 -8
  37. data/lib/facturacr/ticket.rb +27 -14
  38. data/lib/facturacr/version.rb +1 -1
  39. data/lib/facturacr/xml_document.rb +46 -29
  40. metadata +15 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5f79a7e9d0f44bbdc3655d3ec903cba6bc87c8a7
4
- data.tar.gz: e9c3a32ada42c6adea6145681dbdf0141a4688af
2
+ SHA256:
3
+ metadata.gz: 5a8fe4de4d95d4c43eadb53200c1ce6b847554a1970fb9cb803ffdd9b3a5ea93
4
+ data.tar.gz: a4ba9d8357de2b21305f5c32577e25433d0c477c4996cfdfdc8b42e1f5665935
5
5
  SHA512:
6
- metadata.gz: b6da6d3d09e8c9e73b647115371e8efae27d652a789a020eb5ceaa19d9eb9e3073fa73442ad27d9e5c6c3167bf235f771e0e816cee8ed4bc875b97fda739fb9c
7
- data.tar.gz: cad88e6a82f1af07418c41c777eb2310115bc6a7baf2767f8587647e811533b4e6cc87d54e85684d0193cf258533c663f1ef334014bf3f49b37c8c74743757e8
6
+ metadata.gz: c339e27c622a15a04f9d55924b40bd78529fc31c284517e6dfa6b42473f1fa99993b8667e1a3b3960872c65cef8f674951a5f820564ed3754e159013ac2d0bd6
7
+ data.tar.gz: 3640e8f8d11d531ad16e801820c9eeb1c3671988338d5cc029548839338ade8ca4b99e467864647940a2851441d1c1a8ade3711d19b92b1bbff9011cc154f4a3
@@ -18,10 +18,10 @@ Gem::Specification.new do |spec|
18
18
  spec.require_paths = ["lib"]
19
19
 
20
20
  spec.add_development_dependency "bundler", "~> 1.10"
21
- spec.add_development_dependency "rake", "~> 10.0"
21
+ spec.add_development_dependency "rake", ">= 12.3.3"
22
22
  spec.add_development_dependency "minitest", '~> 5.11'
23
23
  spec.add_development_dependency "minitest-colorize", '~> 0.0'
24
-
24
+
25
25
  spec.add_dependency 'rest-client', '~> 2.0'
26
26
  spec.add_dependency 'nokogiri', '~> 1.8'
27
27
  spec.add_dependency 'colorize', '~> 0.8'
@@ -1,25 +1,31 @@
1
1
  require 'awesome_print'
2
- require 'facturacr'
3
- require 'facturacr/configuration'
4
- require 'facturacr/document'
5
- require 'facturacr/invoice'
6
- require 'facturacr/credit_note'
7
- require 'facturacr/debit_note'
8
- require 'facturacr/ticket'
9
- require 'facturacr/signed_document'
10
- require 'facturacr/xml_document'
11
- require 'facturacr/api'
12
- require 'facturacr/builder'
13
- require 'facturacr/version'
14
- require 'facturacr/data_provider'
15
- require 'facturacr/signer/signer'
16
- require 'facturacr/reception_message'
2
+
3
+ #require 'facturacr'
4
+ require_relative 'facturacr/configuration'
5
+ require_relative 'facturacr/element'
6
+ require_relative 'facturacr/invoice'
7
+ require_relative 'facturacr/credit_note'
8
+ require_relative 'facturacr/export_invoice'
9
+ require_relative 'facturacr/purchase_invoice'
10
+ require_relative 'facturacr/debit_note'
11
+ require_relative 'facturacr/ticket'
12
+ require_relative 'facturacr/document'
13
+ require_relative 'facturacr/signed_document'
14
+ require_relative 'facturacr/xml_document'
15
+ require_relative 'facturacr/api'
16
+ require_relative 'facturacr/builder'
17
+ require_relative 'facturacr/version'
18
+ require_relative 'facturacr/data_provider'
19
+ require_relative 'facturacr/signer/signer'
20
+ require_relative 'facturacr/reception_message'
21
+ require_relative 'facturacr/error'
22
+ require_relative 'facturacr/data'
17
23
 
18
24
  module FE
19
25
  class << self
20
26
  attr_accessor :configuration
21
27
  end
22
-
28
+
23
29
  def self.configure
24
30
  if self.configuration.nil?
25
31
  self.configuration ||= Configuration.new
@@ -27,13 +33,13 @@ module FE
27
33
  yield(configuration)
28
34
  configuration.read_config_file if configuration.file?
29
35
  end
30
-
36
+
31
37
  def self.root
32
38
  File.dirname __dir__
33
39
  end
34
-
40
+
35
41
  def self.bin
36
42
  File.join root, 'bin'
37
43
  end
38
-
44
+
39
45
  end
@@ -32,17 +32,17 @@ module FE
32
32
  @token
33
33
  rescue => e
34
34
  puts "AUTH ERROR: #{e.message}".red
35
- raise e
35
+ raise FE::Error.new("authentication error: #{e.message}",class: self.class)
36
36
  end
37
37
 
38
38
  def logout
39
39
  url = @authentication_endpoint
40
40
  if @authentication_endpoint.end_with?('token')
41
- url.gsub!("token","logout")
41
+ url = url.gsub("token","logout")
42
42
  else
43
43
  url += "/logout"
44
44
  end
45
- response = RestClient.post url, logout_data
45
+ RestClient.post url, logout_data
46
46
  rescue => e
47
47
  puts "LOGOUT ERROR: #{e.message}".red
48
48
  end
@@ -57,7 +57,8 @@ module FE
57
57
  return true
58
58
  end
59
59
  rescue => e
60
- @errors[:request] = {message: e.message, response: e.response}
60
+ @errors[:request] = {message: e.message}
61
+ @errors[:response] = e.response if e.respond_to?(:response)
61
62
  return false
62
63
  end
63
64
 
@@ -134,7 +134,7 @@ module FE
134
134
  else
135
135
  summary = args[:summary]
136
136
  end
137
- FE::Invoice.new date: args[:date], issuer: issuer, receiver: receiver, number: args[:number], items: items, condition: args[:condition], credit_term: args[:credit_term], summary: summary, security_code: args[:security_code], document_situation: args[:document_situation]
137
+ FE::Invoice.new date: args[:date], issuer: issuer, receiver: receiver, number: args[:number], items: items, condition: args[:condition], credit_term: args[:credit_term], summary: summary, security_code: args[:security_code], document_situation: args[:document_situation], version: args[:version], economic_activity: args[:economic_activity]
138
138
  end
139
139
 
140
140
  def ticket(args = {})
@@ -165,7 +165,7 @@ module FE
165
165
  else
166
166
  summary = args[:summary]
167
167
  end
168
- FE::Ticket.new date: args[:date], issuer: issuer, receiver: receiver, number: args[:number], items: items, condition: args[:condition], credit_term: args[:credit_term], summary: summary, security_code: args[:security_code], document_situation: args[:document_situation]
168
+ FE::Ticket.new date: args[:date], issuer: issuer, receiver: receiver, number: args[:number], items: items, condition: args[:condition], credit_term: args[:credit_term], summary: summary, security_code: args[:security_code], document_situation: args[:document_situation], version: args[:version], economic_activity: args[:economic_activity]
169
169
  end
170
170
 
171
171
 
@@ -207,7 +207,7 @@ module FE
207
207
  references = args[:references]
208
208
  end
209
209
 
210
- FE::CreditNote.new date: args[:date], issuer: issuer, receiver: receiver, number: args[:number], items: items, condition: args[:condition], credit_term: args[:credit_term], summary: summary, security_code: args[:security_code], document_situation: args[:document_situation], references: references
210
+ FE::CreditNote.new date: args[:date], issuer: issuer, receiver: receiver, number: args[:number], items: items, condition: args[:condition], credit_term: args[:credit_term], summary: summary, security_code: args[:security_code], document_situation: args[:document_situation], references: references, version: args[:version], economic_activity: args[:economic_activity]
211
211
  end
212
212
 
213
213
  def debit_note(args = {})
@@ -248,7 +248,7 @@ module FE
248
248
  references = args[:references]
249
249
  end
250
250
 
251
- FE::DebitNote.new date: args[:date], issuer: issuer, receiver: receiver, number: args[:number], items: items, condition: args[:condition], credit_term: args[:credit_term], summary: summary, security_code: args[:security_code], document_situation: args[:document_situation], references: references
251
+ FE::DebitNote.new date: args[:date], issuer: issuer, receiver: receiver, number: args[:number], items: items, condition: args[:condition], credit_term: args[:credit_term], summary: summary, security_code: args[:security_code], document_situation: args[:document_situation], references: references, version: args[:version], economic_activity: args[:economic_activity]
252
252
  end
253
253
 
254
254
  def reception_message(args={})
@@ -2,7 +2,7 @@ require 'yaml'
2
2
  require 'erb'
3
3
  module FE
4
4
  class Configuration
5
-
5
+
6
6
  attr_accessor :api_username
7
7
  attr_accessor :api_password
8
8
  attr_accessor :key_path
@@ -13,8 +13,9 @@ module FE
13
13
  attr_accessor :environment
14
14
  attr_accessor :file_path
15
15
  attr_accessor :mode
16
-
17
-
16
+ attr_accessor :version
17
+
18
+
18
19
  def initialize
19
20
  @environment = "development"
20
21
  @mode = :manual
@@ -26,9 +27,9 @@ module FE
26
27
  @documents_endpoint = "https://api.comprobanteselectronicos.go.cr/recepcion-sandbox/v1"
27
28
  @authentication_endpoint = "https://idp.comprobanteselectronicos.go.cr/auth/realms/rut-stag/protocol/openid-connect"
28
29
  end
29
-
30
+
30
31
  def read_config_file
31
- if file? && @file_path && File.exists?(@file_path)
32
+ if file? && @file_path && File.exist?(@file_path)
32
33
  template = ERB.new(File.read(@file_path))
33
34
  result = YAML.load(template.result(binding))
34
35
  result[@environment].each do |k,v|
@@ -38,14 +39,22 @@ module FE
38
39
  end
39
40
  end
40
41
  end
41
-
42
+
42
43
  def manual?
43
44
  @mode.to_sym.eql?(:manual)
44
45
  end
45
-
46
+
46
47
  def file?
47
48
  @mode.to_sym.eql?(:file)
48
49
  end
49
-
50
+
51
+ def version_42?
52
+ version.eql?('4.2')
53
+ end
54
+
55
+ def version_43?
56
+ version.eql?('4.3')
57
+ end
58
+
50
59
  end
51
- end
60
+ end
@@ -1,34 +1,45 @@
1
1
  require 'facturacr/document/regulation'
2
2
  module FE
3
-
3
+
4
4
  class CreditNote < Document
5
-
5
+ NAMESPACES ={
6
+ "4.2" => {
7
+ "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
8
+ "xmlns:xsd"=>"http://www.w3.org/2001/XMLSchema",
9
+ "xmlns"=>"https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/notaCreditoElectronica"#,
10
+ },
11
+ "4.3" => {
12
+ "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
13
+ "xmlns:xsd"=>"http://www.w3.org/2001/XMLSchema",
14
+ "xmlns"=>"https://cdn.comprobanteselectronicos.go.cr/xml-schemas/v4.3/notaCreditoElectronica"#,
15
+ }
16
+ }
17
+ DOCUMENT_TYPE = "03"
6
18
  def initialize(args={})
19
+ @version = args[:version]
20
+ @economic_activity = args[:economic_activity]
7
21
  @date = args[:date]
8
22
  @issuer = args[:issuer]
9
23
  @receiver = args[:receiver]
10
24
  @items = args[:items]
11
25
  @number = args[:number]
12
26
  @condition = args[:condition]
13
- @payment_type = args[:payment_type] || "01"
14
- @document_type = "03"
27
+ @payment_type = args[:payment_type] || ["01"]
28
+ @document_type = DOCUMENT_TYPE
15
29
  @credit_term = args[:credit_term]
16
30
  @summary = args[:summary]
17
31
  @regulation = args[:regulation] ||= FE::Document::Regulation.new
18
32
  @security_code = args[:security_code]
19
33
  @document_situation = args[:document_situation]
20
34
  @references = args[:references]
21
- @namespaces = {
22
- "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
23
- "xmlns:xsd"=>"http://www.w3.org/2001/XMLSchema",
24
- "xmlns"=>"https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/notaCreditoElectronica"#,
25
- }
35
+ @other_charges = args[:other_charges]
36
+ @namespaces = NAMESPACES[@version]
26
37
  @others = args[:others] || []
27
38
  end
28
-
39
+
29
40
  def document_tag
30
41
  "NotaCreditoElectronica"
31
42
  end
32
-
33
- end
34
- end
43
+
44
+ end
45
+ end
@@ -0,0 +1,41 @@
1
+ require 'json'
2
+ require 'rest-client'
3
+ require 'active_support/core_ext/hash/indifferent_access'
4
+
5
+ module FE
6
+ class Data
7
+
8
+ ENDPOINT = "https://api.hacienda.go.cr"
9
+
10
+ def self.contributor(id_number)
11
+ response = RestClient.get "#{ENDPOINT}/fe/ae?identificacion=#{id_number}"
12
+ return JSON.parse(response.body).with_indifferent_access
13
+ rescue => e
14
+ puts "FE::Data.contributor(#{id_number}) #{e.message}"
15
+ return nil
16
+ end
17
+
18
+ def self.exchange_rate(currency = "USD")
19
+ if currency.eql?("USD")
20
+ path = "tc/dolar"
21
+ elsif currency.eql?("EUR")
22
+ path = "tc/euro"
23
+ else
24
+ raise "#{currency} is not a valid argument"
25
+ end
26
+ response = RestClient.get "#{ENDPOINT}/indicadores/#{path}"
27
+ return JSON.parse(response.body).with_indifferent_access
28
+ rescue => e
29
+ puts "FE::Data.exchange_rate(#{currency}) #{e.message}"
30
+ return nil
31
+ end
32
+
33
+ def self.exonerations(id_number)
34
+ response = RestClient.get "#{ENDPOINT}/fe/ex?identificacion=#{id_number}"
35
+ return JSON.parse(response.body).with_indifferent_access
36
+ rescue => e
37
+ puts "FE::Data.exonerations(#{id_number}) #{e.message}"
38
+ return nil
39
+ end
40
+ end
41
+ end
@@ -8,7 +8,7 @@ module FE
8
8
  def initialize(source, data)
9
9
  source = source.to_s.to_sym
10
10
  raise ArgumentError, "source (#{source}) is not valid" if !SOURCES.include?(source)
11
- raise ArgumentError, "#{data} does not exist" if source.eql?(:file) && !File.exists?(data)
11
+ raise ArgumentError, "#{data} does not exist" if source.eql?(:file) && !File.exist?(data)
12
12
 
13
13
  if source.eql?(:string)
14
14
  @contents = data
@@ -1,34 +1,46 @@
1
1
  require 'facturacr/document/regulation'
2
2
  module FE
3
-
3
+
4
4
  class DebitNote < Document
5
-
5
+
6
+ NAMESPACES ={
7
+ "4.2" => {
8
+ "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
9
+ "xmlns:xsd"=>"http://www.w3.org/2001/XMLSchema",
10
+ "xmlns"=>"https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/notaDebitoElectronica"
11
+ },
12
+ "4.3" => {
13
+ "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
14
+ "xmlns:xsd"=>"http://www.w3.org/2001/XMLSchema",
15
+ "xmlns"=>"https://cdn.comprobanteselectronicos.go.cr/xml-schemas/v4.3/notaDebitoElectronica"#,
16
+ }
17
+ }
18
+ DOCUMENT_TYPE = "02"
6
19
  def initialize(args={})
20
+ @version = args[:version]
21
+ @economic_activity = args[:economic_activity]
7
22
  @date = args[:date]
8
23
  @issuer = args[:issuer]
9
24
  @receiver = args[:receiver]
10
25
  @items = args[:items]
11
26
  @number = args[:number]
12
27
  @condition = args[:condition]
13
- @payment_type = args[:payment_type] || "01"
14
- @document_type = "02"
28
+ @payment_type = args[:payment_type] || ["01"]
29
+ @document_type = DOCUMENT_TYPE
15
30
  @credit_term = args[:credit_term]
16
31
  @summary = args[:summary]
17
32
  @regulation = args[:regulation] ||= FE::Document::Regulation.new
18
33
  @security_code = args[:security_code]
19
34
  @document_situation = args[:document_situation]
20
35
  @references = args[:references]
21
- @namespaces = {
22
- "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
23
- "xmlns:xsd"=>"http://www.w3.org/2001/XMLSchema",
24
- "xmlns"=>"https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/notaDebitoElectronica"
25
- }
36
+ @other_charges = args[:other_charges]
37
+ @namespaces = NAMESPACES[@version]
26
38
  @others = args[:others] || []
27
39
  end
28
-
40
+
29
41
  def document_tag
30
42
  "NotaDebitoElectronica"
31
43
  end
32
-
33
- end
34
- end
44
+
45
+ end
46
+ end
@@ -1,16 +1,19 @@
1
1
  require 'active_model'
2
2
 
3
- module FE
3
+ module FE
4
4
  class Document
5
5
  include ActiveModel::Validations
6
-
6
+
7
7
  CONDITIONS = {
8
- "01"=>"Contado",
9
- "02"=>"Crédito",
10
- "03"=>"Consignación",
11
- "04"=>"Apartado",
12
- "05"=>"Arrendamiento con Opción de Compra",
8
+ "01"=>"Contado",
9
+ "02"=>"Crédito",
10
+ "03"=>"Consignación",
11
+ "04"=>"Apartado",
12
+ "05"=>"Arrendamiento con Opción de Compra",
13
13
  "06"=>"Arrendamiento en Función Financiera",
14
+ "07"=>"Cobro a favor de un tercero",
15
+ "08"=>"Servicios prestados al Estado a crédito ",
16
+ "09"=>"Pago del servicios prestado al Estado ",
14
17
  "99"=>"Otros"
15
18
  }.freeze
16
19
  PAYMENT_TYPES = {
@@ -29,47 +32,50 @@ module FE
29
32
  "05"=> "Nota de despacho",
30
33
  "06"=> "Contrato",
31
34
  "07"=> "Procedimiento",
32
- "08"=> "Comprobante Emitido en Contingencia",
33
- "99"=> "Otros"
34
-
35
+ "08"=> "Factura Electrónica de compra",
36
+ "09"=> "Factura Electronica de exportación"
35
37
  }.freeze
36
38
  DOCUMENT_SITUATION = {
37
39
  "1" => "Normal",
38
40
  "2" => "Contingencia",
39
41
  "3" => "Sin Internet"
40
42
  }.freeze
41
-
42
- attr_accessor :serial, :date, :issuer, :receiver, :condition, :credit_term,
43
- :payment_type, :service_type, :reference_information,
44
- :regulation, :number, :document_type, :security_code,
45
- :items, :references, :namespaces, :summary, :document_situation,
46
- :headquarters, :terminal, :others, :key
47
-
43
+
44
+ attr_writer :headquarters, :terminal, :key
45
+ attr_accessor :serial, :date, :issuer, :receiver, :condition, :credit_term,
46
+ :payment_type, :service_type, :reference_information,
47
+ :regulation, :number, :document_type, :security_code,
48
+ :items, :references, :namespaces, :summary, :document_situation,
49
+ :headquarters, :terminal, :others, :key, :economic_activity, :other_charges, :version
50
+ validates :version, presence: true
51
+ validates :economic_activity, presence: true, if: ->{ version.eql?("4.3") }
48
52
  validates :date, presence: true
49
53
  validates :number, presence: true
50
54
  validates :issuer, presence: true
55
+ validates :receiver, presence: true, if: -> {document_type.eql?("01") || document_type.eql?("08")}
51
56
  validates :condition, presence: true, inclusion: CONDITIONS.keys
52
- validates :credit_term, presence: true, if: ->{condition.eql?("02")}
53
- validates :payment_type, presence: true, inclusion: PAYMENT_TYPES.keys
57
+ validates :credit_term, presence: true, if: ->{ condition.eql?("02") }
54
58
  validates :document_type, presence: true, inclusion: DOCUMENT_TYPES.keys
55
59
  validates :document_situation, presence: true, inclusion: DOCUMENT_SITUATION.keys
56
60
  validates :summary, presence: true
57
- validates :regulation, presence: true
61
+ validates :regulation, presence: true, if: ->{ version.eql?("4.2") }
58
62
  validates :security_code, presence: true, length: {is: 8}
59
63
  validates :references, presence: true, if: -> {document_type.eql?("02") || document_type.eql?("03")}
60
-
61
-
64
+ validates :items, presence:true
65
+ validate :payment_types_ok?
66
+ validate :other_charges_ok?, if: -> {@other_charges.present?}
67
+
62
68
  def initialize
63
- raise "Subclasses must implement this method"
69
+ raise FE::Error "Subclasses must implement this method"
64
70
  end
65
-
71
+
66
72
  def document_name
67
- raise "Subclasses must implement this method"
73
+ raise FE::Error "Subclasses must implement this method"
68
74
  end
69
-
75
+
70
76
  def key
71
77
  @key ||= begin
72
- raise "Documento inválido: #{errors.messages}" unless valid?
78
+ raise "Documento inválido: #{errors.messages}" unless valid?
73
79
  country = "506"
74
80
  day = "%02d" % @date.day
75
81
  month = "%02d" % @date.month
@@ -81,69 +87,92 @@ module FE
81
87
 
82
88
  result = "#{country}#{day}#{month}#{year}#{id_number}#{sequence}#{type}#{security_code}"
83
89
  raise "The key is invalid: #{result}" unless result.length.eql?(50)
84
-
90
+
85
91
  result
86
92
  end
87
93
  end
88
-
94
+
89
95
  def headquarters
90
96
  @headquarters ||= "001"
91
97
  end
92
-
98
+
93
99
  def terminal
94
100
  @terminal ||= "00001"
95
- end
96
-
101
+ end
102
+
97
103
  def sequence
98
104
  cons = ("%010d" % @number)
99
105
  "#{headquarters}#{terminal}#{@document_type}#{cons}"
100
106
  end
101
-
107
+
108
+ def version_42?
109
+ @version.eql?("4.2")
110
+ end
111
+
112
+ def version_43?
113
+ @version.eql?("4.3")
114
+ end
115
+
102
116
  def build_xml
103
- raise "Documento inválido: #{errors.messages}" unless valid?
117
+ raise FE::Error.new "Documento inválido #{errors.messages}", class: self.class, messages: errors.messages unless valid?
104
118
  builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8')
105
-
119
+
106
120
  builder.send(document_tag, @namespaces) do |xml|
107
121
  xml.Clave key
122
+ xml.CodigoActividad @economic_activity if version_43?
108
123
  xml.NumeroConsecutivo sequence
109
124
  xml.FechaEmision @date.xmlschema
110
- issuer.build_xml(xml)
111
- receiver.build_xml(xml) if receiver.present?
125
+ issuer.build_xml(xml, self)
126
+ receiver.build_xml(xml,self) if receiver.present?
112
127
  xml.CondicionVenta @condition
113
128
  xml.PlazoCredito @credit_term if @credit_term.present? && @condition.eql?("02")
114
- xml.MedioPago @payment_type
129
+
130
+ @payment_type.each do |pt|
131
+ @summary.with_credit_card = true if pt.eql?("02")
132
+ xml.MedioPago pt
133
+ end
134
+
135
+
115
136
  xml.DetalleServicio do |x|
116
137
  @items.each do |item|
117
- item.build_xml(x)
138
+ item.build_xml(x, self)
118
139
  end
119
140
  end
120
-
121
- summary.build_xml(xml)
122
-
141
+
142
+ if other_charges.present?
143
+ @other_charges.each do |other_charge|
144
+ other_charge.build_xml(xml, self)
145
+ end
146
+ end
147
+
148
+ #other_charges.build_xml(xml,self) if other_charges.present? && version_43? # see this
149
+
150
+ summary.build_xml(xml, self)
151
+
123
152
  if references.present?
124
153
  references.each do |r|
125
- r.build_xml(xml)
154
+ r.build_xml(xml, self)
126
155
  end
127
156
  end
128
-
129
- regulation.build_xml(xml)
130
-
157
+
158
+ regulation.build_xml(xml,self) if version_42?
159
+
131
160
  if others.any?
132
161
  xml.Otros do |x|
133
162
  @others.each do |o|
134
- o.build_xml(x)
163
+ o.build_xml(x, self)
135
164
  end
136
165
  end
137
166
  end
138
167
  end
139
-
168
+
140
169
  builder
141
170
  end
142
-
171
+
143
172
  def generate
144
173
  build_xml.to_xml(:save_with => Nokogiri::XML::Node::SaveOptions::AS_XML)
145
174
  end
146
-
175
+
147
176
  def api_payload
148
177
  payload = {}
149
178
  payload[:clave] = key
@@ -158,27 +187,49 @@ module FE
158
187
  numeroIdentificacion: @receiver.identification_document.id_number
159
188
  }
160
189
  end
161
-
190
+
162
191
  payload
163
192
  end
164
-
193
+
194
+ private
195
+
196
+ def other_charges_ok?
197
+ if @other_charges.is_a?(Array)
198
+ errors.add :other_charges, "invalid other_charges: the length can't be greater than 15" if @other_charges.length > 15
199
+ errors.add :other_charges, "invalid other_charges: not included" unless @other_charges.all? {|i| FE::Document::OtherCharges::OTHER_DOCUMENT_TYPES.include?(i.document_type)}
200
+ else
201
+ errors.add :other_charges, "invalid other_charges: not array"
202
+ end
203
+ end
204
+
205
+ def payment_types_ok?
206
+ errors.add :payment_type, "missing payment type" if @payment_type.nil?
207
+ if @payment_type.is_a?(Array)
208
+ errors.add :payment_type, "invalid payment types: not included" unless @payment_type.all? {|i| PAYMENT_TYPES.include?(i)}
209
+ else
210
+ errors.add :payment_type, "invalid payment type: not array"
211
+ end
212
+
213
+ end
214
+
165
215
  end
166
-
167
-
168
216
  end
169
217
 
170
- require 'facturacr/document/code'
171
- require 'facturacr/document/exoneration'
172
- require 'facturacr/document/fax'
173
- require 'facturacr/document/identification_document'
174
- require 'facturacr/document/issuer'
175
- require 'facturacr/document/item'
176
- require 'facturacr/document/location'
177
- require 'facturacr/document/phone_type'
178
- require 'facturacr/document/phone'
179
- require 'facturacr/document/receiver'
180
- require 'facturacr/document/reference'
181
- require 'facturacr/document/regulation'
182
- require 'facturacr/document/summary'
183
- require 'facturacr/document/tax'
184
- require 'facturacr/document/other_text'
218
+ require_relative 'document/code'
219
+ require_relative 'document/exoneration'
220
+ require_relative 'document/fax'
221
+ require_relative 'document/identification_document'
222
+ require_relative 'document/issuer'
223
+ require_relative 'document/item'
224
+ require_relative 'document/location'
225
+ require_relative 'document/phone_type'
226
+ require_relative 'document/phone'
227
+ require_relative 'document/fax'
228
+ require_relative 'document/receiver'
229
+ require_relative 'document/reference'
230
+ require_relative 'document/regulation'
231
+ require_relative 'document/summary'
232
+ require_relative 'document/tax'
233
+ require_relative 'document/other_text'
234
+ require_relative 'document/other_content'
235
+ require_relative 'document/other_charges'