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 +4 -4
- data/README.md +11 -4
- data/lib/m_cfdi/complement.rb +4 -3
- data/lib/m_cfdi/invoice.rb +22 -3
- data/lib/m_cfdi/taxes.rb +2 -1
- data/lib/m_cfdi/version.rb +1 -1
- data/lib/m_cfdi/xml.rb +132 -0
- data/lib/m_cfdi.rb +1 -0
- data/m_cfdi.gemspec +3 -1
- metadata +32 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae85da182607c7e669c5cf6da65cb1687f1ca92d
|
4
|
+
data.tar.gz: 0c94217b234df9b8e054d006e5aec50d184f8444
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
```
|
10
|
-
gem 'm_cfdi'
|
9
|
+
```bash
|
10
|
+
gem 'm_cfdi'
|
11
11
|
```
|
12
12
|
|
13
13
|
or
|
14
14
|
|
15
|
-
```
|
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
|
-
```
|
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
|
data/lib/m_cfdi/complement.rb
CHANGED
@@ -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
|
-
|
17
|
-
|
18
|
-
|
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('|')}||"
|
data/lib/m_cfdi/invoice.rb
CHANGED
@@ -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(
|
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
|
37
|
+
c = Transferred.new(c) unless c.is_a? Tansferred
|
37
38
|
@transferred << c
|
38
39
|
end
|
39
40
|
elsif data.is_a? Hash
|
data/lib/m_cfdi/version.rb
CHANGED
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
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.
|
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.
|
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-
|
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: :
|
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: []
|