Generación de Adendas
Closed
Generación de Adendas
Actualmente la forma en la que se está proponiendo hacer la generación de las adendas es a través de duplicar la plantilla del XML y personalizarla para que, utilizando el mecanismo que permite tener multiples templates y seleccionar el que se va a utilizar en cada reporte a través de un dominio que evalúa ciertas condiciones del objeto que está generando el reporte.
El problema con esta aproximación es que se tiene que repetir completamente la plantilla cada vez que se quiera generar una nueva adenda, generando con ello mucho código duplicado con la consecuente complicación en el mantenimiento de todos los templates pues las correcciones se tendrían que aplicar en todos los templates.
Una forma de disminuir el costo de mantenimiento de las adendas sería encontrar la forma de incluir sub-reportes en un reporte de aeroo (genshi soporta esta característica por defecto) de manera que cada adenda pudiera tener su propio reporte únicamente con el contenido necesario para colocar en el nodo de adenda, y el template del XML de la factura simplemente incluya este reporte cuando se necesite. De esta forma se mantendría únicamente una sola versión del template del XML de la factura y un template específico para cada adenda.
Saludos @agb80 Para solventar esto, algo que se me ocurre que podría hacerse, es lo siguiente:
- Heredar y Agregar un campo en "cfdi.adenda", que enlace a su template donde esté definido para la adenda específica.
- Heredar "ir.attachment.facturae.mx" e interceptar al metodo "create_report_xml": http://gitlab.openpyme.mx/l10n_mx/facturacion/blob/master/l10n_mx_ir_attachment_facturae/models/ir_attachment_facturae.py#L700
En dicho método, se obtiene un XML como Tal con el XMl estándar del CFDI generado, ya que es pasado por la funcion .
Lo que se me ocurre, es evaluar en ese momento, si el Registro actual, sobre el que se generó el Reporte, es sujeto a alguna Addenda, entonces, se genera dicha Addenda y se integra al documento interceptado.
tomar en cuenta, que de igual manera, a parte del contenido, tal vez se tendrían que agregar algunos namespace, como en el caso de Comercio Exterior tal vez, o algún otro complemento o Addenda específica.
Por lo general, hay addendas que no necesitan un namespace.
Adjunto un pequeño diagrama que visualice la idea.
Gracias! Saludos!
La idea que tienes es muy similar a la forma en la que estaba yo visualizando que se tenía que hacer, nada más hay 2 pequeños cambios que yo le haría y me quedarían algunas dudas:
Cambios:
- Heredar "ir.attachment.facturae.mx" e interceptar al metodo "create_report_xml". Creo que más bien esta funcionalidad deberíamos incluirla directamente en el módulo l10n_mx_ir_attachment_facturae, de esa forma el mecanismo de creación de adendas estaría disponible en todo momento con lo que simplificaríamos enormemente la creación de adendas. Incluso pienso que así se podrían llegar a generar las adendas directamente en la interface gráfica sin tener que instalar ningún módulo adicional al sistema.
- En el objeto
cfdi.adenda
también le agregaría un campo para relacionar la adenda con un modelo en particular. Según nos estaban explicando recientemente los del PAC técnicamente cualquier CFDI puede llevar adenda, así que si no tenemos un mecanismo para filtrar las adendas disponibles para un CFDI de ingresos, egresos o cualquier otro, entonces podríamos llegar a agregar adendas donde no deberían de ir.
Duda:
- En la función que adjunta la adenda al XML original (
appendChild
según el diagrama que pones), ¿los namespaces con que se haya generado la adenda también se agregan automáticamente al XML o hay que hacer algún procesamiento adicional?
@agb80 Me parece muy bien asi como dices, y si, las Addendas podrían ser generadas de manera gráfica y como dices, entonces quedaría definido que se tiene que categorizar en base al modelo donde se aplicaría.
En cuanto a la duda:
Eso es algo que habría que ver con pruebas, al momento de hacer el parse_xml_string de la addenda, no estoy seguro, pero creo que en ese momento deberían agregarse todos los namespaces.
Algun ejemplo que te puedo decir, es aqui: http://gitlab.openpyme.mx/chavamm.83/l10n_mx_facturae_complemento/blob/master/invoice.py#L191
Dichos valores vienen de este metodo: http://gitlab.openpyme.mx/chavamm.83/l10n_mx_facturae_detallista/blob/master/invoice.py#L47
Y son setteados justo despues de haber generado el XML de la Addenda y de haberla agregado al CFDI, aqui: http://gitlab.openpyme.mx/chavamm.83/l10n_mx_facturae_complemento/blob/master/invoice.py#L206
Como ejemplo, esto es lo que hice en su momento para Complemento Detallista para Liverpool:
xsi_schemans = "http://www.w3.org/2001/XMLSchema-instance" ns_xmlns = "http://www.w3.org/2000/xmlns/" ns_xsd_sat = nodeComprobante.getAttribute('xsi:schemaLocation')
ns = "http://www.sat.gob.mx/detallista" xsd = "http://www.sat.gob.mx/sitio_internet/cfd/detallista/detallista.xsd" xml_ns = 'xmlns:detallista'
nodeComprobante.setAttributeNS(xsi_schemans, 'xsi:schemaLocation', ns_xsd_sat + ' ' + ns + ' ' + xsd) nodeComprobante.setAttributeNS(ns_xmlns, xml_ns, ns)
Eso es para que sea valido la construccion del XML que se hace de esta manera por ejemplo:
detallista:specialInstruction
Claro, este ejemplo que paso lineas arriba, es de hace ya algunos años, y tal vez no fue la mejor manera de hacerlo.
En conclusión, Los namespaces, deben ir configurados, ya sea, en la configuracion de la addenda (cfdi.adenda) o bien, que se estandarizara, el agregar en el template un nodo, que no sea parte de la adenda como tal, es decir, que los templates para addendas, se definiera algo asi:
<namespaces> <ns>http://www.sat.gob.mx/detallista</ns> <xsd>http://www.sat.gob.mx/sitio_internet/cfd/detallista/detallista.xsd</xsd> <xmlns>xmlns:detallista</xmlns> </namespaces> <Addenda>...Aqui los nodos que conformen la Addenda...</Addenda>
Al momento de que parse_xml_string nos devuelva el xml del template anterior, obtenemos la definición de namespaces, si la tuviera, entonces, se obtienen los datos y una vez obtenidos, se remueve dicho nodo de definición de namespaces. Para poder despues ser Setteados los Namespaces al documento CFDI ya con la Addenda Incluida.
Es solo una idea, espero que sirva para llegar juntos a la obtención de la mejor solución.
Saludos!
El día de hoy trabajando en algunos detalles de las facturas me topé con este código que creo que nos viene muy bien para la generación de las adendas y que me aclaró mucho como funcionan los archivos XML:
tree = fromstring(base64.decodestring(xml_signed)) addenda_node = tree.Addenda if hasattr( tree, 'Addenda') else etree.Element(etree.QName( 'http://www.sat.gob.mx/cfd/3', 'Addenda')) addenda_node.append(fromstring(addenda.render(values=values))) tree.append(addenda_node) return base64.encodestring(etree.tostring( tree, pretty_print=True, xml_declaration=True, encoding='UTF-8'))
Como se puede apreciar, después de generado el archivo XML y firmado se parsea y se trata de obtener el nodo adenda, si no existe se crea. Después simplemente se genera la adenda y se agrega al contenido del nodo adenda antes generado.
De hecho prácticamente con el pedazo de código que acabo de pegar tenemos toda la lógica implementada.