PDF from Carta Porte v3
This commit is contained in:
parent
7f129b84b2
commit
29bfb42abc
|
@ -30,6 +30,7 @@ import requests
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import textwrap
|
import textwrap
|
||||||
import threading
|
import threading
|
||||||
|
@ -44,7 +45,6 @@ from pathlib import Path
|
||||||
from xml.etree import ElementTree as ET
|
from xml.etree import ElementTree as ET
|
||||||
from xml.dom.minidom import parseString
|
from xml.dom.minidom import parseString
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import uno
|
import uno
|
||||||
from com.sun.star.beans import PropertyValue
|
from com.sun.star.beans import PropertyValue
|
||||||
|
@ -52,9 +52,20 @@ try:
|
||||||
from com.sun.star.view.PaperFormat import LETTER
|
from com.sun.star.view.PaperFormat import LETTER
|
||||||
APP_LIBO = True
|
APP_LIBO = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
APP_LIBO = False
|
path_fun = '/usr/lib/libreoffice/program/fundamentalrc'
|
||||||
|
path_uno = '/usr/lib/libreoffice/program/'
|
||||||
|
os.environ['URE_BOOTSTRAP'] = f'vnd.sun.star.pathname:{path_fun}'
|
||||||
|
os.environ['UNO_PATH'] = path_uno
|
||||||
|
sys.path.append(path_uno)
|
||||||
|
try:
|
||||||
|
import uno
|
||||||
|
from com.sun.star.beans import PropertyValue
|
||||||
|
from com.sun.star.awt import Size
|
||||||
|
from com.sun.star.view.PaperFormat import LETTER
|
||||||
|
APP_LIBO = True
|
||||||
|
except ImportError:
|
||||||
|
APP_LIBO = False
|
||||||
|
|
||||||
# ~ import pyqrcode
|
|
||||||
from dateutil import parser
|
from dateutil import parser
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
|
@ -69,7 +80,6 @@ from settings import DEBUG, MV, log, template_lookup, COMPANIES, DB_SAT, \
|
||||||
PATH_XMLSEC, TEMPLATE_CANCEL, DEFAULT_SAT_PRODUCTO, DECIMALES, DIR_FACTURAS
|
PATH_XMLSEC, TEMPLATE_CANCEL, DEFAULT_SAT_PRODUCTO, DECIMALES, DIR_FACTURAS
|
||||||
|
|
||||||
from settings import USAR_TOKEN, API, DECIMALES_TAX
|
from settings import USAR_TOKEN, API, DECIMALES_TAX
|
||||||
# ~ from .configpac import AUTH
|
|
||||||
|
|
||||||
|
|
||||||
from .utils import get_qr
|
from .utils import get_qr
|
||||||
|
@ -951,6 +961,7 @@ class LIBO(object):
|
||||||
return
|
return
|
||||||
|
|
||||||
# ~ print(data)
|
# ~ print(data)
|
||||||
|
qr = data.pop('qr', False)
|
||||||
figuras = data.pop('figuras')
|
figuras = data.pop('figuras')
|
||||||
mercancias = data.pop('mercancias')
|
mercancias = data.pop('mercancias')
|
||||||
detalle = mercancias.pop('detalle')
|
detalle = mercancias.pop('detalle')
|
||||||
|
@ -1019,7 +1030,27 @@ class LIBO(object):
|
||||||
cell_3 = self._set_cell(v=unidad, cell=cell_3)
|
cell_3 = self._set_cell(v=unidad, cell=cell_3)
|
||||||
cell_4 = self._set_cell(v=cantidad, cell=cell_4)
|
cell_4 = self._set_cell(v=cantidad, cell=cell_4)
|
||||||
cell_5 = self._set_cell(v=peso, cell=cell_5)
|
cell_5 = self._set_cell(v=peso, cell=cell_5)
|
||||||
|
if qr:
|
||||||
|
self._timbre_carta(qr)
|
||||||
|
return
|
||||||
|
|
||||||
|
def _timbre_carta(self, qr):
|
||||||
|
pd = self._sheet.getDrawPage()
|
||||||
|
image = self._template.createInstance('com.sun.star.drawing.GraphicObjectShape')
|
||||||
|
gp = self._create_instance('com.sun.star.graphic.GraphicProvider')
|
||||||
|
pd.add(image)
|
||||||
|
|
||||||
|
instance = 'com.sun.star.io.SequenceInputStream'
|
||||||
|
stream = self._create_instance(instance)
|
||||||
|
stream.initialize((uno.ByteSequence(qr.getvalue()),))
|
||||||
|
properties = self._set_properties({'InputStream': stream})
|
||||||
|
image.Graphic = gp.queryGraphic(properties)
|
||||||
|
|
||||||
|
s = Size()
|
||||||
|
s.Width = 4000
|
||||||
|
s.Height = 4000
|
||||||
|
image.setSize(s)
|
||||||
|
image.Anchor = self._set_cell('{cp.qr}')
|
||||||
return
|
return
|
||||||
|
|
||||||
def _comercio_exterior(self, data):
|
def _comercio_exterior(self, data):
|
||||||
|
@ -1690,7 +1721,7 @@ def to_pdf(data, emisor_rfc, ods=False, pdf_from='1'):
|
||||||
version = f'{version}_cn_{version_nomina}'
|
version = f'{version}_cn_{version_nomina}'
|
||||||
|
|
||||||
if 'carta_porte' in data:
|
if 'carta_porte' in data:
|
||||||
default = 'plantilla_factura_ccp.ods'
|
default = 'plantilla_ccp.ods'
|
||||||
version = '{}_ccp_{}'.format(version, data['carta_porte']['version'])
|
version = '{}_ccp_{}'.format(version, data['carta_porte']['version'])
|
||||||
|
|
||||||
if data.get('pagos', False):
|
if data.get('pagos', False):
|
||||||
|
@ -1844,24 +1875,6 @@ def to_letters(value, currency):
|
||||||
return NumLet(value, currency).letras
|
return NumLet(value, currency).letras
|
||||||
|
|
||||||
|
|
||||||
# ~ def get_qr(data, p=True):
|
|
||||||
# ~ qr = pyqrcode.create(data, mode='binary')
|
|
||||||
# ~ if p:
|
|
||||||
# ~ path = get_path_temp('.qr')
|
|
||||||
# ~ qr.png(path, scale=7)
|
|
||||||
# ~ return path
|
|
||||||
|
|
||||||
# ~ buffer = io.BytesIO()
|
|
||||||
# ~ qr.png(buffer, scale=8)
|
|
||||||
# ~ return base64.b64encode(buffer.getvalue()).decode()
|
|
||||||
|
|
||||||
|
|
||||||
# ~ def get_qr2(data, kind='svg'):
|
|
||||||
# ~ buffer = io.BytesIO()
|
|
||||||
# ~ segno.make(data).save(buffer, kind=kind, scale=8, border=2)
|
|
||||||
# ~ return buffer
|
|
||||||
|
|
||||||
|
|
||||||
def _get_relacionados(doc, version):
|
def _get_relacionados(doc, version):
|
||||||
node = doc.find('{}CfdiRelacionados'.format(PRE[version]))
|
node = doc.find('{}CfdiRelacionados'.format(PRE[version]))
|
||||||
if node is None:
|
if node is None:
|
||||||
|
@ -3146,7 +3159,8 @@ def parse_xml2(xml_str):
|
||||||
|
|
||||||
|
|
||||||
def get_idccp():
|
def get_idccp():
|
||||||
uuid_v4 = uuid.uuid4()
|
uuid4 = str(uuid.uuid4()).upper()
|
||||||
custom_uuid_str = f"CCC{uuid_v4.hex[3:8].upper()}-{uuid_v4.hex[8:12].upper()}-{uuid_v4.hex[12:16].upper()}-{uuid_v4.hex[16:20].upper()}-{uuid_v4.hex[20:32].upper()}"
|
custom_uuid_str = f'CCC{uuid4[3:]}'
|
||||||
|
# ~ custom_uuid_str = f"CCC{uuid_v4.hex[3:8].upper()}-{uuid_v4.hex[8:12].upper()}-{uuid_v4.hex[12:16].upper()}-{uuid_v4.hex[16:20].upper()}-{uuid_v4.hex[20:32].upper()}"
|
||||||
return custom_uuid_str
|
return custom_uuid_str
|
||||||
|
|
||||||
|
|
|
@ -261,9 +261,11 @@ class CfdiToDict(object):
|
||||||
'cfdi4.0': 'http://www.sat.gob.mx/cfd/4',
|
'cfdi4.0': 'http://www.sat.gob.mx/cfd/4',
|
||||||
}
|
}
|
||||||
NS = {
|
NS = {
|
||||||
|
'tfd': 'http://www.sat.gob.mx/TimbreFiscalDigital',
|
||||||
'divisas': 'http://www.sat.gob.mx/divisas',
|
'divisas': 'http://www.sat.gob.mx/divisas',
|
||||||
'leyendasFisc': 'http://www.sat.gob.mx/leyendasFiscales',
|
'leyendasFisc': 'http://www.sat.gob.mx/leyendasFiscales',
|
||||||
'cartaporte20': 'http://www.sat.gob.mx/CartaPorte20',
|
'cartaporte20': 'http://www.sat.gob.mx/CartaPorte20',
|
||||||
|
'cartaporte30': 'http://www.sat.gob.mx/CartaPorte30',
|
||||||
'nomina12': 'http://www.sat.gob.mx/nomina12',
|
'nomina12': 'http://www.sat.gob.mx/nomina12',
|
||||||
'cce20': 'http://www.sat.gob.mx/ComercioExterior20',
|
'cce20': 'http://www.sat.gob.mx/ComercioExterior20',
|
||||||
}
|
}
|
||||||
|
@ -397,11 +399,23 @@ class CfdiToDict(object):
|
||||||
self.version = self._root.attrib['Version']
|
self.version = self._root.attrib['Version']
|
||||||
ns = f'cfdi{self.version}'
|
ns = f'cfdi{self.version}'
|
||||||
self.NS['cfdi'] = self.NS_VERSION[ns]
|
self.NS['cfdi'] = self.NS_VERSION[ns]
|
||||||
|
self._timbre_fiscal()
|
||||||
self._informacion_global()
|
self._informacion_global()
|
||||||
self._receptor()
|
self._receptor()
|
||||||
self._complementos()
|
self._complementos()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def _timbre_fiscal(self):
|
||||||
|
path = '//tfd:TimbreFiscalDigital'
|
||||||
|
data = self._root.xpath(path, namespaces=self.NS)
|
||||||
|
if not data:
|
||||||
|
return
|
||||||
|
|
||||||
|
data = data[0]
|
||||||
|
attr = CaseInsensitiveDict(data.attrib)
|
||||||
|
self._fecha_timbrado = attr['FechaTimbrado']
|
||||||
|
return
|
||||||
|
|
||||||
def _informacion_global(self):
|
def _informacion_global(self):
|
||||||
self._values['informacion_global'] = {}
|
self._values['informacion_global'] = {}
|
||||||
|
|
||||||
|
@ -514,10 +528,75 @@ class CfdiToDict(object):
|
||||||
|
|
||||||
self._values['carta_porte'] = values
|
self._values['carta_porte'] = values
|
||||||
|
|
||||||
|
self._complemento_carta_porte(complemento)
|
||||||
self._complemento_comercio_exterior(complemento)
|
self._complemento_comercio_exterior(complemento)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def _complemento_carta_porte(self, complemento):
|
||||||
|
path = '//cartaporte30:CartaPorte'
|
||||||
|
carta_porte = complemento.xpath(path, namespaces=self.NS)
|
||||||
|
if carta_porte:
|
||||||
|
self._get_carta_porte_3(carta_porte)
|
||||||
|
return
|
||||||
|
|
||||||
|
def _get_carta_porte_3(self, carta_porte):
|
||||||
|
URL = 'https://verificacfdi.facturaelectronica.sat.gob.mx/verificaccp/default.aspx'
|
||||||
|
PRE = '//cartaporte30'
|
||||||
|
values = CaseInsensitiveDict(carta_porte[0].attrib)
|
||||||
|
idccp = values['idccp']
|
||||||
|
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(node.attrib)
|
||||||
|
detalle = [CaseInsensitiveDict(n.attrib)
|
||||||
|
for n in node if 'Mercancia' in n.tag]
|
||||||
|
values['mercancias'] = {
|
||||||
|
'mercancias': mercancias,
|
||||||
|
'detalle': detalle,
|
||||||
|
}
|
||||||
|
|
||||||
|
path = f'{PRE}:Autotransporte'
|
||||||
|
node_auto = node.xpath(path, namespaces=self.NS)[0]
|
||||||
|
values_auto = CaseInsensitiveDict(node_auto.attrib)
|
||||||
|
values['autotransporte'] = values_auto
|
||||||
|
|
||||||
|
path = f'{PRE}:IdentificacionVehicular'
|
||||||
|
node_tmp = node_auto.xpath(path, namespaces=self.NS)[0]
|
||||||
|
values_auto = CaseInsensitiveDict(node_tmp.attrib)
|
||||||
|
values['autotransporte'].update(values_auto)
|
||||||
|
|
||||||
|
path = f'{PRE}:Seguros'
|
||||||
|
node_tmp = node_auto.xpath(path, namespaces=self.NS)[0]
|
||||||
|
values_auto = CaseInsensitiveDict(node_tmp.attrib)
|
||||||
|
values['autotransporte'].update(values_auto)
|
||||||
|
|
||||||
|
path = f'{PRE}:Remolques'
|
||||||
|
try:
|
||||||
|
node_tmp = node_auto.xpath(path, namespaces=self.NS)[0][0]
|
||||||
|
values_auto = CaseInsensitiveDict(node_tmp.attrib)
|
||||||
|
values['autotransporte'].update(values_auto)
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
elif 'Ubicaciones' in node.tag:
|
||||||
|
ubicaciones = []
|
||||||
|
for n in node:
|
||||||
|
ubicacion = CaseInsensitiveDict(n.attrib)
|
||||||
|
if ubicacion['TipoUbicacion'] == 'Origen':
|
||||||
|
fecha_origen = ubicacion['FechaHoraSalidaLlegada']
|
||||||
|
ubicacion['domicilio'] = self._set_carta_porte_domicilio(
|
||||||
|
CaseInsensitiveDict(n[0].attrib))
|
||||||
|
ubicaciones.append(ubicacion)
|
||||||
|
values['FechaOrigen'] = fecha_origen
|
||||||
|
values['ubicaciones'] = ubicaciones
|
||||||
|
qr_data = f'{URL}?IdCCP={idccp}&FechaOrig={fecha_origen}&FechaTimb={self._fecha_timbrado}'
|
||||||
|
values['qr'] = get_qr(qr_data, 'png')
|
||||||
|
self._values['carta_porte'] = values
|
||||||
|
return
|
||||||
|
|
||||||
def _complemento_comercio_exterior(self, complemento):
|
def _complemento_comercio_exterior(self, complemento):
|
||||||
path = '//cce20:ComercioExterior'
|
path = '//cce20:ComercioExterior'
|
||||||
comercio_exterior = complemento.xpath(path, namespaces=self.NS)
|
comercio_exterior = complemento.xpath(path, namespaces=self.NS)
|
||||||
|
|
|
@ -4823,16 +4823,6 @@ class Facturas(BaseModel):
|
||||||
obj = SATTipoRelacion.get(SATTipoRelacion.key==invoice.tipo_relacion)
|
obj = SATTipoRelacion.get(SATTipoRelacion.key==invoice.tipo_relacion)
|
||||||
values['tiporelacion'] = str(obj)
|
values['tiporelacion'] = str(obj)
|
||||||
|
|
||||||
# ~ use_packing = Configuracion.get_bool('chk_use_packing')
|
|
||||||
# ~ if use_packing:
|
|
||||||
# ~ w = FacturasDetalle.factura == invoice
|
|
||||||
# ~ q = (FacturasDetalle
|
|
||||||
# ~ .select(FacturasDetalle.empaques)
|
|
||||||
# ~ .where(w)
|
|
||||||
# ~ .order_by(FacturasDetalle.id.asc())
|
|
||||||
# ~ .tuples())
|
|
||||||
# ~ values['pakings'] = [str(int(r[0])) for r in q]
|
|
||||||
|
|
||||||
return values
|
return values
|
||||||
|
|
||||||
def _get_not_in_xml2(self, invoice, data):
|
def _get_not_in_xml2(self, invoice, data):
|
||||||
|
|
|
@ -882,68 +882,9 @@ function guardar_y_timbrar(values){
|
||||||
|
|
||||||
var usar_cartaporte = $$('chk_cfdi_usar_cartaporte').getValue()
|
var usar_cartaporte = $$('chk_cfdi_usar_cartaporte').getValue()
|
||||||
if(usar_cartaporte){
|
if(usar_cartaporte){
|
||||||
//~ var total_distance = 0.00
|
|
||||||
//~ var total_weight = 0.00
|
|
||||||
//~ var cartaporte = {
|
|
||||||
//~ TranspInternac: $$('lst_carta_TranspInternac').getValue(),
|
|
||||||
//~ TotalDistRec: total_distance,
|
|
||||||
//~ }
|
|
||||||
//~ var ubicaciones = $$('grid_carta_ubicaciones').data.getRange()
|
|
||||||
//~ ubicaciones.forEach(function(row, index){
|
|
||||||
//~ delete row['id']
|
|
||||||
//~ delete row['delete']
|
|
||||||
//~ if(row['DistanciaRecorrida']){
|
|
||||||
//~ total_distance += parseFloat(row['DistanciaRecorrida'])
|
|
||||||
//~ }
|
|
||||||
//~ })
|
|
||||||
//~ cartaporte['TotalDistRec'] = total_distance
|
|
||||||
//~ cartaporte['ubicaciones'] = ubicaciones
|
|
||||||
|
|
||||||
//~ var row = $$('grid_carta_autotransporte').data.getRange()[0]
|
|
||||||
//~ var autotransporte = {
|
|
||||||
//~ PermSCT: row['PermSCT'],
|
|
||||||
//~ NumPermisoSCT: row['NumPermisoSCT'],
|
|
||||||
//~ identificacion: {
|
|
||||||
//~ ConfigVehicular: row['ConfigVehicular'],
|
|
||||||
//~ PlacaVM: row['PlacaVM'],
|
|
||||||
//~ AnioModeloVM: row['AnioModeloVM'],
|
|
||||||
//~ },
|
|
||||||
//~ seguros: {
|
|
||||||
//~ AseguraRespCivil: row['AseguraRespCivil'],
|
|
||||||
//~ PolizaRespCivil: row['PolizaRespCivil'],
|
|
||||||
//~ },
|
|
||||||
//~ remolque: {
|
|
||||||
//~ SubTipoRem: row['SubTipoRem'],
|
|
||||||
//~ Placa: row['Placa'],
|
|
||||||
//~ }
|
|
||||||
//~ }
|
|
||||||
|
|
||||||
//~ var mercancias = $$('grid_carta_mercancias').data.getRange()
|
|
||||||
//~ mercancias.forEach(function(row, index){
|
|
||||||
//~ delete row['id']
|
|
||||||
//~ delete row['delete']
|
|
||||||
//~ row['Cantidad'] = String(row['Cantidad'])
|
|
||||||
//~ row['ValorMercancia'] = String(row['ValorMercancia'])
|
|
||||||
//~ if(row['PesoEnKg']){
|
|
||||||
//~ total_weight += parseFloat(row['PesoEnKg'])
|
|
||||||
//~ }
|
|
||||||
//~ })
|
|
||||||
//~ var mercancias = {
|
|
||||||
//~ 'PesoBrutoTotal': 0.00,
|
|
||||||
//~ 'UnidadPeso': $$('lst_carta_UnidadPeso').getValue(),
|
|
||||||
//~ 'NumTotalMercancias': String(mercancias.length),
|
|
||||||
//~ mercancias: mercancias,
|
|
||||||
//~ autotransporte: autotransporte,
|
|
||||||
//~ }
|
|
||||||
//~ cartaporte['mercancias'] = mercancias
|
|
||||||
|
|
||||||
//~ var tiposfigura = $$('grid_carta_tipos_figuras').data.getRange()
|
|
||||||
//~ tiposfigura.forEach(function(row, index){
|
|
||||||
//~ delete row['id']
|
|
||||||
//~ })
|
|
||||||
//~ cartaporte['tiposfigura'] = tiposfigura
|
|
||||||
var result = _get_values_carta_porte()
|
var result = _get_values_carta_porte()
|
||||||
data['cartaporte'] = result.values
|
data['cartaporte'] = result.values
|
||||||
|
$$('chk_cfdi_usar_cartaporte').setValue(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
var usar_comercioe = $$('chk_cfdi_usar_comercioe').getValue()
|
var usar_comercioe = $$('chk_cfdi_usar_comercioe').getValue()
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue