facturacr 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 442248d98ebb602ee4d8f647bf9a24939b07e87a
4
- data.tar.gz: d6786825ba580d22c565b0714a744fadf34f5347
3
+ metadata.gz: 5fe54ad4526251387084b74247d3897b87781a56
4
+ data.tar.gz: 549cdc504c1ee37a4cac7c15cc424031fe043c0f
5
5
  SHA512:
6
- metadata.gz: 68d71ab7ae6715f6e61fbc92e09ca4da4d062e2ef9bc1c215ebea38c6bf4f865f9214a2344e48463f6ec3b3bda71fd1855de64b6b58e4a994fa7b65a0daf90df
7
- data.tar.gz: cc15f59583e0d342fd11148a948e48137abf52ae27a2886e7e151d2add273d69628f97754142ea6c9d0f70a3d406686eaa1f7e81093b2ae3c9df8a2b9a0be72c
6
+ metadata.gz: 0dcf0d1781a0be675f4a33053dd834b6c60a1e6e0d6e8a2a4d7b82bdbe3ae63aa8549664b6e4f281104175daa50969eb520c8447051ab827359dd9700e14a343
7
+ data.tar.gz: 8ca8978495e86e774cdb566fb6162d6ea112c369e84b70ce46f7c54100b05dfd31757a4e473c4eec48813e267c823f42d5050b845886f73c6fac8a21eb0a58b0
data/README.md CHANGED
@@ -30,45 +30,45 @@ O instale el gem
30
30
  Para generar documentos:
31
31
 
32
32
  ```ruby
33
- require 'facturacr'
33
+ require 'facturacr'
34
34
 
35
- id_document = FE::Document::IdentificationDocument.new type: "01", number: "112345678"
36
- phone = FE::Document::Phone.new country_code: "506", "22222222"
37
- location = FE::Document::Location.new province: "1",county: "01", district: "01", others: "Otras señas"
38
- issuer = FE::Document::Issuer.new name: "EMISON EJEMPLO", identification_document: id_document, location: location, phone: phone, email: "emisor@ejemplo.com"
35
+ id_document = FE::Document::IdentificationDocument.new type: "01", number: "112345678"
36
+ phone = FE::Document::Phone.new country_code: "506", "22222222"
37
+ location = FE::Document::Location.new province: "1",county: "01", district: "01", others: "Otras señas"
38
+ issuer = FE::Document::Issuer.new name: "EMISON EJEMPLO", identification_document: id_document, location: location, phone: phone, email: "emisor@ejemplo.com"
39
39
 
40
- reciever_id_document = FE::Document::IdentificationDocument.new type: "02", number: "3102123456"
41
- receiver = FE::Document::Receiver.new name: "RECEPTOR EJEMPLO", identification_document: id_document
40
+ reciever_id_document = FE::Document::IdentificationDocument.new type: "02", number: "3102123456"
41
+ receiver = FE::Document::Receiver.new name: "RECEPTOR EJEMPLO", identification_document: id_document
42
42
 
43
- items = []
44
- items << FE::Document::Item.new(code: "001", line_number: 1, quantity: 1, unit: "Sp", description: "Desarrollo de Software y Mantenimiento", unit_price: 300, subtotal: 300, net_total: 300, total: 300)
45
- taxes = [FE::Document::Tax.new(code: "01", rate: 13, total: (100 * 0.13))]
46
- items << FE::Document::Item.new(code: "002", line_number: 2, quantity: 2, unit: "Unid", description: "Impresora de POS", unit_price: 50, total: 100, taxes: taxes, net_total: 113, subtotal: 100)
47
- summary = FE::Document::Summary.new currency: "USD", exchange_rate: 575, services_exent_total: 300, goods_taxable_total: 100, exent_total: 300, taxable_total: 100, subtotal: 400, gross_total: 400, tax_total: 13, net_total: 413
43
+ items = []
44
+ items << FE::Document::Item.new(code: "001", line_number: 1, quantity: 1, unit: "Sp", description: "Desarrollo de Software y Mantenimiento", unit_price: 300, subtotal: 300, net_total: 300, total: 300)
45
+ taxes = [FE::Document::Tax.new(code: "01", rate: 13, total: (100 * 0.13))]
46
+ items << FE::Document::Item.new(code: "002", line_number: 2, quantity: 2, unit: "Unid", description: "Impresora de POS", unit_price: 50, total: 100, taxes: taxes, net_total: 113, subtotal: 100)
47
+ summary = FE::Document::Summary.new currency: "USD", exchange_rate: 575, services_exent_total: 300, goods_taxable_total: 100, exent_total: 300, taxable_total: 100, subtotal: 400, gross_total: 400, tax_total: 13, net_total: 413
48
48
 
49
49
 
50
- invoice = FE::Invoice.new date: date, issuer: issuer, receiver: receiver, number: number, items: items, condition: condition, credit_term: credit_term, summary: summary, security_code: "12345678", document_situation: "1"
50
+ invoice = FE::Invoice.new date: date, issuer: issuer, receiver: receiver, number: number, items: items, condition: condition, credit_term: credit_term, summary: summary, security_code: "12345678", document_situation: "1"
51
51
 
52
- # Para generar el XML como string
53
- xml = invoice.generate
54
-
55
- # Escribir el archivo
56
- File.open("/path/to/file.xml","w"){|f| f.write(xml)}
52
+ # Para generar el XML como string
53
+ xml = invoice.generate
54
+
55
+ # Escribir el archivo
56
+ File.open("/path/to/file.xml","w"){|f| f.write(xml)}
57
57
  ```
58
58
 
59
59
  Para configurar el API / Firmador:
60
60
  ```ruby
61
61
 
62
- FE.configure do |config|
63
- config.api_username "su_usuario_api_atv"
64
- config.api_password = "su_password_api_atv"
65
- config.key_path = "tmp/llave_criptografica.p12"
66
- config.key_password = "99999999999999"
67
- # api hacienda: valores default
68
- config.api_client_id = 'api-stag'
69
- config.documents_endpoint = "https://api.comprobanteselectronicos.go.cr/recepcion-sandbox/v1"
70
- config.authentication_endpoint = "https://idp.comprobanteselectronicos.go.cr/auth/realms/rut-stag/protocol/openid-connect/token"s
71
- end
62
+ FE.configure do |config|
63
+ config.api_username "su_usuario_api_atv"
64
+ config.api_password = "su_password_api_atv"
65
+ config.key_path = "tmp/llave_criptografica.p12"
66
+ config.key_password = "99999999999999"
67
+ # api hacienda: valores default
68
+ config.api_client_id = 'api-stag'
69
+ config.documents_endpoint = "https://api.comprobanteselectronicos.go.cr/recepcion-sandbox/v1"
70
+ config.authentication_endpoint = "https://idp.comprobanteselectronicos.go.cr/auth/realms/rut-stag/protocol/openid-connect/token"s
71
+ end
72
72
  ```
73
73
 
74
74
  Para firmar documentos. (Debe tener java instalado)
@@ -81,27 +81,27 @@ Para firmar documentos. (Debe tener java instalado)
81
81
 
82
82
  Para enviar documentos al API
83
83
  ```ruby
84
-
85
- api = FE::API.new
86
- # document is FE::Document
87
- signed_document = FE::SignedDocument.new(document,path)
88
- api = FE::Api.new
89
- if api.send_document(signed_document.payload)
90
- puts "Document sent!"
91
- else
92
- puts "Error: #{api.errors}"
93
- end
84
+
85
+ api = FE::API.new
86
+ # document is FE::Document
87
+ signed_document = FE::SignedDocument.new(document,path)
88
+ api = FE::Api.new
89
+ if api.send_document(signed_document.payload)
90
+ puts "Document sent!"
91
+ else
92
+ puts "Error: #{api.errors}"
93
+ end
94
94
  ```
95
95
 
96
96
  Para chequear el estatus del documento
97
97
  ```ruby
98
98
 
99
- api = FE::API.new
100
- FE::Utils.configure(options[:config_file])
101
- api = FE::Api.new
102
- document_status = api.get_document_status(key)
103
- puts document_status.to_h
104
- #=> {key: "50601011600310112345600100010100000000011999999999", date: "2016-01-01T00:00:00-0600", status: "aceptado", datails: ""}
99
+ api = FE::API.new
100
+ FE::Utils.configure(options[:config_file])
101
+ api = FE::Api.new
102
+ document_status = api.get_document_status(key)
103
+ puts document_status.to_h
104
+ #=> {key: "50601011600310112345600100010100000000011999999999", date: "2016-01-01T00:00:00-0600", status: "aceptado", datails: ""}
105
105
  ```
106
106
 
107
107
  ## Lína de comando
@@ -112,15 +112,22 @@ Para utilziar la línea de comando y generar documentos de prueba, debe generar
112
112
 
113
113
  Modifique los archivos config.yml y data.yml para utilziar la línea de comando
114
114
 
115
- Para generar documentos:
115
+ Resumen de la funcionalidad de la línea de comando
116
116
 
117
- $ facturacr generate help
118
-
117
+ $ facturacr help
119
118
  Commands:
120
- facturacr generate credit_note # generates an XML credit note
121
- facturacr generate debit_note # generates an XML debit note
122
- facturacr generate help [COMMAND] # Describe subcommands or one specific subcommand
123
- facturacr generate invoice # generates an XML invoice
119
+ facturacr check KEY # checks a sent document in the api
120
+ facturacr generate DOCUMENT ARGS # generate xml documents
121
+ facturacr generate credit_note # generates an XML credit note
122
+ facturacr generate debit_note # generates an XML debit note
123
+ facturacr generate help [COMMAND] # Describe subcommands or one specific subcommand
124
+ facturacr generate invoice # generates an XML invoice
125
+ facturacr generate reception_message # generate an XML reception message
126
+ facturacr generate ticket # generates an XML ticket
127
+ facturacr help [COMMAND] # Describe available commands or one specific command
128
+ facturacr send_document SIGNED_XML # sends the SIGNED_XML file to the API
129
+ facturacr setup PATH # will create a tmp directory with a sample config file and a sample data file at the specified path.
130
+ facturacr sign XML_IN XML_OUT # signs the xml document and stores the signed document in the output path
124
131
 
125
132
  Por ejemplo, para generar una factura
126
133
 
@@ -156,7 +163,7 @@ Adicionalmente se pueden especificar las opciones para firma y enviar a hacienda
156
163
 
157
164
  Para firmar documentos
158
165
 
159
- $ facturacr sign_document /path/to/unsigned.xml /path/to/signed.xml
166
+ $ facturacr sign /path/to/unsigned.xml /path/to/signed.xml
160
167
 
161
168
  Para enviar documentos
162
169
 
data/lib/facturacr/api.rb CHANGED
@@ -24,7 +24,8 @@ module FE
24
24
 
25
25
  @token
26
26
  rescue => e
27
- raise "AUTH ERROR"
27
+ puts "AUTH ERROR: #{e.message}".red
28
+ raise e
28
29
  end
29
30
 
30
31
 
@@ -45,7 +46,13 @@ module FE
45
46
 
46
47
  def get_document(key)
47
48
  authenticate
48
- response = RestClient.get "#{@document_endpoint}/comprogantes/#{key}", {:Authorization=> "bearer #{@token}", content_type: :json}
49
+ response = RestClient.get "#{@document_endpoint}/comprobantes/#{key}", {:Authorization=> "bearer #{@token}", content_type: :json}
50
+ JSON.parse(response)
51
+ end
52
+
53
+ def get_documents
54
+ authenticate
55
+ response = RescClient.get "#{@document_endpoint}/comprobantes", {:Authorization => "bearer #{@token}", content_type: :json }
49
56
  JSON.parse(response)
50
57
  end
51
58
 
@@ -132,6 +132,38 @@ module FE
132
132
  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]
133
133
  end
134
134
 
135
+ def ticket(args = {})
136
+ if args[:issuer].is_a?(Hash)
137
+ issuer = self.issuer(args[:issuer])
138
+ else
139
+ issuer = args[:issuer]
140
+ end
141
+
142
+ if args[:receiver].is_a?(Hash)
143
+ receiver = self.receiver(args[:receiver])
144
+ else
145
+ receiver = args[:receiver]
146
+ end
147
+
148
+ if args[:items].is_a?(Array) && args[:items].first.is_a?(Hash)
149
+ tmp_items = []
150
+ args[:items].each do |i|
151
+ tmp_items << self.item(i)
152
+ end
153
+ items = tmp_items
154
+ else
155
+ items = args[:items]
156
+ end
157
+
158
+ if args[:summary].is_a?(Hash)
159
+ summary = self.summary(args[:summary])
160
+ else
161
+ summary = args[:summary]
162
+ end
163
+ 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]
164
+ end
165
+
166
+
135
167
  def credit_note(args = {})
136
168
  if args[:issuer].is_a?(Hash)
137
169
  issuer = self.issuer(args[:issuer])
@@ -214,6 +246,13 @@ module FE
214
246
  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
215
247
  end
216
248
 
249
+ def reception_message(args={})
250
+ FE::ReceptionMessage.new number: args[:number], date: args[:date], key: args[:key],
251
+ issuer_id_number: args[:issuer_id_number], issuer_id_type: args[:issuer_id_type],
252
+ receiver_id_number: args[:receiver_id_number], receiver_id_type: args[:receiver_id_type],
253
+ message: args[:message], details: args[:details], tax: args[:tax], total: args[:total], security_code: args[:security_code], document_situation: args[:document_situation]
254
+ end
255
+
217
256
 
218
257
  def reference(args={})
219
258
  FE::Document::Reference.new args
@@ -19,7 +19,7 @@ module FE
19
19
  invoice.number = options[:number].to_i if options[:number].present?
20
20
 
21
21
  if options[:output_path]
22
- output_path = output_path
22
+ output_path = options[:output_path]
23
23
  else
24
24
  output_path = "tmp/#{invoice.key}.xml"
25
25
  end
@@ -55,7 +55,7 @@ module FE
55
55
  credit_note.number = options[:number].to_i if options[:number].present?
56
56
 
57
57
  if options[:output_path]
58
- output_path = output_path
58
+ output_path = options[:output_path]
59
59
  else
60
60
  output_path = "tmp/#{credit_note.key}.xml"
61
61
  end
@@ -90,7 +90,7 @@ module FE
90
90
  debit_note.number = options[:number].to_i if options[:number].present?
91
91
 
92
92
  if options[:output_path]
93
- output_path = output_path
93
+ output_path = options[:output_path]
94
94
  else
95
95
  output_path = "tmp/#{debit_note.key}.xml"
96
96
  end
@@ -102,6 +102,82 @@ module FE
102
102
 
103
103
  end
104
104
 
105
+ desc "ticket", "generates an XML ticket"
106
+ method_option :config_file, aliases: '-c', desc: "default configuration file", default: "tmp/config.yml"
107
+ method_option :number, aliases: '-n', desc: "set the number of the document"
108
+ method_option :sign, type: :boolean, default: false
109
+ method_option :send, type: :boolean, default: false
110
+ method_option :data_path, default: "tmp/data.yml"
111
+ method_option :output_path, desc: "path to save the output"
112
+ def ticket
113
+ data = YAML.load_file(options[:data_path]).with_indifferent_access
114
+ builder = FE::Builder.new
115
+
116
+ ticket = builder.ticket(data[:document])
117
+ ticket.date = Time.now
118
+ ticket.number = options[:number].to_i if options[:number].present?
119
+
120
+ if options[:output_path]
121
+ output_path = options[:output_path]
122
+ else
123
+ output_path = "tmp/#{ticket.key}.xml"
124
+ end
125
+
126
+ write(ticket, output_path)
127
+ print_details(ticket)
128
+ sign(output_path, options) if options[:sign]
129
+ send_document("#{output_path}.signed.xml") if options[:sign] && options[:send]
130
+
131
+ end
132
+ desc "reception_message", "generate an XML reception message"
133
+ method_option :xml_in, aliases: '-i', desc: "path to the xml invoice to accept"
134
+ method_option :number, aliases: '-n', desc: "the number of the document"
135
+ method_option :output_path, desc: "path to save the output"
136
+ method_option :sign, type: :boolean, default: false
137
+ method_option :send, type: :boolean, default: false
138
+ method_option :action, aliases: '-a', desc: "action 1=total 2=partial 3=reject", limited_to: [1,2,3]
139
+ method_option :details, desc: "details to include"
140
+ method_option :document_situation, desc: "the situation of the document", default: "1"
141
+ method_option :config_file, aliases: '-c', desc: "default configuration file", default: "tmp/config.yml"
142
+ def reception_message
143
+ doc = XmlDocument.new(options[:xml_in])
144
+
145
+ builder = FE::Builder.new
146
+
147
+ # Roles of receiver and issuer are inverted because they are extracted from the document.
148
+ # The ISSUER of the reception message is the RECEIVER of the document
149
+ message = builder.reception_message({
150
+ key: doc.document.key,
151
+ date: doc.document.date,
152
+ number: options[:number],
153
+ issuer_id_number: doc.document.receiver.identification_document.id_number,
154
+ issuer_id_type: doc.document.receiver.identification_document.document_type,
155
+ receiver_id_number: doc.document.issuer.identification_document.id_number,
156
+ receiver_id_type: doc.document.issuer.identification_document.document_type,
157
+ message: options[:action],
158
+ tax: doc.document.summary.tax_total,
159
+ total: doc.document.summary.net_total,
160
+ document_situation: options[:document_situation]
161
+ })
162
+
163
+ message.security_code = (SecureRandom.random_number * (10**8)).round.to_s
164
+ if options[:output_path]
165
+ output_path = options[:output_path]
166
+ else
167
+ output_path = "tmp/msj-receptor-#{message.key}.xml"
168
+ end
169
+ write(message, output_path)
170
+ puts "Mensaje Receptor"
171
+ puts "Accion: #{FE::ReceptionMessage::MESSAGE_TYPES[message.message]}"
172
+ puts "Factura: #{doc.document.key}"
173
+ puts "Ced. Receptor: #{message.receiver_id_number}"
174
+ puts "Ced. Emisor: #{message.issuer_id_number}"
175
+
176
+ sign(output_path, options) if options[:sign]
177
+ send_document("#{output_path}.signed.xml") if options[:sign] && options[:send]
178
+
179
+ end
180
+
105
181
  no_commands{
106
182
  def write(document, output_path)
107
183
  File.open(output_path, 'w'){|f| f.write(document.generate.gsub("\n",""))}
@@ -115,10 +191,10 @@ module FE
115
191
  end
116
192
 
117
193
  def sign(path, options)
118
- puts " => SIGN ..............."
194
+ puts "=> SIGN ................."
119
195
  cli = FE::CLI.new
120
196
  cli.options = {config_file: options[:config_file]}
121
- cli.sign_document("#{path}", "#{path}.signed.xml")
197
+ cli.sign("#{path}", "#{path}.signed.xml")
122
198
  end
123
199
 
124
200
  def send_document(path)
data/lib/facturacr/cli.rb CHANGED
@@ -53,9 +53,9 @@ module FE
53
53
  desc "generate DOCUMENT ARGS", "generate xml documents"
54
54
  subcommand "generate", Generate
55
55
 
56
- desc "sign_document XML_IN XML_OUT", "signs the xml document and stores the signed document in the output path"
56
+ desc "sign XML_IN XML_OUT", "signs the xml document and stores the signed document in the output path"
57
57
  method_option :config_file, aliases: '-c', desc: "default configuration file", default: "tmp/config.yml"
58
- def sign_document(xml_in, xml_out)
58
+ def sign(xml_in, xml_out)
59
59
  FE::Utils.configure(options[:config_file])
60
60
  signer = FE::JavaSigner.new FE.configuration.key_path, FE.configuration.key_password, xml_in, xml_out
61
61
  signer.sign
@@ -66,15 +66,18 @@ module FE
66
66
  def send_document(path)
67
67
  FE::Utils.configure(options[:config_file])
68
68
  xml_document = FE::XmlDocument.new(path)
69
- invoice = xml_document.document
70
- signed_document = FE::SignedDocument.new(invoice,path)
69
+ document = xml_document.document
70
+ if document.is_a?(FE::ReceptionMessage)
71
+ document.receiver_id_type = "02"
72
+ end
73
+ signed_document = FE::SignedDocument.new(document,path)
71
74
  api = FE::Api.new
72
75
  if api.send_document(signed_document.payload)
73
76
  puts "Document Sent".green
74
- puts "KEY: #{invoice.key}"
77
+ puts "KEY: #{document.key}"
75
78
  puts "Wait 5 seconds before check..."
76
79
  sleep 5
77
- invoke :check, [invoice.key], :config_file=>options[:config_file]
80
+ invoke :check, [document.key], :config_file=>options[:config_file]
78
81
  else
79
82
  puts "ERROR".red
80
83
  ap api.errors
@@ -82,18 +85,7 @@ module FE
82
85
  end
83
86
  end
84
87
 
85
- desc "test_invoice NUMBER DATA_PATH", "generates a test invoice and sends it to the api"
86
- method_option :config_file, aliases: '-c', desc: "default configuration file", default: "tmp/config.yml"
87
- def test_invoice(number, data_path)
88
- FE::Utils.configure(options[:config_file])
89
- puts "Generating document ..."
90
- invoke :generate_invoice, [data_path,"tmp/unsigned_#{number}.xml"], number: number
91
- puts "Signing document ..."
92
- invoke :sign_document, ["tmp/unsigned_#{number}.xml","tmp/#{number}.xml"]
93
- puts "Sending ..."
94
- invoke :send_document, ["tmp/#{number}.xml"]
95
- end
96
-
88
+
97
89
  desc "setup PATH", "will create a tmp directory with a sample config file and a sample data file at the specified path."
98
90
  def setup(path)
99
91
  puts "\n\n SETUP FACTURACR \n\n"
@@ -103,8 +95,8 @@ module FE
103
95
  answer = ask("Are you sure you want to continue?", :yellow, limited_to: ["y","n"])
104
96
  if answer.downcase == "y"
105
97
  FileUtils.mkdir_p "#{path}/tmp"
106
- FileUtils.cp "resources/data.yml", "#{path}/tmp/data.yml"
107
- FileUtils.cp "config/config.yml", "#{path}/tmp/config.yml"
98
+ FileUtils.cp "#{FE.root}/resources/data.yml", "#{path}/tmp/data.yml"
99
+ FileUtils.cp "#{FE.root}/config/config.yml", "#{path}/tmp/config.yml"
108
100
  say "Done.", :green
109
101
  else
110
102
  say "Ok. Bye", :green
@@ -17,7 +17,7 @@ module FE
17
17
  }
18
18
 
19
19
  validates :document_type, presence: true, inclusion: FE::Document::DOCUMENT_TYPES.keys
20
- validates :number, presence: true, length: {is: 50}
20
+ validates :number, presence: true, length: {maximum: 50}
21
21
  validates :date, presence: true
22
22
  validates :code, presence: true, length: {is: 2}, inclusion: REFERENCE_CODES.keys
23
23
  validates :reason, presence: true, length: {maximum: 180}
@@ -0,0 +1,118 @@
1
+ require 'active_model'
2
+
3
+ module FE
4
+ class ReceptionMessage
5
+ include ActiveModel::Validations
6
+
7
+ MESSAGE_TYPES = {
8
+ "1" => "Aceptado",
9
+ "2" => "Aceptacion Parcial",
10
+ "3" => "Rechazado"
11
+ }
12
+ attr_accessor :key, :date, :issuer_id_number, :receiver_id_number, :message, :details, :tax, :total, :number, :receiver_id_type, :security_code, :document_situation
13
+
14
+ validates :date, presence: true
15
+ validates :issuer_id_number, presence: true, length: {is: 12}
16
+ validates :receiver_id_number, presence: true, length: {is: 12}
17
+ validates :message, presence: true, inclusion: MESSAGE_TYPES.keys
18
+ validates :tax, numericality: true, if: -> { tax.present? }
19
+ validates :total, presence: true, numericality: true
20
+ validates :number, presence: true
21
+ validates :security_code, presence: true, length: {is: 8}
22
+
23
+ def initialize(args = {})
24
+ @key = args[:key]
25
+ @date = args[:date]
26
+ @issuer_id_number = args[:issuer_id_number]
27
+ @receiver_id_type = args[:receiver_id_type]
28
+ @receiver_id_number = args[:receiver_id_number]
29
+ @message = args[:message].to_s
30
+ @details = args[:details]
31
+ @tax = args[:tax]
32
+ @total = args[:total]
33
+ @number = args[:number].to_i
34
+ @security_code = args[:security_code]
35
+ @document_situation = args[:document_situation]
36
+ @namespaces = {
37
+ "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
38
+ "xmlns:xsd"=>"http://www.w3.org/2001/XMLSchema",
39
+ "xmlns"=>"https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/mensajeReceptor"
40
+ }
41
+ end
42
+
43
+ def key
44
+ raise "Documento inválido: #{errors.messages}" unless valid?
45
+ country = "506"
46
+ day = "%02d" % @date.day
47
+ month = "%02d" % @date.month
48
+ year = "%02d" % (@date.year - 2000)
49
+ id_number = @receiver_id_number.rjust(12,"0")
50
+
51
+ situation = @document_situation
52
+ security_code = @security_code
53
+
54
+ result = "#{country}#{day}#{month}#{year}#{id_number}#{sequence}#{situation}#{security_code}"
55
+ raise "The key is invalid: #{result}" unless result.length.eql?(50)
56
+
57
+ result
58
+ end
59
+
60
+ def headquarters
61
+ @headquarters ||= "001"
62
+ end
63
+
64
+ def terminal
65
+ @terminal ||= "00001"
66
+ end
67
+
68
+ def sequence
69
+ if @message.eql?("1")
70
+ @document_type = "05"
71
+ elsif @message.eql?("2")
72
+ @document_type = "06"
73
+ elsif @message.eql?("3")
74
+ @document_type = "07"
75
+ end
76
+ cons = ("%010d" % @number)
77
+ "#{headquarters}#{terminal}#{@document_type}#{cons}"
78
+ end
79
+
80
+
81
+
82
+ def build_xml
83
+ raise "Documento inválido: #{errors.messages}" unless valid?
84
+ builder = Nokogiri::XML::Builder.new
85
+
86
+ builder.MensajeReceptor(@namespaces) do |xml|
87
+ xml.Clave key
88
+ xml.NumeroCedulaEmisor @issuer_id_number
89
+ xml.FechaEmisionDoc @date.xmlschema
90
+ xml.Mensaje @message
91
+ xml.DetalleMensaje @details if @details
92
+ xml.MontoTotalImpuesto @tax if @tax
93
+ xml.TotalFactura @total
94
+ xml.NumeroCedulaReceptor @receiver_id_number
95
+ xml.NumConsecutivoReceptor sequence
96
+ end
97
+
98
+ builder
99
+ end
100
+
101
+ def generate
102
+ build_xml.to_xml(:save_with => Nokogiri::XML::Node::SaveOptions::AS_XML)
103
+ end
104
+
105
+ def api_payload
106
+ payload = {}
107
+ payload[:clave] = key
108
+ payload[:fecha] = @date.xmlschema
109
+ payload[:emisor] = {
110
+ tipoIdentificacion: @receiver_id_type,
111
+ numeroIdentificacion: @receiver_id_number
112
+ }
113
+ payload
114
+ end
115
+
116
+
117
+ end
118
+ end
@@ -21,8 +21,7 @@ module FE
21
21
  @namespaces = {
22
22
  "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
23
23
  "xmlns:xsd"=>"http://www.w3.org/2001/XMLSchema",
24
- "xmlns"=>"https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/tiqueteElectronico",
25
- "xsi:schemaLocation"=>"https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/tiqueteElectronico https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/tiqueteElectronico.xsd"
24
+ "xmlns"=>"https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/tiqueteElectronico"
26
25
  }
27
26
  end
28
27
 
@@ -1,3 +1,3 @@
1
1
  module FE
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
@@ -21,138 +21,158 @@ module FE
21
21
  @document = FE::CreditNote.new
22
22
  elsif root_tag.eql?("NotaDebitoElectronica")
23
23
  @document = FE::DebitNote.new
24
+ elsif root_tag.eql?("TiqueteElectronico")
25
+ @document = FE::Ticket.new
26
+ elsif root_tag.eql?("MensajeReceptor")
27
+ @document = FE::ReceptionMessage.new
24
28
  end
25
- @document.date = DateTime.parse(@doc.css("#{root_tag} FechaEmision").text)
26
- @key = @doc.css("#{root_tag} Clave").text
27
- @document.number = @key[31..40].to_i
28
- @document.document_situation = @key[41]
29
- @document.security_code = @key[42..-1]
30
- @document.condition = @doc.css("#{root_tag} CondicionVenta").text
31
- @document.credit_term = @doc.css("#{root_tag} PlazoCredito").text unless @doc.css("#{root_tag} PlazoCredito").empty?
32
- @document.payment_type = @doc.css("#{root_tag} MedioPago").first.text
33
29
 
34
- @issuer = FE::Document::Issuer.new
35
- @issuer.identification_document = FE::Document::IdentificationDocument.new type: @doc.css("#{root_tag} Emisor Identificacion Tipo").text, number: @doc.css("#{root_tag} Emisor Identificacion Numero").text.to_i
36
- @issuer.name = @doc.css("#{root_tag} Emisor Nombre").text
37
- @issuer.comercial_name = @doc.css("#{root_tag} Emisor NombreComercial").text unless @doc.css("#{root_tag} Emisor NombreComercial").empty?
38
- location = FE::Document::Location.new
39
- location.province = @doc.css("#{root_tag} Emisor Ubicacion Provincia").text
40
- location.county = @doc.css("#{root_tag} Emisor Ubicacion Canton").text
41
- location.district = @doc.css("#{root_tag} Emisor Ubicacion Distrito").text
42
- location.others = @doc.css("#{root_tag} Emisor Ubicacion OtrasSenas").text
43
- @issuer.location = location
30
+ if @document.is_a?(FE::Document)
31
+ @document.date = DateTime.parse(@doc.css("#{root_tag} FechaEmision").text)
32
+ @key = @doc.css("#{root_tag} Clave").text
33
+ @document.number = @key[31..40].to_i
34
+ @document.document_situation = @key[41]
35
+ @document.security_code = @key[42..-1]
36
+ @document.condition = @doc.css("#{root_tag} CondicionVenta").text
37
+ @document.credit_term = @doc.css("#{root_tag} PlazoCredito").text unless @doc.css("#{root_tag} PlazoCredito").empty?
38
+ @document.payment_type = @doc.css("#{root_tag} MedioPago").first.text
44
39
 
45
- if !@doc.css("#{root_tag} Emisor Telefono").empty?
46
- @issuer.phone = FE::Document::Phone.new country_code: @doc.css("#{root_tag} Emisor Telefono CodigoPais").text, number: @doc.css("#{root_tag} Emisor Telefono CodigoPais").text
47
- end
48
- if !@doc.css("#{root_tag} Emisor Fax").empty?
49
- @issuer.fax = FE::Document::Phone.new country_code: @doc.css("#{root_tag} Emisor Telefono CodigoPais").text, number: @doc.css("#{root_tag} Emisor Telefono CodigoPais").text
50
- end
51
- @issuer.email = @doc.css("#{root_tag} Emisor CorreoElectronico").text
40
+ @issuer = FE::Document::Issuer.new
41
+ @issuer.identification_document = FE::Document::IdentificationDocument.new type: @doc.css("#{root_tag} Emisor Identificacion Tipo").text, number: @doc.css("#{root_tag} Emisor Identificacion Numero").text.to_i
42
+ @issuer.name = @doc.css("#{root_tag} Emisor Nombre").text
43
+ @issuer.comercial_name = @doc.css("#{root_tag} Emisor NombreComercial").text unless @doc.css("#{root_tag} Emisor NombreComercial").empty?
44
+ location = FE::Document::Location.new
45
+ location.province = @doc.css("#{root_tag} Emisor Ubicacion Provincia").text
46
+ location.county = @doc.css("#{root_tag} Emisor Ubicacion Canton").text
47
+ location.district = @doc.css("#{root_tag} Emisor Ubicacion Distrito").text
48
+ location.others = @doc.css("#{root_tag} Emisor Ubicacion OtrasSenas").text
49
+ @issuer.location = location
52
50
 
53
- unless @doc.css("#{root_tag} Receptor").empty?
54
- @receiver = FE::Document::Receiver.new
55
- @receiver.name = @doc.css("#{root_tag} Receptor Nombre").text
56
- unless @doc.css("#{root_tag} Receptor Identificacion").empty?
57
- @receiver.identification_document = FE::Document::IdentificationDocument.new type: @doc.css("#{root_tag} Receptor Identificacion Tipo").text, number: @doc.css("#{root_tag} Receptor Identificacion Numero").text.to_i
51
+ if !@doc.css("#{root_tag} Emisor Telefono").empty?
52
+ @issuer.phone = FE::Document::Phone.new country_code: @doc.css("#{root_tag} Emisor Telefono CodigoPais").text, number: @doc.css("#{root_tag} Emisor Telefono CodigoPais").text
58
53
  end
59
-
60
- unless @doc.css("#{root_tag} Receptor IdentificacionExtranjero").empty?
61
- @receiver.foreign_id_number = @doc.css("#{root_tag} Receptor IdentificacionExtranjero").text
54
+ if !@doc.css("#{root_tag} Emisor Fax").empty?
55
+ @issuer.fax = FE::Document::Phone.new country_code: @doc.css("#{root_tag} Emisor Telefono CodigoPais").text, number: @doc.css("#{root_tag} Emisor Telefono CodigoPais").text
62
56
  end
63
- @receiver.comercial_name = @doc.css("#{root_tag} Receptor NombreComercial").text unless @doc.css("#{root_tag} Receptor NombreComercial").empty?
57
+ @issuer.email = @doc.css("#{root_tag} Emisor CorreoElectronico").text
58
+
59
+ unless @doc.css("#{root_tag} Receptor").empty?
60
+ @receiver = FE::Document::Receiver.new
61
+ @receiver.name = @doc.css("#{root_tag} Receptor Nombre").text
62
+ unless @doc.css("#{root_tag} Receptor Identificacion").empty?
63
+ @receiver.identification_document = FE::Document::IdentificationDocument.new type: @doc.css("#{root_tag} Receptor Identificacion Tipo").text, number: @doc.css("#{root_tag} Receptor Identificacion Numero").text.to_i
64
+ end
64
65
 
65
- unless @doc.css("#{root_tag} Receptor Ubicacion").empty?
66
- location = FE::Document::Location.new
67
- location.province = @doc.css("#{root_tag} Receptor Ubicacion Provincia").text
68
- location.county = @doc.css("#{root_tag} Receptor Ubicacion Canton").text
69
- location.district = @doc.css("#{root_tag} Receptor Ubicacion Distrito").text
70
- location.others = @doc.css("#{root_tag} Receptor Ubicacion OtrasSenas").text
71
- @receiver.location = location
72
- end
66
+ unless @doc.css("#{root_tag} Receptor IdentificacionExtranjero").empty?
67
+ @receiver.foreign_id_number = @doc.css("#{root_tag} Receptor IdentificacionExtranjero").text
68
+ end
69
+ @receiver.comercial_name = @doc.css("#{root_tag} Receptor NombreComercial").text unless @doc.css("#{root_tag} Receptor NombreComercial").empty?
73
70
 
74
- if !@doc.css("#{root_tag} Receptor Telefono").empty?
75
- @issuer.phone = FE::Document::Phone.new country_code: @doc.css("#{root_tag} Receptor Telefono CodigoPais").text, number: @doc.css("#{root_tag} Receptor Telefono CodigoPais").text
76
- end
77
- if !@doc.css("#{root_tag} Receptor Fax").empty?
78
- @receiver.fax = FE::Document::Phone.new country_code: @doc.css("#{root_tag} Receptor Telefono CodigoPais").text, number: @doc.css("#{root_tag} Receptor Telefono CodigoPais").text
79
- end
80
- @receiver.email = @doc.css("#{root_tag} Receptor CorreoElectronico").text unless @doc.css("#{root_tag} Receptor CorreoElectronico").empty?
81
- end
82
- @items = []
83
- @doc.css("#{root_tag} DetalleServicio LineaDetalle").each do |line|
84
- item = FE::Document::Item.new
85
- item.line_number = line.css("NumeroLinea").text.to_i
86
- item.code = line.css("Codigo Codigo").text
87
- item.quantity = line.css("Cantidad").text
88
- item.unit = line.css("UnidadMedida").text
89
- item.description = line.css("Detalle").text
90
- item.unit_price = line.css("PrecioUnitario").text.to_f
91
- item.total = line.css("MontoTotal").text.to_f
92
- item.discount = line.css("MontoDescuento").text.to_f unless line.css("MontoDescuento").empty?
93
- item.discount_reason = line.css("NaturalezaDescuento").text unless line.css("NaturalezaDescuento").empty?
94
- item.subtotal = line.css("SubTotal").text.to_f
95
- item.net_total = line.css("MontoTotalLinea").text.to_f
96
- item.taxes = []
97
- line.css("Impuesto").each do |tax|
98
- item.taxes << FE::Document::Tax.new(code: tax.css("Codigo").text, rate: tax.css("Tarifa").text.to_f, total: tax.css("Monto").text.to_f)
71
+ unless @doc.css("#{root_tag} Receptor Ubicacion").empty?
72
+ location = FE::Document::Location.new
73
+ location.province = @doc.css("#{root_tag} Receptor Ubicacion Provincia").text
74
+ location.county = @doc.css("#{root_tag} Receptor Ubicacion Canton").text
75
+ location.district = @doc.css("#{root_tag} Receptor Ubicacion Distrito").text
76
+ location.others = @doc.css("#{root_tag} Receptor Ubicacion OtrasSenas").text
77
+ @receiver.location = location
78
+ end
79
+
80
+ if !@doc.css("#{root_tag} Receptor Telefono").empty?
81
+ @issuer.phone = FE::Document::Phone.new country_code: @doc.css("#{root_tag} Receptor Telefono CodigoPais").text, number: @doc.css("#{root_tag} Receptor Telefono CodigoPais").text
82
+ end
83
+ if !@doc.css("#{root_tag} Receptor Fax").empty?
84
+ @receiver.fax = FE::Document::Phone.new country_code: @doc.css("#{root_tag} Receptor Telefono CodigoPais").text, number: @doc.css("#{root_tag} Receptor Telefono CodigoPais").text
85
+ end
86
+ @receiver.email = @doc.css("#{root_tag} Receptor CorreoElectronico").text unless @doc.css("#{root_tag} Receptor CorreoElectronico").empty?
99
87
  end
100
- unless line.css("Exoneracion").empty?
101
- exo = FE::Document::Exoneration.new
102
- exo.document_type = line.css("Exoneracion TipoDocumento").text
103
- exo.document_number = line.css("Exoneracion NumeroDocumento").text
104
- exo.institution = line.css("Exoneracion NombreInstitucion").text
105
- exo.date = DateTime.parse(line.css("Exoneracion FechaEmision").text)
106
- exo.total_tax = line.css("Exoneracion MontoImpuesto").text.to_f
107
- exo.percentage = line.css("Exoneracion PorcentajeCompra").text.to_i
108
- item.exoneration = exo
88
+ @items = []
89
+ @doc.css("#{root_tag} DetalleServicio LineaDetalle").each do |line|
90
+ item = FE::Document::Item.new
91
+ item.line_number = line.css("NumeroLinea").text.to_i
92
+ item.code = line.css("Codigo Codigo").text
93
+ item.quantity = line.css("Cantidad").text
94
+ item.unit = line.css("UnidadMedida").text
95
+ item.description = line.css("Detalle").text
96
+ item.unit_price = line.css("PrecioUnitario").text.to_f
97
+ item.total = line.css("MontoTotal").text.to_f
98
+ item.discount = line.css("MontoDescuento").text.to_f unless line.css("MontoDescuento").empty?
99
+ item.discount_reason = line.css("NaturalezaDescuento").text unless line.css("NaturalezaDescuento").empty?
100
+ item.subtotal = line.css("SubTotal").text.to_f
101
+ item.net_total = line.css("MontoTotalLinea").text.to_f
102
+ item.taxes = []
103
+ line.css("Impuesto").each do |tax|
104
+ item.taxes << FE::Document::Tax.new(code: tax.css("Codigo").text, rate: tax.css("Tarifa").text.to_f, total: tax.css("Monto").text.to_f)
105
+ end
106
+ unless line.css("Exoneracion").empty?
107
+ exo = FE::Document::Exoneration.new
108
+ exo.document_type = line.css("Exoneracion TipoDocumento").text
109
+ exo.document_number = line.css("Exoneracion NumeroDocumento").text
110
+ exo.institution = line.css("Exoneracion NombreInstitucion").text
111
+ exo.date = DateTime.parse(line.css("Exoneracion FechaEmision").text)
112
+ exo.total_tax = line.css("Exoneracion MontoImpuesto").text.to_f
113
+ exo.percentage = line.css("Exoneracion PorcentajeCompra").text.to_i
114
+ item.exoneration = exo
115
+ end
116
+ @items << item
109
117
  end
110
- @items << item
111
- end
112
118
 
113
119
 
114
- @summary = FE::Document::Summary.new
115
- sum = @doc.css("#{root_tag} ResumenFactura")
116
- @summary.currency = sum.css("CodigoMoneda").text
117
- @summary.exchange_rate = sum.css("TipoCambio").text.to_f
118
- @summary.services_taxable_total = sum.css("TotalServGravados").text.to_f
119
- @summary.services_exent_total = sum.css("TotalServExentos").text.to_f
120
- @summary.goods_taxable_total = sum.css("TotalMercanciasGravadas").text.to_f
121
- @summary.goods_exent_total = sum.css("TotalMercanciasExentas").text.to_f
122
- @summary.taxable_total = sum.css("TotalGravado").text.to_f
123
- @summary.exent_total = sum.css("TotalExento").text.to_f
124
- @summary.subtotal = sum.css("TotalVenta").text.to_f
125
- @summary.discount_total = sum.css("TotalDescuentos").text.to_f
126
- @summary.gross_total = sum.css("TotalVentaNeta").text.to_f
127
- @summary.tax_total = sum.css("TotalImpuesto").text.to_f
128
- @summary.net_total = sum.css("TotalComprobante").text.to_f
120
+ @summary = FE::Document::Summary.new
121
+ sum = @doc.css("#{root_tag} ResumenFactura")
122
+ @summary.currency = sum.css("CodigoMoneda").text
123
+ @summary.exchange_rate = sum.css("TipoCambio").text.to_f
124
+ @summary.services_taxable_total = sum.css("TotalServGravados").text.to_f
125
+ @summary.services_exent_total = sum.css("TotalServExentos").text.to_f
126
+ @summary.goods_taxable_total = sum.css("TotalMercanciasGravadas").text.to_f
127
+ @summary.goods_exent_total = sum.css("TotalMercanciasExentas").text.to_f
128
+ @summary.taxable_total = sum.css("TotalGravado").text.to_f
129
+ @summary.exent_total = sum.css("TotalExento").text.to_f
130
+ @summary.subtotal = sum.css("TotalVenta").text.to_f
131
+ @summary.discount_total = sum.css("TotalDescuentos").text.to_f
132
+ @summary.gross_total = sum.css("TotalVentaNeta").text.to_f
133
+ @summary.tax_total = sum.css("TotalImpuesto").text.to_f
134
+ @summary.net_total = sum.css("TotalComprobante").text.to_f
129
135
 
130
- refs = @doc.css("#{root_tag} InformacionReferencia")
131
- @references = []
132
- unless refs.empty?
133
- refs.each do |ref|
134
- reference = FE::Document::Reference.new
135
- reference.document_type = ref.css("TipoDoc")
136
- reference.number = ref.css("Numero")
137
- reference.date = ref.css("FechaEmision")
138
- reference.code = ref.css("Codigo")
139
- reference.reason = ref.css("Razon")
140
- @references << reference
136
+ refs = @doc.css("#{root_tag} InformacionReferencia")
137
+ @references = []
138
+ unless refs.empty?
139
+ refs.each do |ref|
140
+ reference = FE::Document::Reference.new
141
+ reference.document_type = ref.css("TipoDoc")
142
+ reference.number = ref.css("Numero")
143
+ reference.date = ref.css("FechaEmision")
144
+ reference.code = ref.css("Codigo")
145
+ reference.reason = ref.css("Razon")
146
+ @references << reference
147
+ end
141
148
  end
142
- end
143
149
 
144
- reg = @doc.css("#{root_tag} Normativa")
145
- @regulation = FE::Document::Regulation.new
146
- @regulation.number = reg.css("NumeroResolucion").text
147
- @regulation.date = reg.css("FechaResolucion").text
150
+ reg = @doc.css("#{root_tag} Normativa")
151
+ @regulation = FE::Document::Regulation.new
152
+ @regulation.number = reg.css("NumeroResolucion").text
153
+ @regulation.date = reg.css("FechaResolucion").text
148
154
 
149
155
 
150
- @document.issuer = @issuer
151
- @document.receiver = @receiver
152
- @document.items = @items
153
- @document.summary = @summary
154
- @document.references = @references
155
- @document.regulation = @regulation
156
+ @document.issuer = @issuer
157
+ @document.receiver = @receiver
158
+ @document.items = @items
159
+ @document.summary = @summary
160
+ @document.references = @references
161
+ @document.regulation = @regulation
162
+ else
163
+ @document.date = DateTime.parse(@doc.css("#{root_tag} FechaEmisionDoc").text)
164
+ @key = @doc.css("#{root_tag} Clave").text
165
+ @document.key = @key
166
+ @document.issuer_id_number = @doc.css("#{root_tag} NumeroCedulaEmisor").text
167
+ @document.receiver_id_number = @doc.css("#{root_tag} NumeroCedulaReceptor").text
168
+ @document.message = @doc.css("#{root_tag} Mensaje").text
169
+ @document.details = @doc.css("#{root_tag} DetalleMensaje").text
170
+ @document.number = @key[31..40].to_i
171
+ @document.document_situation = @key[41]
172
+ @document.security_code = @key[42..-1]
173
+ @document.total = @doc.css("#{root_tag} TotalFactura").text
174
+ @document.tax = @doc.css("#{root_tag} MontoTotalImpuesto").text
175
+ end
156
176
  else
157
177
  raise "#{xml_path} does not exist"
158
178
  end
data/lib/facturacr.rb CHANGED
@@ -12,6 +12,7 @@ require 'facturacr/api'
12
12
  require 'facturacr/builder'
13
13
  require 'facturacr/version'
14
14
  require 'facturacr/signer/signer'
15
+ require 'facturacr/reception_message'
15
16
 
16
17
  module FE
17
18
  class << self
@@ -0,0 +1,86 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <NotaCreditoElectronica xmlns="https://tribunet.hacienda.go.cr/docs/esquemas/2017/v4.2/notaCreditoElectronica" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
3
+ <Clave>50601041800310263679500100001030000000111199999999</Clave>
4
+ <NumeroConsecutivo>00100001030000000111</NumeroConsecutivo>
5
+ <FechaEmision>2018-04-01T01:00:18-06:00</FechaEmision>
6
+ <Emisor>
7
+ <Nombre>EMISOR EJEMPLO</Nombre>
8
+ <Identificacion>
9
+ <Tipo>02</Tipo>
10
+ <Numero>3102123456</Numero>
11
+ </Identificacion>
12
+ <Ubicacion>
13
+ <Provincia>1</Provincia>
14
+ <Canton>01</Canton>
15
+ <Distrito>01</Distrito>
16
+ <OtrasSenas>Direccion</OtrasSenas>
17
+ </Ubicacion>
18
+ <Telefono>
19
+ <CodigoPais>506</CodigoPais>
20
+ <NumTelefono>22222222</NumTelefono>
21
+ </Telefono>
22
+ <CorreoElectronico>email@ejemplo.com</CorreoElectronico>
23
+ </Emisor>
24
+ <Receptor>
25
+ <Nombre>RECEPTOR EJEMPLO</Nombre>
26
+ <Identificacion>
27
+ <Tipo>01</Tipo>
28
+ <Numero>112345678</Numero>
29
+ </Identificacion>
30
+ </Receptor>
31
+ <CondicionVenta>01</CondicionVenta>
32
+ <MedioPago>01</MedioPago>
33
+ <DetalleServicio>
34
+ <LineaDetalle>
35
+ <NumeroLinea>1</NumeroLinea>
36
+ <Cantidad>1</Cantidad>
37
+ <UnidadMedida>Sp</UnidadMedida>
38
+ <Detalle>Honorarios por servicios profesionales</Detalle>
39
+ <PrecioUnitario>300</PrecioUnitario>
40
+ <MontoTotal>300</MontoTotal>
41
+ <SubTotal>300</SubTotal>
42
+ <MontoTotalLinea>300</MontoTotalLinea>
43
+ </LineaDetalle>
44
+ <LineaDetalle>
45
+ <NumeroLinea>2</NumeroLinea>
46
+ <Cantidad>2</Cantidad>
47
+ <UnidadMedida>Unid</UnidadMedida>
48
+ <Detalle>Articulo de Venta</Detalle>
49
+ <PrecioUnitario>50</PrecioUnitario>
50
+ <MontoTotal>100</MontoTotal>
51
+ <SubTotal>100</SubTotal>
52
+ <Impuesto>
53
+ <Codigo>01</Codigo>
54
+ <Tarifa>13</Tarifa>
55
+ <Monto>13</Monto>
56
+ </Impuesto>
57
+ <MontoTotalLinea>113</MontoTotalLinea>
58
+ </LineaDetalle>
59
+ </DetalleServicio>
60
+ <ResumenFactura>
61
+ <CodigoMoneda>USD</CodigoMoneda>
62
+ <TipoCambio>575</TipoCambio>
63
+ <TotalServGravados>0.0</TotalServGravados>
64
+ <TotalServExentos>300.0</TotalServExentos>
65
+ <TotalMercanciasGravadas>100.0</TotalMercanciasGravadas>
66
+ <TotalMercanciasExentas>0.0</TotalMercanciasExentas>
67
+ <TotalGravado>100.0</TotalGravado>
68
+ <TotalExento>300.0</TotalExento>
69
+ <TotalVenta>400.0</TotalVenta>
70
+ <TotalDescuentos>0.0</TotalDescuentos>
71
+ <TotalVentaNeta>400.0</TotalVentaNeta>
72
+ <TotalImpuesto>13.0</TotalImpuesto>
73
+ <TotalComprobante>413.0</TotalComprobante>
74
+ </ResumenFactura>
75
+ <InformacionReferencia>
76
+ <TipoDoc>01</TipoDoc>
77
+ <Numero>50601041800310263679500100001010000000109199999999</Numero>
78
+ <FechaEmision>2018-04-01T00:19:27-06:00</FechaEmision>
79
+ <Codigo>01</Codigo>
80
+ <Razon>Anula documento</Razon>
81
+ </InformacionReferencia>
82
+ <Normativa>
83
+ <NumeroResolucion>DGT-R-48-2016</NumeroResolucion>
84
+ <FechaResolucion>20-02-2017 13:22:22</FechaResolucion>
85
+ </Normativa>
86
+ </NotaCreditoElectronica>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: facturacr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josef Sauter
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-04-01 00:00:00.000000000 Z
11
+ date: 2018-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -196,6 +196,7 @@ files:
196
196
  - lib/facturacr/document/summary.rb
197
197
  - lib/facturacr/document/tax.rb
198
198
  - lib/facturacr/invoice.rb
199
+ - lib/facturacr/reception_message.rb
199
200
  - lib/facturacr/signed_document.rb
200
201
  - lib/facturacr/signer/signer.rb
201
202
  - lib/facturacr/ticket.rb
@@ -208,6 +209,7 @@ files:
208
209
  - resources/debit_note.xml
209
210
  - resources/invoice.xml
210
211
  - resources/pruebas.xml
212
+ - resources/reception_message.xml
211
213
  - resources/test.p12
212
214
  homepage: https://github.com/apokalipto/facturacr
213
215
  licenses: []