From 0498217b65ff5aaadc90d0151a774af35dedc519 Mon Sep 17 00:00:00 2001 From: El Mau Date: Tue, 18 Jan 2022 23:28:52 -0600 Subject: [PATCH] =?UTF-8?q?Iniciar=20representaci=C3=B3n=20impresa=20de=20?= =?UTF-8?q?Carta=20Porte?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/app/controllers/util.py | 55 +++++++++++++++++- source/app/controllers/utils.py | 98 +++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+), 1 deletion(-) diff --git a/source/app/controllers/util.py b/source/app/controllers/util.py index a217182..088795e 100644 --- a/source/app/controllers/util.py +++ b/source/app/controllers/util.py @@ -934,6 +934,52 @@ class LIBO(object): cell3 = self._set_cell(v=disposicion, cell=cell3) return + def _carta_porte(self, data): + if not data: + return + + # ~ print(data) + figuras = data.pop('figuras') + mercancias = data.pop('mercancias') + autotransporte = data.pop('autotransporte') + ubicaciones = data.pop('ubicaciones') + + for k, v in data.items(): + self._set_cell(f'{{cp.{k}}}', v) + for k, v in figuras.items(): + self._set_cell(f'{{cp.{k}}}', v) + for k, v in autotransporte.items(): + self._set_cell(f'{{cp.{k}}}', v) + + first = True + count = len(ubicaciones) - 1 + for i, ubicacion in enumerate(ubicaciones): + tipo = ubicacion['TipoUbicacion'] + nombre = ubicacion['NombreRemitenteDestinatario'] + rfc = ubicacion['RFCRemitenteDestinatario'] + nombre_rfc = f"{nombre} ({rfc})" + fecha = ubicacion['FechaHoraSalidaLlegada'] + domicilio = ubicacion['domicilio'] + if first: + first = False + cell_1 = self._set_cell('{cp.TipoUbicacion}', tipo) + cell_2 = self._set_cell('{cp.NombreRemitenteDestinatario}', nombre) + cell_3 = self._set_cell('{cp.RFCRemitenteDestinatario}', rfc) + cell_4 = self._set_cell('{cp.FechaHoraSalidaLlegada}', fecha) + cell_5 = self._set_cell('{cp.Domicilio}', domicilio) + + row = cell_1.CellAddress.Row + 1 + try: + self._sheet.Rows.insertByIndex(row, count) + except Exception as e: + print(e) + # ~ self._copy_paste_rows(cell_1, count) + # ~ row = cell_1.getCellAddress().Row + # ~ else: + # ~ cell_1 = self._set_cell(v=tipo, cell=cell_1) + + return + def _nomina(self, data): if not data: return @@ -1162,6 +1208,7 @@ class LIBO(object): self._divisas(data.get('divisas', {})) self._leyendas(data.get('leyendas', '')) + self._carta_porte(data.get('carta_porte', {})) self._cancelado(data['cancelada']) self._others_values(data) @@ -1479,10 +1526,16 @@ def to_pdf(data, emisor_rfc, ods=False, pdf_from='1'): default = 'plantilla_factura.ods' if DEBUG: rfc = emisor_rfc + version = data['comprobante']['version'] + if 'nomina' in data and data['nomina']: - version = '{}_{}'.format(data['nomina']['version'], version) default = 'plantilla_nomina.ods' + version = '{}_{}'.format(data['nomina']['version'], version) + + if 'carta_porte' in data: + default = 'plantilla_factura_cp.ods' + version = '{}_cp_{}'.format(version, data['carta_porte']['version']) pagos = '' if data.get('pagos', False): diff --git a/source/app/controllers/utils.py b/source/app/controllers/utils.py index 22cc7c0..2497bff 100644 --- a/source/app/controllers/utils.py +++ b/source/app/controllers/utils.py @@ -260,6 +260,51 @@ class CfdiToDict(object): 'cfdi': 'http://www.sat.gob.mx/cfd/3', 'divisas': 'http://www.sat.gob.mx/divisas', 'leyendasFisc': 'http://www.sat.gob.mx/leyendasFiscales', + 'cartaporte20': 'http://www.sat.gob.mx/CartaPorte20', + } + tipo_figura = { + '01': '[01] Operador', + '02': '[02] Propietario', + '03': '[03] Arrendador', + '04': '[04] Notificado', + } + PAISES = { + 'MEX': 'México', + } + ESTADOS = { + 'AGU': 'Aguascalientes', + 'BCN': 'Baja California', + 'BCS': 'Baja California Sur', + 'CAM': 'Campeche', + 'CHP': 'Chiapas', + 'CHH': 'Chihuahua', + 'COA': 'Coahuila', + 'COL': 'Colima', + 'DIF': 'Ciudad de México', + 'DUR': 'Durango', + 'GUA': 'Guanajuato', + 'GRO': 'Guerrero', + 'HID': 'Hidalgo', + 'JAL': 'Jalisco', + 'MEX': 'México', + 'MIC': 'Michoacán', + 'MOR': 'Morelos', + 'NAC': 'Nacional', + 'NAY': 'Nayarit', + 'NLE': 'Nuevo León', + 'OAX': 'Oaxaca', + 'PUE': 'Puebla', + 'QUE': 'Querétaro', + 'ROO': 'Quintana Roo', + 'SLP': 'San Luis Potosí', + 'SIN': 'Sinaloa', + 'SON': 'Sonora', + 'TAB': 'Tabasco', + 'TAM': 'Tamaulipas', + 'TLA': 'Tlaxcala', + 'VER': 'Veracruz', + 'YUC': 'Yucatán', + 'ZAC': 'Zacatecas', } def __init__(self, xml): @@ -277,6 +322,13 @@ class CfdiToDict(object): self._complementos() return + def _set_carta_porte_domicilio(self, data): + municipio = data['Municipio'] + estado = self.ESTADOS[data['Estado']] + pais = self.PAISES[data['Pais']] + domicilio = f"{municipio}, {estado}, {pais}, C.P. {data['CodigoPostal']}" + return domicilio + def _complementos(self): path = '//cfdi:Complemento' complemento = self._root.xpath(path, namespaces=self.NS)[0] @@ -293,6 +345,52 @@ class CfdiToDict(object): if node: leyendas = [CaseInsensitiveDict(n.attrib) for n in node] self._values['leyendas'] = leyendas + + path = '//cartaporte20:CartaPorte' + carta_porte = complemento.xpath(path, namespaces=self.NS) + if carta_porte: + values = CaseInsensitiveDict(carta_porte[0].attrib) + for node in carta_porte[0]: + if 'FiguraTransporte' in node.tag: + figuras = CaseInsensitiveDict(node[0].attrib) + figuras['TipoFigura'] = self.tipo_figura[figuras['TipoFigura']] + values['figuras'] = figuras + elif 'Mercancias' in node.tag: + mercancias = [CaseInsensitiveDict(n.attrib) + for n in node if 'Mercancia' in n.tag] + values['mercancias'] = mercancias + + path = '//cartaporte20:Autotransporte' + node_auto = node.xpath(path, namespaces=self.NS)[0] + values_auto = CaseInsensitiveDict(node_auto.attrib) + values['autotransporte'] = values_auto + + path = '//cartaporte20:IdentificacionVehicular' + node_tmp = node_auto.xpath(path, namespaces=self.NS)[0] + values_auto = CaseInsensitiveDict(node_tmp.attrib) + values['autotransporte'].update(values_auto) + + path = '//cartaporte20:Seguros' + node_tmp = node_auto.xpath(path, namespaces=self.NS)[0] + values_auto = CaseInsensitiveDict(node_tmp.attrib) + values['autotransporte'].update(values_auto) + + path = '//cartaporte20:Remolques' + node_tmp = node_auto.xpath(path, namespaces=self.NS)[0][0] + values_auto = CaseInsensitiveDict(node_tmp.attrib) + values['autotransporte'].update(values_auto) + elif 'Ubicaciones' in node.tag: + ubicaciones = [] + for n in node: + ubicacion = CaseInsensitiveDict(n.attrib) + ubicacion['domicilio'] = self._set_carta_porte_domicilio( + CaseInsensitiveDict(n[0].attrib)) + ubicaciones.append(ubicacion) + + values['ubicaciones'] = ubicaciones + + self._values['carta_porte'] = values + return