Module: CFDI

Defined in:
lib/cfdi.rb,
lib/key.rb,
lib/xml.rb,
lib/comun.rb,
lib/addenda.rb,
lib/entidad.rb,
lib/version.rb,
lib/concepto.rb,
lib/impuestos.rb,
lib/certificado.rb,
lib/complemento.rb,
lib/comprobante.rb

Overview

Comprobantes fiscales digitales por los internets

El sistema de generación y sellado de facturas es una patada en los genitales. Este gem pretende ser una bolsa de hielos. Igual va a doler, pero espero que al menos no quede moretón.

Defined Under Namespace

Classes: Addenda, Certificado, Complemento, Comprobante, Concepto, Domicilio, ElementoComprobante, Entidad, Impuestos, Key

Constant Summary collapse

METODOS_DE_PAGO =

Porque SAT, los métodos de pago con su clave

Returns:

  • (Hash)

    La clave y su valor como texto

{
  '01' => 'Efectivo',
  '02' => 'Cheque nominativo',
  '03' => 'Transferencia electrónica de fondos',
  '04' => 'Tarjeta de crédito',
  '05' => 'Monedero electrónico',
  '06' => 'Dinero electrónico',
  '08' => 'Vales de despensa',
  '28' => 'Tarjeta de débito',
  '29' => 'Tarjeta de servicio',
  '99' => 'Otros',
}
VERSION =

La versión de este gem

'1.0.0'

Class Method Summary collapse

Class Method Details

.from_xml(data) ⇒ CFDI::Comprobante

Crea un CFDI::Comprobante desde un string XML

Parameters:

  • data (String, IO)

    El XML a parsear, según acepte Nokogiri

Returns:



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/xml.rb', line 8

def self.from_xml(data)
  xml = Nokogiri::XML(data);
  xml.remove_namespaces!
  factura = Comprobante.new

  comprobante = xml.at_xpath('//Comprobante')
  emisor = xml.at_xpath('//Emisor')
  de = emisor.at_xpath('//DomicilioFiscal')
  exp = emisor.at_xpath('//ExpedidoEn')
  receptor = xml.at_xpath('//Receptor')
  dr = receptor.at_xpath('//Domicilio')

  factura.version = comprobante.attr('version')
  factura.serie = comprobante.attr('serie')
  factura.folio = comprobante.attr('folio')
  factura.fecha = Time.parse(comprobante.attr('fecha'))
  factura.noCertificado = comprobante.attr('noCertificado')
  factura.certificado = comprobante.attr('certificado')
  factura.sello = comprobante.attr('sello')
  factura.formaDePago = comprobante.attr('formaDePago')
  factura.condicionesDePago = comprobante.attr('condicionesDePago')
  factura.tipoDeComprobante = comprobante.attr('tipoDeComprobante')
  factura.lugarExpedicion = comprobante.attr('LugarExpedicion')
  factura.metodoDePago = comprobante.attr('metodoDePago')
  factura.moneda = comprobante.attr('Moneda')
  factura.NumCtaPago = comprobante.attr('NumCtaPago')
  factura.total = comprobante.attr('total').to_f
  factura.subTotal = comprobante.attr('subTotal').to_f


  rf = emisor.at_xpath('//RegimenFiscal')

  emisor = {
    rfc: emisor.attr('rfc'),
    nombre: emisor.attr('nombre'),
    regimenFiscal: rf  && rf.attr('Regimen'),
    domicilioFiscal: {
      calle: de.attr('calle'),
      noExterior: de.attr('noExterior'),
      noInterior: de.attr('noInterior'),
      colonia: de.attr('colonia'),
      localidad: de.attr('localidad'),
      referencia: de.attr('referencia'),
      municipio: de.attr('municipio'),
      estado: de.attr('estado'),
      pais: de.attr('pais'),
      codigoPostal: de.attr('codigoPostal')
    }
  }

  if exp
    emisor[:expedidoEn] = {
      calle: exp.attr('calle'),
      noExterior: exp.attr('noExterior'),
      no_int: exp.attr('noInterior'),
      colonia: exp.attr('colonia'),
      localidad: exp.attr('localidad'),
      referencia: exp.attr('referencia'),
      municipio: exp.attr('municipio'),
      estado: exp.attr('estado'),
      pais: exp.attr('pais'),
      codigoPostal: exp.attr('codigoPostal')
    }
  end

  factura.emisor = emisor;

  factura.receptor = {
    rfc: receptor.attr('rfc'),
    nombre: receptor.attr('nombre')
  }

  if dr
    factura.receptor.domicilioFiscal = {
      calle: dr.attr('calle'),
      noExterior: dr.attr('noExterior'),
      noInterior: dr.attr('noInterior'),
      colonia: dr.attr('colonia'),
      localidad: dr.attr('localidad'),
      referencia: dr.attr('referencia'),
      municipio: dr.attr('municipio'),
      estado: dr.attr('estado'),
      pais: dr.attr('pais'),
      codigoPostal: dr.attr('codigoPostal')
    }
  end

  factura.conceptos = []
  #puts "conceptos: #{factura.conceptos.length}"
  xml.xpath('//Concepto').each do |concepto|
    hash = {
      cantidad: concepto.attr('cantidad').to_f,
      unidad: concepto.attr('unidad'),
      noIdentificacion: concepto.attr('noIdentificacion'),
      descripcion: concepto.attr('descripcion'),
      valorUnitario: concepto.attr('valorUnitario').to_f
    }
    factura.conceptos << Concepto.new(hash)
  end

  timbre = xml.at_xpath('//TimbreFiscalDigital')
  if timbre
    version = timbre.attr('version');
    uuid = timbre.attr('UUID')
    fecha = timbre.attr('FechaTimbrado')
    sello = timbre.attr('selloCFD')
    certificado = timbre.attr('noCertificadoSAT')
    factura.complemento = {
      UUID: uuid,
      selloCFD: sello,
      FechaTimbrado: fecha,
      noCertificadoSAT: certificado,
      version: version,
      selloSAT: timbre.attr('selloSAT')
    }
  end

  impuestos_node = comprobante.at_xpath('//Impuestos')

  traslados_node = impuestos_node.xpath('//Traslados')
  unless traslados_node.empty?
    factura.impuestos.totalImpuestosTrasladados = impuestos_node.attr('totalImpuestosTrasladados')
    traslados = []
    traslados_node.xpath('//Traslado').each do |traslado_node|
      traslado = Impuestos::Traslado.new
      traslado.impuesto = traslado_node.attr('impuesto') if traslado_node.attr('impuesto')
      traslado.tasa = traslado_node.attr('tasa').to_f if traslado_node.attr('tasa')
      traslado.importe = traslado_node.attr('importe').to_f if traslado_node.attr('importe')
      traslados << traslado
    end
    factura.impuestos.traslados = traslados
  end

  retenciones_node = impuestos_node.xpath('//Retenciones')
  unless retenciones_node.empty?
    factura.impuestos.totalImpuestosRetenidos = impuestos_node.attr('totalImpuestosRetenidos')
    retenciones = []
    retenciones_node.xpath('//Retencion').each do |retencion_node|
      retencion = Impuestos::Retencion.new
      retencion.impuesto = retencion_node.attr('impuesto') if retencion_node.attr('impuesto')
      retencion.tasa = retencion_node.attr('tasa').to_f if retencion_node.attr('tasa')
      retencion.importe = retencion_node.attr('importe').to_f if retencion_node.attr('importe')
      retenciones << retencion
    end
    factura.impuestos.retenciones = retenciones
  end

  factura

end

.metodos_de_pagoObject

alias



42
43
44
# File 'lib/cfdi.rb', line 42

def self.metodos_de_pago
  METODOS_DE_PAGO
end