m_cfdi 0.1.0 → 0.2.0

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: 6a4f6145d69b6c02670db615dc5d83e810c77ebe
4
- data.tar.gz: e658056476fabedbcf1c2936e5bdb45de5cbc688
3
+ metadata.gz: ae85da182607c7e669c5cf6da65cb1687f1ca92d
4
+ data.tar.gz: 0c94217b234df9b8e054d006e5aec50d184f8444
5
5
  SHA512:
6
- metadata.gz: 7cd62893bf6c100cb869b3e35bc12b751f7c0faaa0f2b7bdd78d683515534dae0933d8bdd5a0244d96e7a1e333d013fcd0c633b39710aeae1e8aefa57fb9899a
7
- data.tar.gz: 458b70122799bca1db0ab0350c0597d2d856b1d8d16bddc5e884f5e8d81f419c011a2743ba58c7ddb82c148a0bcf301b7e69cffb0184bb59330f6cd2c92dbee3
6
+ metadata.gz: 3bac5a4eb45682f0140aa69aeaf1d95536a4d1bb57eaccd93acd5a71415280a587331ef4ad586d05424f26bdbd6dbb6b89c88e5e30ba17e16211c54a64703d25
7
+ data.tar.gz: 8f1b8a518a5fb0112d2744778d6539294ac020ca874eede131d83c9e4fce71a2d8e73238bc769a938f3a3bce5d702f4af2f1f4bdde02764fc685db3a0920ec1a
data/README.md CHANGED
@@ -6,23 +6,30 @@ CFDI GEM, to generate XML file for invoice, all you have to do, is to send the x
6
6
  # Installation:
7
7
 
8
8
  In your gem file:
9
- ```git
10
- gem 'm_cfdi' # NOT UPLOADED
9
+ ```bash
10
+ gem 'm_cfdi'
11
11
  ```
12
12
 
13
13
  or
14
14
 
15
- ```git
15
+ ```bash
16
16
  gem 'm_cfdi', git: 'https://github.com/MaSys/m_cfdi.git'
17
17
  ```
18
18
 
19
19
  or install it directly from your terminal:
20
- ```git
20
+ ```bash
21
21
  gem install m_cfdi
22
22
  ```
23
23
 
24
24
  # Usage:
25
25
 
26
+ Importante:
27
+ ```
28
+ Dont't forgot to set TimeZone in your app.
29
+ ```
30
+ You have to set timezone in your app to send the invoice date.
31
+ if not, it will return an error.
32
+
26
33
  ```ruby
27
34
 
28
35
  class Invoice
@@ -13,9 +13,10 @@ module MCFDI
13
13
  attr_accessor :uuid, :stamp_date, :cfd_stamp, :sat_certificate_num,
14
14
  :sat_stamp, :version
15
15
 
16
- # Regresa la cadena Original del Timbre Fiscal Digital del SAT
17
- #
18
- # @return [String] la cadena formada
16
+ def initialize(args = {})
17
+ args.each { |key, value| send("#{key}=", value) }
18
+ end
19
+
19
20
  def string
20
21
  a = [@version, @uuid, @stamp_date, @cfd_stamp, @sat_certificate_num]
21
22
  "||#{a.join('|')}||"
@@ -90,15 +90,17 @@ module MCFDI
90
90
  # save xml to file and generate original string from schema.
91
91
  def original_string_from_xslt
92
92
  # fail 'You have to specify schema!' unless # TODO: create configuration.
93
- save_xml
94
93
  xml = "#{Rails.root}/#{@transmitter.rfc}-#{@series}-#{@folio}.xml"
94
+ save_xml(xml)
95
95
  sch = "#{Rails.root}/public/sat/schemas/cadenaoriginal_3_2.xslt"
96
96
  @original_string_from_xslt ||= `xsltproc #{sch} #{xml}`
97
+ File.delete(xml) if File.exist?(xml)
98
+ @original_string_from_xslt
97
99
  end
98
100
 
99
101
  # Save invoice xml to file
100
- def save_xml
101
- file = File.new("#{@transmitter.rfc}-#{@series}-#{@folio}.xml", 'w+')
102
+ def save_xml(name)
103
+ file = File.new(name, 'w+')
102
104
  file.write(to_xml)
103
105
  file.close
104
106
  end
@@ -300,5 +302,22 @@ module MCFDI
300
302
  end
301
303
  errors
302
304
  end # Validate_xml
305
+
306
+ # return string with total in words.
307
+ # Example: ( UN MIL CIENTO SESENTA PESOS 29/100 M.N. )
308
+ def total_to_words
309
+ decimal = format('%.2f', @total).split('.')
310
+ "( #{@total.to_words.upcase} PESOS #{decimal[1]}/100 M.N. )"
311
+ end
312
+
313
+ # return data of qr code image
314
+ def qr_code
315
+ t = "?re=#{@transmitter.rfc}"
316
+ t += "&rr=#{@receptor.rfc}"
317
+ t += "&tt=#{format('%6f', @total).rjust(17, '0')}"
318
+ t += "&id=#{@complement.uuid}"
319
+ img = RQRCode::QRCode.new(t).to_img
320
+ img.resize(120, 120).to_data_url
321
+ end
303
322
  end
304
323
  end
data/lib/m_cfdi/taxes.rb CHANGED
@@ -8,6 +8,7 @@
8
8
  module MCFDI
9
9
  class Taxes < Base
10
10
  attr_accessor :transferred, :detained
11
+
11
12
  def initialize
12
13
  @transferred = []
13
14
  @detained = []
@@ -33,7 +34,7 @@ module MCFDI
33
34
  def transferred=(tax)
34
35
  if data.is_a? Array
35
36
  data.map do |c|
36
- c << Transferred.new(c) unless c.is_a? Tansferred
37
+ c = Transferred.new(c) unless c.is_a? Tansferred
37
38
  @transferred << c
38
39
  end
39
40
  elsif data.is_a? Hash
@@ -1,3 +1,3 @@
1
1
  module MCFDI
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/m_cfdi/xml.rb ADDED
@@ -0,0 +1,132 @@
1
+ module MCFDI
2
+ def self.from_xml(data)
3
+ xml = Nokogiri::XML(data)
4
+ xml.remove_namespaces!
5
+ invoice = Invoice.new
6
+ invoice.taxes = Taxes.new
7
+
8
+ proof = xml.at_xpath('//Comprobante')
9
+ transmitter = xml.at_xpath('//Emisor')
10
+ trans_address = transmitter.at_xpath('//DomicilioFiscal')
11
+ issued_in = transmitter.at_xpath('//ExpedidoEn')
12
+ receptor = xml.at_xpath('//Receptor')
13
+ rec_address = receptor.at_xpath('//Domicilio')
14
+
15
+ invoice.version = proof.attr('version')
16
+ invoice.series = proof.attr('serie')
17
+ invoice.folio = proof.attr('folio')
18
+ invoice.created_at = Time.parse(proof.attr('fecha'))
19
+ invoice.certificate_number = proof.attr('noCertificado')
20
+ invoice.certificate = proof.attr('certificado')
21
+ invoice.stamp = proof.attr('sello')
22
+ invoice.payment_way = proof.attr('formaDePago')
23
+ invoice.payment_conditions = proof.attr('condicionesDePago')
24
+ invoice.proof_type = proof.attr('tipoDeComprobante')
25
+ invoice.expedition_place = proof.attr('LugarExpedicion')
26
+ invoice.payment_method = proof.attr('metodoDePago')
27
+ invoice.currency = proof.attr('Moneda')
28
+ invoice.payment_account_num = proof.attr('NumCtaPago')
29
+ invoice.total = proof.attr('total').to_f
30
+ invoice.subtotal = proof.attr('subTotal').to_f
31
+
32
+
33
+ fiscal_regime = transmitter.at_xpath('//RegimenFiscal')
34
+
35
+ transmitter = {
36
+ rfc: transmitter.attr('rfc'),
37
+ business_name: transmitter.attr('nombre'),
38
+ fiscal_regime: fiscal_regime && fiscal_regime.attr('Regimen'),
39
+ address: {
40
+ street: trans_address.attr('calle'),
41
+ street_number: trans_address.attr('noExterior'),
42
+ interior_number: trans_address.attr('noInterior'),
43
+ neighborhood: trans_address.attr('colonia'),
44
+ location: trans_address.attr('localidad'),
45
+ reference: trans_address.attr('referencia'),
46
+ city: trans_address.attr('municipio'),
47
+ state: trans_address.attr('estado'),
48
+ country: trans_address.attr('pais'),
49
+ zip_code: trans_address.attr('codigoPostal')
50
+ }
51
+ }
52
+
53
+ if issued_in
54
+ transmitter[:issued_in] = {
55
+ street: issued_in.attr('calle'),
56
+ street_number: issued_in.attr('noExterior'),
57
+ interior_number: issued_in.attr('noInterior'),
58
+ neighborhood: issued_in.attr('colonia'),
59
+ location: issued_in.attr('localidad'),
60
+ reference: issued_in.attr('referencia'),
61
+ city: issued_in.attr('municipio'),
62
+ state: issued_in.attr('estado'),
63
+ country: issued_in.attr('pais'),
64
+ zip_code: issued_in.attr('codigoPostal')
65
+ }
66
+ end
67
+
68
+ invoice.transmitter = transmitter
69
+
70
+ invoice.receptor = {
71
+ rfc: receptor.attr('rfc'),
72
+ business_name: receptor.attr('nombre')
73
+ }
74
+
75
+ if rec_address
76
+ invoice.receptor.address = {
77
+ street: rec_address.attr('calle'),
78
+ street_number: rec_address.attr('noExterior'),
79
+ interior_number: rec_address.attr('noInterior'),
80
+ neighborhood: rec_address.attr('colonia'),
81
+ location: rec_address.attr('localidad'),
82
+ reference: rec_address.attr('referencia'),
83
+ city: rec_address.attr('municipio'),
84
+ state: rec_address.attr('estado'),
85
+ country: rec_address.attr('pais'),
86
+ zip_code: rec_address.attr('codigoPostal')
87
+ }
88
+ end
89
+
90
+ invoice.concepts = []
91
+ xml.xpath('//Concepto').each do |concept|
92
+ invoice.concepts << Concept.new(
93
+ quantity: concept.attr('cantidad').to_f,
94
+ measure_unit: concept.attr('unidad'),
95
+ code: concept.attr('noIdentificacion'),
96
+ name: concept.attr('descripcion'),
97
+ price: concept.attr('valorUnitario').to_f,
98
+ import: concept.attr('importe').to_f
99
+ )
100
+ end
101
+
102
+ complement = xml.at_xpath('//TimbreFiscalDigital')
103
+ if complement
104
+ invoice.complement = Complement.new(
105
+ version: complement.attr('version'),
106
+ uuid: complement.attr('UUID'),
107
+ stamp_date: complement.attr('FechaTimbrado'),
108
+ cfd_stamp: complement.attr('selloCFD'),
109
+ sat_certificate_num: complement.attr('noCertificadoSAT'),
110
+ sat_stamp: complement.attr('selloSAT')
111
+ )
112
+ end
113
+
114
+ xml.xpath('//Traslado').each do |node|
115
+ invoice.taxes.transferred << Transferred.new(
116
+ tax: node.attr('impuesto'),
117
+ rate: node.attr('tasa').to_f,
118
+ import: node.attr('importe').to_f
119
+ )
120
+ end
121
+
122
+ xml.xpath('//Retencion').each do |node|
123
+ invoice.taxes.detained << Detained.new(
124
+ tax: node.attr('impuesto'),
125
+ rate: node.attr('tasa').to_f,
126
+ import: node.attr('importe').to_f
127
+ )
128
+ end
129
+
130
+ invoice
131
+ end # from_xml
132
+ end
data/lib/m_cfdi.rb CHANGED
@@ -9,6 +9,7 @@ require "m_cfdi/entity"
9
9
  require "m_cfdi/key"
10
10
  require "m_cfdi/taxes"
11
11
  require "m_cfdi/invoice"
12
+ require "m_cfdi/xml"
12
13
 
13
14
  module MCFDI
14
15
  # Your code goes here...
data/m_cfdi.gemspec CHANGED
@@ -29,5 +29,7 @@ Gem::Specification.new do |spec|
29
29
  spec.add_development_dependency "bundler", "~> 1.10"
30
30
  spec.add_development_dependency "rake", "~> 10.0"
31
31
  spec.add_development_dependency "rspec"
32
- spec.add_development_dependency 'nokogiri', '~> 1.6'
32
+ spec.add_dependency 'nokogiri', '~> 1.6'
33
+ spec.add_dependency 'number_to_words', '~> 1.2'
34
+ spec.add_dependency 'rqrcode_png', '~> 0.1'
33
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: m_cfdi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yaser Almasri
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-12-04 00:00:00.000000000 Z
11
+ date: 2015-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -59,13 +59,41 @@ dependencies:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '1.6'
62
- type: :development
62
+ type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.6'
69
+ - !ruby/object:Gem::Dependency
70
+ name: number_to_words
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.2'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.2'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rqrcode_png
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.1'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.1'
69
97
  description: CFDI Mexico, To generate XML files from invoices of Mexico, Comprobantes
70
98
  Fiscales Digitales por Internet
71
99
  email:
@@ -96,6 +124,7 @@ files:
96
124
  - lib/m_cfdi/key.rb
97
125
  - lib/m_cfdi/taxes.rb
98
126
  - lib/m_cfdi/version.rb
127
+ - lib/m_cfdi/xml.rb
99
128
  - m_cfdi.gemspec
100
129
  homepage: https://github.com/MaSys/cfdi
101
130
  licenses: []