m_cfdi 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 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: []