Class: VerifactuRails::Respuesta

Inherits:
Object
  • Object
show all
Defined in:
lib/verifactu_rails/respuesta.rb

Overview

Respuesta de la AEAT a un envío de registros (RespuestaSuministro.xsd).

Solo lee: no valida contra el esquema ni impone reglas de negocio. Lo que llega de la AEAT es la verdad, y una respuesta que no encaje con lo que esperamos no debe impedir leer el resto.

El punto que más importa entender: EstadoRegistro tiene TRES valores, no dos. "AceptadoConErrores" significa que el registro SÍ quedó anotado en la AEAT pero arrastra un error que hay que subsanar. Tratarlo como fallo lleva a reenviar un registro que ya existe (y a un rechazo por duplicado); tratarlo como éxito deja una obligación pendiente sin que nadie se entere.

Defined Under Namespace

Classes: Duplicado, Linea

Constant Summary collapse

NS =
'https://www2.agenciatributaria.gob.es/static_files/common/internet/' \
'dep/aplicaciones/es/aeat/tike/cont/ws/RespuestaSuministro.xsd'
NS_SF =
'https://www2.agenciatributaria.gob.es/static_files/common/internet/' \
'dep/aplicaciones/es/aeat/tike/cont/ws/SuministroInformacion.xsd'
NS_SOAP =
'http://schemas.xmlsoap.org/soap/envelope/'
ESTADOS_ENVIO =
%w[Correcto ParcialmenteCorrecto Incorrecto].freeze
ESTADOS_REGISTRO =
%w[Correcto AceptadoConErrores Incorrecto].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(xml) ⇒ Respuesta

Returns a new instance of Respuesta.

Parameters:

  • xml (String)

    cuerpo devuelto por Transporte#enviar



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/verifactu_rails/respuesta.rb', line 62

def initialize(xml)
  @xml = xml
  doc = Nokogiri::XML(xml)
  raiz = doc.at_xpath('//r:RespuestaRegFactuSistemaFacturacion', 'r' => NS)

  if raiz.nil?
    raise RespuestaError,
          "La respuesta no contiene RespuestaRegFactuSistemaFacturacion. " \
          "#{resumen_de_fallo(doc)}"
  end

  @csv = texto(raiz, 'r:CSV')
  @estado_envio = texto(raiz, 'r:EstadoEnvio')
  @tiempo_espera = texto(raiz, 'r:TiempoEsperaEnvio')&.to_i
  @nif_presentador = texto(raiz, 'r:DatosPresentacion/sf:NIFPresentador')
  @timestamp_presentacion = texto(raiz, 'r:DatosPresentacion/sf:TimestampPresentacion')
  @lineas = raiz.xpath('r:RespuestaLinea', 'r' => NS).map { |n| leer_linea(n) }
end

Instance Attribute Details

#csvObject (readonly)

Returns the value of attribute csv.



58
59
60
# File 'lib/verifactu_rails/respuesta.rb', line 58

def csv
  @csv
end

#estado_envioObject (readonly)

Returns the value of attribute estado_envio.



58
59
60
# File 'lib/verifactu_rails/respuesta.rb', line 58

def estado_envio
  @estado_envio
end

#lineasObject (readonly)

Returns the value of attribute lineas.



58
59
60
# File 'lib/verifactu_rails/respuesta.rb', line 58

def lineas
  @lineas
end

#nif_presentadorObject (readonly)

Returns the value of attribute nif_presentador.



58
59
60
# File 'lib/verifactu_rails/respuesta.rb', line 58

def nif_presentador
  @nif_presentador
end

#tiempo_esperaObject (readonly)

Returns the value of attribute tiempo_espera.



58
59
60
# File 'lib/verifactu_rails/respuesta.rb', line 58

def tiempo_espera
  @tiempo_espera
end

#timestamp_presentacionObject (readonly)

Returns the value of attribute timestamp_presentacion.



58
59
60
# File 'lib/verifactu_rails/respuesta.rb', line 58

def timestamp_presentacion
  @timestamp_presentacion
end

#xmlObject (readonly)

Returns the value of attribute xml.



58
59
60
# File 'lib/verifactu_rails/respuesta.rb', line 58

def xml
  @xml
end

Instance Method Details

#a_subsanarObject

Las que quedaron anotadas pero obligan a subsanar. Es la lista que hay que mirar cuando el envío sale "Correcto" y uno se relaja: un envío puede ser globalmente correcto y aun así contener registros con esta marca.



91
# File 'lib/verifactu_rails/respuesta.rb', line 91

def a_subsanar = lineas.select(&:aceptado_con_errores?)

#anotadasObject



85
# File 'lib/verifactu_rails/respuesta.rb', line 85

def anotadas = lineas.select(&:anotado?)

#correcto?Boolean

Returns:

  • (Boolean)


81
# File 'lib/verifactu_rails/respuesta.rb', line 81

def correcto? = estado_envio == 'Correcto'

#esperar_hasta(desde = nil) ⇒ Object

Segundos que hay que esperar antes del siguiente envío, o acumular hasta el límite de lote, lo que ocurra primero.



95
96
97
98
99
# File 'lib/verifactu_rails/respuesta.rb', line 95

def esperar_hasta(desde = nil)
  return nil if tiempo_espera.nil?

  (desde || Time.now) + tiempo_espera
end

#incorrecto?Boolean

Returns:

  • (Boolean)


83
# File 'lib/verifactu_rails/respuesta.rb', line 83

def incorrecto? = estado_envio == 'Incorrecto'

#parcialmente_correcto?Boolean

Returns:

  • (Boolean)


82
# File 'lib/verifactu_rails/respuesta.rb', line 82

def parcialmente_correcto? = estado_envio == 'ParcialmenteCorrecto'

#rechazadasObject



86
# File 'lib/verifactu_rails/respuesta.rb', line 86

def rechazadas = lineas.select(&:incorrecto?)

#to_sObject

El recuento es de LOS REGISTROS DE ESTE ENVÍO, no de la cadena: la AEAT responde sobre lo que le mandaste en esta petición. Una cadena de tres eslabones puede haberse construido en tres envíos de un registro cada uno.



104
105
106
107
108
# File 'lib/verifactu_rails/respuesta.rb', line 104

def to_s
  registros = lineas.size == 1 ? '1 registro en este envío' : "#{lineas.size} registros en este envío"
  "#{estado_envio} (#{registros}: #{anotadas.size} anotados, " \
    "#{a_subsanar.size} a subsanar, #{rechazadas.size} rechazados)"
end