Source code for satcfdi.cfdi

import logging
import os
import lxml.etree
from weasyprint import CSS

from . import CFDIError, XElement
from .transform import *
from .transform.helpers import fmt_decimal

current_dir = os.path.dirname(__file__)
logger = logging.getLogger(__name__)

VERIFICA_CFDI = "https://verificacfdi.facturaelectronica.sat.gob.mx/default.aspx"
VERIFICA_RETENCION = "https://prodretencionverificacion.clouda.sat.gob.mx/"
PDF_CSS = CSS(string="@page {margin: 1.0cm 1.27cm 1.1cm 0.85cm;}")


[docs]class CFDI(XElement):
[docs] def to_xml(self, validate=False, include_schema_location=True) -> lxml.etree.Element: return super().to_xml(validate, include_schema_location)
[docs] def xml_bytes(self, pretty_print=False, xml_declaration=True, validate=False, include_schema_location=True) -> bytes: return super().xml_bytes(pretty_print=pretty_print, xml_declaration=xml_declaration, validate=validate, include_schema_location=include_schema_location)
[docs] def process(self, validate=False) -> 'CFDI': return CFDI.from_xml(self.to_xml(validate=validate))
[docs] def copy(self) -> 'CFDI': cfdi = CFDI(super().copy()) cfdi.tag = self.tag return cfdi
@property def verifica_url(self) -> str: match self.tag: case '{http://www.sat.gob.mx/cfd/3}Comprobante' | '{http://www.sat.gob.mx/cfd/4}Comprobante': base_url = VERIFICA_CFDI q = { "id": self['Complemento']['TimbreFiscalDigital']["UUID"], "re": self['Emisor']["Rfc"], "rr": self['Receptor']["Rfc"], "tt": fmt_decimal(self["Total"]), "fe": self["Sello"][-8:] } case '{http://www.sat.gob.mx/esquemas/retencionpago/1}Retenciones': base_url = VERIFICA_RETENCION q = { "id": self["Complemento"]["TimbreFiscalDigital"]["UUID"], "re": self['Emisor']["RFCEmisor"], "tt": fmt_decimal(self['Totales']["MontoTotOperacion"]), "fe": self["Sello"][-8:] } match self['Receptor']['Nacionalidad']: case "Nacional": q["rr"] = self['Receptor']['Nacional']["RFCRecep"] case "Extranjero": if nr := self['Receptor']['Extranjero'].get("NumRegIdTrib"): q["nr"] = nr case '{http://www.sat.gob.mx/esquemas/retencionpago/2}Retenciones': base_url = VERIFICA_RETENCION q = { "id": self["Complemento"]["TimbreFiscalDigital"]["UUID"], "re": self['Emisor']["RfcE"], "tt": fmt_decimal(self['Totales']["MontoTotOperacion"]), "fe": self["Sello"][-8:] } match self['Receptor']['NacionalidadR']: case "Nacional": q["rr"] = self['Receptor']['Nacional']["RfcR"] case "Extranjero": if nr := self['Receptor']['Extranjero'].get("NumRegIdTribR"): q["nr"] = nr case _: raise CFDIError("No Verification URL found") if base_url: return base_url + "?" + "&".join(f"{k}={v}" for k, v in q.items())
[docs] def cadena_original(self): transform = xslt_transform(self.tag, self['Version']) xml = super().to_xml() return str(transform(xml))