From 0c7abf634b3019746e82ef68c768622f749aee03 Mon Sep 17 00:00:00 2001 From: El Mau Date: Mon, 4 Mar 2024 14:07:10 -0600 Subject: [PATCH 1/4] Update changelog --- CHANGELOG.md | 6 + VERSION | 2 +- source/app/controllers/util.py | 2 + source/app/models/main.py | 1 - source/app/settings.py | 2 +- source/xslt/cadena.xslt | 2 +- source/xslt/cartaporte30.xslt | 744 +++++++++++++++++++++++++++++++++ 7 files changed, 755 insertions(+), 4 deletions(-) create mode 100644 source/xslt/cartaporte30.xslt diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a38f42..bdc244b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +v 2.3.0 [01-Feb-2024] + - Mejora: Soporte para complemento Carta Porte 3.0 + - **IMPORTANTE**: Aunque no lo uses, esto afecta al JS de facturación, por + lo que tienes que forzar el refresco (CTRL+F5) si tienes algún problema. + + v 2.2.0 [24-Ene-2024] - Mejora: Soporte para complemento Comercio Exterior 2.0 - **IMPORTANTE**: Aunque no lo uses, esto afecta al JS de facturación, por diff --git a/VERSION b/VERSION index ccbccc3..276cbf9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2.0 +2.3.0 diff --git a/source/app/controllers/util.py b/source/app/controllers/util.py index f1cfb29..2e1220c 100644 --- a/source/app/controllers/util.py +++ b/source/app/controllers/util.py @@ -1355,6 +1355,7 @@ class LIBO(object): except KeyError: msg = 'Hoja no existe' return (), msg + return cursor.getDataArray(), '' def products(self, path): @@ -1615,6 +1616,7 @@ class LIBO(object): return (), msg rows = tuple(data[1:]) + return rows, '' def _data_to_dict(self, rows): diff --git a/source/app/models/main.py b/source/app/models/main.py index ed75c0f..c9d8756 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -79,7 +79,6 @@ def conectar(opt): db = { 'sqlite': SqliteDatabase, 'postgres': PostgresqlDatabase, - 'mysql': MySQLDatabase, } db_type = opt.pop('type') db_name = opt.pop('name') diff --git a/source/app/settings.py b/source/app/settings.py index a2458d9..190833e 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -39,7 +39,7 @@ except ImportError: DEBUG = DEBUG -VERSION = '2.2.0' +VERSION = '2.3.0' EMAIL_SUPPORT = ('soporte@empresalibre.mx',) TITLE_APP = '{} v{}'.format(TITLE_APP, VERSION) diff --git a/source/xslt/cadena.xslt b/source/xslt/cadena.xslt index 218d9d2..119e79d 100644 --- a/source/xslt/cadena.xslt +++ b/source/xslt/cadena.xslt @@ -10,7 +10,7 @@ - + diff --git a/source/xslt/cartaporte30.xslt b/source/xslt/cartaporte30.xslt new file mode 100644 index 0000000..d5fe39b --- /dev/null +++ b/source/xslt/cartaporte30.xslt @@ -0,0 +1,744 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 13a3c106c61ccba68c717d2c2758d83d0c655cf3 Mon Sep 17 00:00:00 2001 From: El Mau Date: Sun, 31 Mar 2024 22:28:13 -0600 Subject: [PATCH 2/4] UI for Carta Porte v3 --- CHANGELOG.md | 2 +- source/app/controllers/cfdi_xml.py | 4 +- source/static/js/controller/invoices.js | 36 ++- source/static/js/ui/invoices.js | 288 +++++++++++++++++------- 4 files changed, 238 insertions(+), 92 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdc244b..bb62838 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -v 2.3.0 [01-Feb-2024] +v 2.3.0 [01-Abr-2024] - Mejora: Soporte para complemento Carta Porte 3.0 - **IMPORTANTE**: Aunque no lo uses, esto afecta al JS de facturación, por lo que tienes que forzar el refresco (CTRL+F5) si tienes algún problema. diff --git a/source/app/controllers/cfdi_xml.py b/source/app/controllers/cfdi_xml.py index ee3d961..a335be1 100644 --- a/source/app/controllers/cfdi_xml.py +++ b/source/app/controllers/cfdi_xml.py @@ -630,7 +630,9 @@ class CFDI(object): atributos.update(datos['ine']) node_ine = ET.SubElement(self._complemento, 'ine:INE', atributos) if ine_key_entidad: - attr = {'ClaveEntidad': ine_key_entidad, 'Ambito': ine_ambito} + attr = {'ClaveEntidad': ine_key_entidad} + if ine_ambito: + attr['Ambito'] = ine_ambito node_entidad = ET.SubElement(node_ine, 'ine:Entidad', attr) attr = {'IdContabilidad': ine_id_conta} ET.SubElement(node_entidad, 'ine:Contabilidad', attr) diff --git a/source/static/js/controller/invoices.js b/source/static/js/controller/invoices.js index 74aca5f..03b2c05 100644 --- a/source/static/js/controller/invoices.js +++ b/source/static/js/controller/invoices.js @@ -97,12 +97,16 @@ var invoices_controllers = { tv_invoice = $$('tv_invoice').getTabbar() tv_invoice.attachEvent('onChange', tv_invoice_change) - $$('grid_carta_mercancias').attachEvent('onItemClick', grid_carta_mercancias_click) - $$('grid_carta_ubicaciones').attachEvent('onBeforeEditStop', grid_carta_ubicaciones_before_edit_stop) - $$('cmd_carta_add_product').attachEvent('onItemClick', cmd_carta_add_product_click) - $$('cmd_carta_copy_from_invoice').attachEvent('onItemClick', cmd_carta_copy_from_invoice_click) + //~ CartaPorte + $$('grid_ccp_ubicaciones').attachEvent('onBeforeEditStop', grid_ccp_ubicaciones_before_edit_stop) + $$('grid_ccp_ubicaciones').attachEvent('onItemClick', grid_ccp_ubicaciones_click) + $$('cmd_ccp_agregar_ubicacion').attachEvent('onItemClick', cmd_ccp_agregar_ubicacion_click) + $$('grid_ccp_mercancias').attachEvent('onItemClick', grid_ccp_mercancias_click) + $$('cmd_ccp_add_product').attachEvent('onItemClick', cmd_ccp_add_product_click) + //~ $$('cmd_carta_copy_from_invoice').attachEvent('onItemClick', cmd_carta_copy_from_invoice_click) $$('cmd_carta_import_json').attachEvent('onItemClick', cmd_carta_import_json_click) + //~ ComercioExterior $$('cmd_import_json_comercioe').attachEvent('onItemClick', cmd_import_json_comercioe_click) $$('cmd_ce_import_ods').attachEvent('onItemClick', cmd_ce_import_ods_click) $$('cmd_ce_tipo_cambio').attachEvent('onItemClick', cmd_ce_tipo_cambio_click) @@ -1259,8 +1263,8 @@ function grid_details_before_edit_start(id){ } -function grid_carta_ubicaciones_before_edit_stop(state, editor){ - var g = $$('grid_carta_ubicaciones') +function grid_ccp_ubicaciones_before_edit_stop(state, editor){ + var g = $$('grid_ccp_ubicaciones') var row = g.getItem(editor.row) if(editor.column != 'CodigoPostal'){ @@ -2806,8 +2810,14 @@ function cmd_invoice_ask_cancel_click(){ } -function cmd_carta_add_product_click(){ - var g = $$('grid_carta_mercancias') +function cmd_ccp_agregar_ubicacion_click(){ + var g = $$('grid_ccp_ubicaciones') + g.add({delete: '-', Pais: 'MEX'}) +} + + +function cmd_ccp_add_product_click(){ + var g = $$('grid_ccp_mercancias') g.add({delete: '-'}) } @@ -2855,7 +2865,15 @@ function cmd_carta_copy_from_invoice_click(){ } -function grid_carta_mercancias_click(id, e, node){ +function grid_ccp_ubicaciones_click(id, e, node){ + if(id.column != 'delete'){ + return + } + this.remove(id.row) +} + + +function grid_ccp_mercancias_click(id, e, node){ if(id.column != 'delete'){ return } diff --git a/source/static/js/ui/invoices.js b/source/static/js/ui/invoices.js index 790d277..70834d4 100644 --- a/source/static/js/ui/invoices.js +++ b/source/static/js/ui/invoices.js @@ -845,20 +845,66 @@ var controls_leyendas_fiscales = [ ] -var opt_transporte_internacional = [ +var opt_ccp_transporte_internacional = [ {id: 'Sí', value: 'Sí'}, {id: 'No', value: 'No'}, ] -var opt_entrada_salida = [ +var opt_ccp_regimen_aduanero = [ + {id: '', value: ''}, + {id: 'IMD', value: '[IMD] Definitivo de importación.'}, + {id: 'EXD', value: '[EXD] Definitivo de exportación.'}, + {id: 'ITR', value: '[ITR] Temporales de importación para retomar al extranjero en el mismo estado.'}, + {id: 'ITE', value: '[ITE] Temporales de importación para elaboración, transformación o reparación para empresas con programa IMMEX.'}, + {id: 'ETR', value: '[ETR] Temporales de exportación para retornar al país en el mismo estado.'}, + {id: 'ETE', value: '[ETE] Temporales de exportación para elaboración, transformación o reparación.'}, + {id: 'DFI', value: '[DFI] Depósito Fiscal.'}, + {id: 'RFE', value: '[RFE] Elaboración, transformación o reparación en recinto fiscalizado.'}, + {id: 'RFS', value: '[RFS] Recinto fiscalizado estratégico.'}, + {id: 'TRA', value: '[TRA] Tránsitos.'}, +] + + +var opt_ccp_entrada_salida = [ {id: '', value: ''}, {id: 'Entrada', value: 'Entrada'}, {id: 'Salida', value: 'Salida'}, ] -var opt_origen_destino = [ +var opt_ccp_pais_origen = [ + {id: '', value: ''}, +] + + +var opt_ccp_via_entrada = [ + {id: '', value: ''}, + {id: '01', value: '[01] Autotransporte'}, + {id: '02', value: '[02] Marítimo'}, + {id: '03', value: '[03] Aéreo'}, + {id: '04', value: '[04] Ferroviario'}, +] + + +var opt_ccp_ubicacion_polo = [ + {id: '', value: ''}, + {id: '01', value: '[01] Coatzacoalcos I'}, + {id: '02', value: '[02] Coatzacoalcos II'}, + {id: '03', value: '[03] Texistepec'}, + {id: '04', value: '[04] San Juan Evangelista'}, + {id: '05', value: '[05] Salina Cruz'}, + {id: '06', value: '[06] San Blas Atempa'}, +] + + +var opt_ccp_registro_istmo = [ + {id: '', value: ''}, + {id: 'Si', value: 'Sí'}, +] + + +var opt_ccp_origen_destino = [ {id: 'Origen', value: 'Origen'}, {id: 'Destino', value: 'Destino'}, ] @@ -873,12 +919,12 @@ var date_suggest = { } -var opt_countries = [ +var opt_ccp_countries = [ {id: 'MEX', value: 'México'}, ] -var opt_carta_estados = [ +var opt_ccp_carta_estados = [ {id: 'AGU', value: 'Aguascalientes'}, {id: 'BCN', value: 'Baja California'}, {id: 'BCS', value: 'Baja California Sur'}, @@ -915,18 +961,25 @@ var opt_carta_estados = [ ] -var grid_cols_carta_ubicaciones = [ +var grid_cols_ccp_ubicaciones = [ {id: 'id', header: 'ID', hidden: true}, - {id: 'delete', header: '', hidden: true, width: 30, css: 'delete'}, - {id: 'TipoUbicacion', header: 'Tipo de Ubicación', editor: 'select', options: opt_origen_destino, fillspace: 1}, + {id: 'delete', header: '', width: 30, css: 'delete'}, + {id: 'TipoUbicacion', header: 'TipoUbicacion', editor: 'select', options: opt_ccp_origen_destino, fillspace: 1}, + {id: 'IDUbicacion', header: 'IDUbicacion', hidden: true, editor: 'text', fillspace: 1}, {id: 'RFCRemitenteDestinatario', header: 'RFC Rem/Des', editor: 'text', fillspace: 1}, {id: 'NombreRemitenteDestinatario', header: 'Nombre Rem/Des', editor: 'text', fillspace: 1}, + {id: 'NumRegIdTrib', header: 'NumRegIdTrib', hidden: true, editor: 'text', fillspace: 1}, + {id: 'ResidenciaFiscal', header: 'ResidenciaFiscal', hidden: true, editor: 'text', fillspace: 1}, + {id: 'NumEstacion', header: 'NumEstacion', hidden: true, editor: 'text', fillspace: 1}, + {id: 'NombreEstacion', header: 'NombreEstacion', hidden: true, editor: 'text', fillspace: 1}, + {id: 'NavegacionTrafico', header: 'NavegacionTrafico', hidden: true, editor: 'text', fillspace: 1}, {id: 'FechaHoraSalidaLlegada', header: 'Fecha/Hora', editor: 'date', suggest: date_suggest, format: webix.Date.dateToStr("%D, %d-%M-%Y %h:%i"), footer: 'Total distancia:', fillspace: 1}, + {id: 'TipoEstacion', header: 'TipoEstacion', hidden: true, editor: 'text', fillspace: 1}, {id: 'DistanciaRecorrida', header: 'Distancia (KM)', editor: 'text', format: webix.i18n.numberFormat, css: 'right', footer: {content: 'summColumn', css: 'right'}, fillspace: 1}, - {id: 'Municipio', headerd: 'Municipio', editor: 'text', fillspace: 1}, - {id: 'Estado', headerd: 'Estado', editor: 'select', options: opt_carta_estados, fillspace: 1}, - {id: 'Pais', headerd: 'Pais', editor: 'select', options: opt_countries, fillspace: 1}, - {id: 'CodigoPostal', headerd: 'C.P.', editor: 'text', fillspace: 1}, + {id: 'Municipio', header: 'Municipio', editor: 'text', fillspace: 1}, + {id: 'Estado', header: 'Estado', editor: 'select', options: opt_ccp_carta_estados, fillspace: 1}, + {id: 'Pais', header: 'País', editor: 'select', options: opt_ccp_countries, fillspace: 1}, + {id: 'CodigoPostal', header: 'C.P.', editor: 'text', fillspace: 1}, ] //~ Calle //~ NumeroExterior @@ -936,19 +989,29 @@ var grid_cols_carta_ubicaciones = [ //~ Referencia -var grid_cols_carta_mercancias = [ +var grid_cols_ccp_mercancias = [ {id: 'id', header: 'ID', hidden: true}, {id: 'delete', header: '', width: 30, css: 'delete'}, {id: 'BienesTransp', header: 'Clave SAT', editor: 'text', fillspace: 1}, + //~ {id: 'ClaveSTCC', header: 'ClaveSTCC', editor: 'text', fillspace: 1}, {id: 'Descripcion', header: 'Descripción', editor: 'text', fillspace: 1}, {id: 'Cantidad', header: 'Cantidad', editor: 'text', format: webix.i18n.numberFormat, css: 'right', fillspace: 1}, {id: 'ClaveUnidad', header: 'Unidad', editor: 'select', options: 'values/unitbykey', footer: 'Total peso:', fillspace: 1}, - //~ {id: 'ValorMercancia', header: 'Valor Mercancia', format: webix.i18n.priceFormat, css: 'right', footer: 'Total peso:', fillspace: 1}, + //~ {id: 'Unidad', header: 'Unidad', editor: 'text', fillspace: 1}, + //~ {id: 'Dimensiones', header: 'Dimensiones', editor: 'text', fillspace: 1}, + //~ {id: 'MaterialPeligroso', header: 'MaterialPeligroso', editor: 'text', fillspace: 1}, + //~ {id: 'CveMaterialPeligroso', header: 'CveMaterialPeligroso', editor: 'text', fillspace: 1}, + //~ {id: 'Embalaje', header: 'Embalaje', editor: 'text', fillspace: 1}, + //~ {id: 'DescripEmbalaje', header: 'DescripEmbalaje', editor: 'text', fillspace: 1}, + //~ {id: 'SectorCOFEPRIS', header: 'SectorCOFEPRIS', editor: 'text', fillspace: 1}, {id: 'PesoEnKg', header: 'Peso (Kg)', format: webix.i18n.numberFormat, css: 'right', editor: 'text', footer: {content: 'summColumn', css: 'right'}, fillspace: 1}, + //~ {id: 'ValorMercancia', header: 'Valor Mercancia', format: webix.i18n.priceFormat, css: 'right', footer: 'Total peso:', fillspace: 1}, + //~ {id: 'Moneda', header: 'Moneda', editor: 'text', fillspace: 1}, + //~ {id: 'FraccionArancelaria', header: 'FraccionArancelaria', editor: 'text', fillspace: 1}, ] -var opt_carta_tipo_permiso_sct = [ +var opt_ccp_tipo_permiso_sct = [ {id: 'TPAF01', value: '[TPAF01] Autotransporte Federal de carga general.'}, {id: 'TPAF02', value: '[TPAF02] Transporte privado de carga.'}, {id: 'TPAF03', value: '[TPAF03] Autotransporte Federal de Carga Especializada de materiales y residuos peligrosos.'}, @@ -978,7 +1041,7 @@ var opt_carta_tipo_permiso_sct = [ ] -var opt_config_auto = [ +var opt_ccp_config_auto = [ {id: '', value: ''}, {id: 'VL', value: '[VL] Vehículo ligero de carga (2 llantas en el eje delantero y 2 llantas en el eje trasero)'}, {id: 'C2', value: '[C2] Camión Unitario (2 llantas en el eje delantero y 4 llantas en el eje trasero)'}, @@ -1017,7 +1080,7 @@ var opt_config_auto = [ ] -var opt_carta_tipo_remolque = [ +var opt_ccp_tipo_remolque = [ {id: '', value: ''}, {id: 'CTR001', value: '[CTR001] Caballete'}, {id: 'CTR002', value: '[CTR002] Caja'}, @@ -1053,27 +1116,41 @@ var opt_carta_tipo_remolque = [ ] -var opt_carta_aseguradoras = [ - {id: 'General de Seguros', value: 'General de Seguros'}, - {id: 'Qualitas', value: 'Qualitas'}, -] +//~ var opt_carta_aseguradoras = [ + //~ {id: 'General de Seguros', value: 'General de Seguros'}, + //~ {id: 'Qualitas', value: 'Qualitas'}, +//~ ] -var grid_cols_carta_autotransporte = [ +var grid_cols_ccp_autotransporte = [ {id: 'id', header: 'ID', hidden: true}, - {id: 'PermSCT', header: 'Tipo Permiso SCT', editor: 'select', options: opt_carta_tipo_permiso_sct, fillspace: 1}, - {id: 'NumPermisoSCT', header: 'Número Permiso SCT', editor: 'text', fillspace: 1}, - {id: 'ConfigVehicular', header: 'Clave Autotransporte', editor: 'select', options: opt_config_auto, fillspace: 1}, + {id: 'PermSCT', header: 'PermSCT', editor: 'select', options: opt_ccp_tipo_permiso_sct, fillspace: 1}, + {id: 'NumPermisoSCT', header: 'NumPermisoSCT', editor: 'text', fillspace: 1}, + {id: 'ConfigVehicular', header: 'ConfigVehicular', editor: 'select', options: opt_ccp_config_auto, fillspace: 1}, + {id: 'PesoBrutoVehicular', header: 'PesoBrutoVehicular', editor: 'text', format: webix.i18n.numberFormat, css: 'right', fillspace: 1}, {id: 'PlacaVM', header: 'Placa', editor: 'text', fillspace: 1}, {id: 'AnioModeloVM', header: 'Modelo (Año)', editor: 'text', fillspace: 1}, - {id: 'SubTipoRem', header: 'ST Remolque', editor: 'select', options: opt_carta_tipo_remolque, fillspace: 1}, + //~ {id: 'SubTipoRem', header: 'ST Remolque', editor: 'select', options: opt_ccp_tipo_remolque, fillspace: 1}, + //~ {id: 'Placa', header: 'Placa', editor: 'text', fillspace: 1}, +] +var grid_cols_ccp_remolques = [ + {id: 'id', header: 'ID', hidden: true}, + {id: 'SubTipoRem', header: 'SubTipo Remolque', editor: 'select', options: opt_ccp_tipo_remolque, fillspace: 1}, {id: 'Placa', header: 'Placa', editor: 'text', fillspace: 1}, +] +var grid_cols_ccp_seguros = [ + {id: 'id', header: 'ID', hidden: true}, {id: 'AseguraRespCivil', header: 'Aseguradora', editor: 'text', fillspace: 1}, {id: 'PolizaRespCivil', header: 'Póliza', editor: 'text', fillspace: 1}, + //~ {id: 'AseguraMedAmbiente', header: 'AseguraMedAmbiente', editor: 'text', fillspace: 1}, + //~ {id: 'PolizaMedAmbiente', header: 'PolizaMedAmbiente', editor: 'text', fillspace: 1}, + //~ {id: 'AseguraCarga', header: 'AseguraCarga', editor: 'text', fillspace: 1}, + //~ {id: 'PolizaCarga', header: 'PolizaCarga', editor: 'text', fillspace: 1}, + //~ {id: 'PrimaSeguro', header: 'PrimaSeguro', editor: 'text', format: webix.i18n.numberFormat, css: 'right', fillspace: 1}, ] -var opt_tipos_figura = [ +var opt_ccp_tipos_figura = [ {id: '', value: ''}, {id: '01', value: '[01] Operador'}, {id: '02', value: '[02] Propietario'}, @@ -1082,101 +1159,163 @@ var opt_tipos_figura = [ ] -var grid_cols_carta_tipos_figuras = [ +var grid_cols_ccp_tipos_figuras = [ {id: 'id', header: 'ID', hidden: true}, - {id: 'TipoFigura', header: 'Tipo Figura', editor: 'select', options: opt_tipos_figura, fillspace: 1}, - {id: 'RFCFigura', header: 'RFC Figura', editor: 'text', fillspace: 1}, - {id: 'NombreFigura', header: 'Nombre Figura', editor: 'text', fillspace: 1}, - {id: 'NumLicencia', header: 'Número de Licencia', editor: 'text', fillspace: 1}, + {id: 'TipoFigura', header: 'TipoFigura', editor: 'select', options: opt_ccp_tipos_figura, fillspace: 1}, + {id: 'RFCFigura', header: 'RFCFigura', editor: 'text', fillspace: 1}, + {id: 'NumLicencia', header: 'NumLicencia', editor: 'text', fillspace: 1}, + {id: 'NombreFigura', header: 'NombreFigura', editor: 'text', fillspace: 1}, + //~ {id: 'NumRegIdTribFigura', header: 'NumRegIdTribFigura', editor: 'text', fillspace: 1}, + //~ {id: 'ResidenciaFiscalFigura', header: 'ResidenciaFiscalFigura', editor: 'text', fillspace: 1}, + {id: 'Municipio', header: 'Municipio', editor: 'text', fillspace: 1}, + {id: 'Estado', header: 'Estado', editor: 'select', options: opt_ccp_carta_estados, fillspace: 1}, + {id: 'Pais', header: 'País', editor: 'select', options: opt_ccp_countries, fillspace: 1}, + {id: 'CodigoPostal', header: 'C.P.', editor: 'text', fillspace: 1}, ] -var grid_carta_ubicaciones = { +var grid_ccp_ubicaciones = { view: 'datatable', - id: 'grid_carta_ubicaciones', + id: 'grid_ccp_ubicaciones', multiselect: false, adjust: true, autoheight: true, headermenu: true, editable: true, footer: true, - columns: grid_cols_carta_ubicaciones, - //~ data: data_tmp1, - data: [ - {delete: '-', TipoUbicacion: 'Origen', Pais: 'MEX'}, - {delete: '-', TipoUbicacion: 'Destino', Pais: 'MEX'}, - ] + columns: grid_cols_ccp_ubicaciones, } -var grid_carta_mercancias = { +var grid_ccp_mercancias = { view: 'datatable', - id: 'grid_carta_mercancias', + id: 'grid_ccp_mercancias', multiselect: false, adjust: true, autoheight: true, headermenu: true, editable: true, footer: true, - columns: grid_cols_carta_mercancias, + columns: grid_cols_ccp_mercancias, } -var grid_carta_autotransporte = { +var grid_ccp_autotransporte = { view: 'datatable', - id: 'grid_carta_autotransporte', + id: 'grid_ccp_autotransporte', multiselect: false, adjust: true, autoheight: true, headermenu: true, editable: true, - columns: grid_cols_carta_autotransporte, + columns: grid_cols_ccp_autotransporte, data: [{id: 0}], - //~ data: data_tmp2, } - - -var grid_carta_tipos_figuras = { +var grid_ccp_remolques = { view: 'datatable', - id: 'grid_carta_tipos_figuras', + id: 'grid_ccp_remolques', multiselect: false, adjust: true, autoheight: true, headermenu: true, editable: true, - columns: grid_cols_carta_tipos_figuras, + columns: grid_cols_ccp_remolques, + data: [{id: 0}, {id: 1}], +} +var grid_ccp_seguros = { + view: 'datatable', + id: 'grid_ccp_seguros', + multiselect: false, + adjust: true, + autoheight: true, + headermenu: true, + editable: true, + columns: grid_cols_ccp_seguros, data: [{id: 0}], - //~ data: data_tmp3, } -var body_carta_mercancias = {rows:[ +var grid_ccp_tipos_figuras = { + view: 'datatable', + id: 'grid_ccp_tipos_figuras', + multiselect: false, + adjust: true, + autoheight: true, + headermenu: true, + editable: true, + columns: grid_cols_ccp_tipos_figuras, + data: [{id: 0}], +} + + +var body_ccp_ubicaciones = {rows:[ {cols: [ - {view: 'button', id: 'cmd_carta_add_product', label: 'Agregar Mercancía', icon: 'plus', + {view: 'button', id: 'cmd_ccp_agregar_ubicacion', label: 'Agregar Ubicación', icon: 'plus', type: 'iconButton', autowidth: true, align: 'center'}, - {view: 'button', id: 'cmd_carta_copy_from_invoice', label: 'Copiar de CFDI', icon: 'copy', + {}]}, + {maxHeight: 10}, + grid_ccp_ubicaciones, +]} + + +var body_ccp_mercancias = {rows:[ + {cols: [ + {view: 'button', id: 'cmd_ccp_add_product', label: 'Agregar Mercancía', icon: 'plus', type: 'iconButton', autowidth: true, align: 'center'}, + //~ {view: 'button', id: 'cmd_carta_copy_from_invoice', label: 'Copiar de CFDI', icon: 'copy', + //~ type: 'iconButton', autowidth: true, align: 'center'}, {}, {view: 'richselect', id: 'lst_carta_UnidadPeso', label: 'Unidad de Peso: ', labelWidth: 110, maxWidth: 300, options: '/satunidadespeso?opt=active'} ]}, {maxHeight: 10}, - grid_carta_mercancias, + grid_ccp_mercancias, ]} -var body_carta_ubicaciones = {rows:[ - grid_carta_ubicaciones, +var body_ccp_autotransporte = {rows:[ + grid_ccp_autotransporte, + {maxHeight: 10}, + grid_ccp_remolques, + {maxHeight: 10}, + grid_ccp_seguros, ]} -var body_carta_autotransporte = {rows:[ - grid_carta_autotransporte, +var body_ccp_tipos_figuras = {rows:[ + grid_ccp_tipos_figuras, ]} -var body_carta_tipos_figuras = {rows:[ - grid_carta_tipos_figuras, +var body_cp_datos_generales = {rows:[ + {cols: [{maxWidth: 15}, + {view: 'richselect', id: 'lst_cp_TranspInternac', labelPosition: 'top', + label: 'TranspInternac', options: opt_ccp_transporte_internacional, + value: 'No', readonly: true}, + {view: 'richselect', id: 'lst_cp_RegimenAduanero', labelPosition: 'top', + label: 'RegimenAduanero', options: opt_ccp_regimen_aduanero, + value: '', disabled: true}, + {view: 'richselect', id: 'lst_cp_EntradaSalidaMerc', labelPosition: 'top', + label: 'EntradaSalidaMerc', options: opt_ccp_entrada_salida, + value: '', disabled: true}, + {view: 'richselect', id: 'lst_cp_PaisOrigenDestino', labelPosition: 'top', + label: 'PaisOrigenDestino', options: opt_ccp_pais_origen, + value: '', disabled: true}, + {view: 'richselect', id: 'lst_cp_ViaEntradaSalida', labelPosition: 'top', + label: 'ViaEntradaSalida', options: opt_ccp_via_entrada, + value: '', disabled: true}, + ]}, + {cols: [{maxWidth: 15}, + {view: 'richselect', id: 'lst_cp_RegistroISTMO', labelPosition: 'top', + label: 'RegistroISTMO', options: opt_ccp_registro_istmo, + value: '', readonly: false}, + {view: 'richselect', id: 'lst_cp_UbicacionPoloOrigen', labelPosition: 'top', + label: 'UbicacionPoloOrigen', options: opt_ccp_ubicacion_polo, + value: '', disabled: true}, + {view: 'richselect', id: 'lst_cp_UbicacionPoloDestino', labelPosition: 'top', + label: 'UbicacionPoloDestino', options: opt_ccp_ubicacion_polo, + value: '', disabled: true}, + {}]}, ]} @@ -1189,24 +1328,11 @@ var controls_carta_porte = [ {view: 'button', id: 'cmd_carta_import_ods', label: 'Importar ODS', icon: 'upload', type: 'iconButton', autowidth: true, align: 'center'}, {maxWidth: 15}]}, - {view: 'fieldset', label: 'Mercancias', body: body_carta_mercancias}, - {cols: [{maxWidth: 15}, - {view: 'richselect', id: 'lst_carta_TranspInternac', labelPosition: 'top', - label: 'Transporte Internacional', options: opt_transporte_internacional, - value: 'No', readonly: true}, - {view: 'richselect', id: 'lst_carta_EntradaSalidaMerc', labelPosition: 'top', - label: 'Entrada o Salida', options: opt_entrada_salida, - value: '', disabled: true}, - {view: 'richselect', id: 'lst_carta_PaisOrigenDestino', labelPosition: 'top', - label: 'País Origen/Destino', options: [], - value: '', disabled: true}, - {view: 'richselect', id: 'lst_carta_ViaEntradaSalida', labelPosition: 'top', - label: 'Vía de Entrada o Salida', options: [], - value: '', disabled: true}, - ]}, - {view: 'fieldset', label: 'Ubicaciones', body: body_carta_ubicaciones}, - {view: 'fieldset', label: 'Autotransporte', body: body_carta_autotransporte}, - {view: 'fieldset', label: 'Tipos Figura', body: body_carta_tipos_figuras}, + {view: 'fieldset', label: 'Datos generales', body: body_cp_datos_generales}, + {view: 'fieldset', label: 'Ubicaciones', body: body_ccp_ubicaciones}, + {view: 'fieldset', label: 'Mercancias', body: body_ccp_mercancias}, + {view: 'fieldset', label: 'Autotransporte', body: body_ccp_autotransporte}, + {view: 'fieldset', label: 'Tipos Figura', body: body_ccp_tipos_figuras}, ] From 7f129b84b2aca43d9ea837ae24ebf5bf940e3bf6 Mon Sep 17 00:00:00 2001 From: El Mau Date: Mon, 1 Apr 2024 14:09:57 -0600 Subject: [PATCH 3/4] Stamp Carta Porte v3 --- source/app/controllers/cfdi_xml.py | 25 +- source/app/controllers/util.py | 5 + source/app/models/main.py | 34 ++- source/static/js/controller/invoices.js | 308 ++++++++++++++++-------- source/static/js/ui/admin.js | 1 + source/static/js/ui/invoices.js | 33 +-- 6 files changed, 279 insertions(+), 127 deletions(-) diff --git a/source/app/controllers/cfdi_xml.py b/source/app/controllers/cfdi_xml.py index a335be1..90abbce 100644 --- a/source/app/controllers/cfdi_xml.py +++ b/source/app/controllers/cfdi_xml.py @@ -111,10 +111,10 @@ SAT = { 'schema': ' http://www.sat.gob.mx/leyendasFiscales http://www.sat.gob.mx/sitio_internet/cfd/leyendasFiscales/leyendasFisc.xsd', }, 'cartaporte': { - 'version': '2.0', - 'prefix': 'cartaporte20', - 'xmlns': 'http://www.sat.gob.mx/CartaPorte20', - 'schema': ' http://www.sat.gob.mx/CartaPorte20 http://www.sat.gob.mx/sitio_internet/cfd/CartaPorte/CartaPorte20.xsd', + 'version': '3.0', + 'prefix': 'cartaporte30', + 'xmlns': 'http://www.sat.gob.mx/CartaPorte30', + 'schema': ' http://www.sat.gob.mx/CartaPorte30 http://www.sat.gob.mx/sitio_internet/cfd/CartaPorte/CartaPorte30.xsd', }, 'comercioe': { 'version': '2.0', @@ -575,6 +575,11 @@ class CFDI(object): mercancias = datos.pop('mercancias', ()) tiposfigura = datos.pop('tiposfigura', ()) + autotransporte = datos.pop('autotransporte', {}) + identificacion = autotransporte.pop('identificacion') + seguros = autotransporte.pop('seguros') + remolques = autotransporte.pop('remolques') + atributos = {'Version': SAT['cartaporte']['version']} atributos.update(datos) @@ -592,10 +597,6 @@ class CFDI(object): attr = mercancias mercancias = attr.pop('mercancias') - autotransporte = attr.pop('autotransporte') - identificacion = autotransporte.pop('identificacion') - seguros = autotransporte.pop('seguros') - remolque = autotransporte.pop('remolque') node = ET.SubElement(node_carta, f'{prefix}:Mercancias', attr) for mercancia in mercancias: @@ -604,10 +605,10 @@ class CFDI(object): sub_node = ET.SubElement(node, f'{prefix}:Autotransporte', autotransporte) ET.SubElement(sub_node, f'{prefix}:IdentificacionVehicular', identificacion) ET.SubElement(sub_node, f'{prefix}:Seguros', seguros) - if 'SubTipoRem' in remolque and 'Placa' in remolque \ - and remolque['SubTipoRem'] and remolque['Placa']: - tmp = ET.SubElement(sub_node, f'{prefix}:Remolques') - ET.SubElement(tmp, f'{prefix}:Remolque', remolque) + if remolques: + node_remolques = ET.SubElement(sub_node, f'{prefix}:Remolques') + for remolque in remolques: + ET.SubElement(node_remolques, f'{prefix}:Remolque', remolque) if tiposfigura: sub_node = ET.SubElement(node_carta, f'{prefix}:FiguraTransporte') diff --git a/source/app/controllers/util.py b/source/app/controllers/util.py index 2e1220c..b1e8d46 100644 --- a/source/app/controllers/util.py +++ b/source/app/controllers/util.py @@ -2422,6 +2422,7 @@ def upload_file(rfc, opt, file_obj): '_4.0_cn_1.2.ods', '_4.0_cp_2.0.ods', '_4.0_ccp_2.0.ods', + '_4.0_ccp_3.0.ods', '_4.0_cd_1.1.ods', '_4.0_cce_2.0.ods', '_4.0.json', @@ -3144,4 +3145,8 @@ def parse_xml2(xml_str): return etree.fromstring(xml_str.encode('utf-8')) +def get_idccp(): + uuid_v4 = uuid.uuid4() + 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 diff --git a/source/app/models/main.py b/source/app/models/main.py index c9d8756..4551753 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -5575,16 +5575,37 @@ class Facturas(BaseModel): if not valores: return + info = {} values = utils.loads(valores) + info['IdCCP'] = util.get_idccp() + info['TranspInternac'] = values['TranspInternac'] + autotransporte = { + 'PermSCT': values['autotransporte'].pop('PermSCT'), + 'NumPermisoSCT': values['autotransporte'].pop('NumPermisoSCT'), + } + identificacion = values['autotransporte'] + if 'PesoBrutoVehicular' in identificacion \ + and isinstance(identificacion['PesoBrutoVehicular'], float): + identificacion['PesoBrutoVehicular'] = f"{identificacion['PesoBrutoVehicular']:.2f}" + info['autotransporte'] = autotransporte + info['autotransporte']['identificacion'] = identificacion + info['autotransporte']['seguros'] = values['seguros'] + info['autotransporte']['remolques'] = values['remolques'] total_distance = 0.00 total_weight = 0.00 mercancias = values['mercancias'] - for mercancia in mercancias['mercancias']: + for mercancia in mercancias: total_weight += float(mercancia['PesoEnKg']) if isinstance(mercancia['PesoEnKg'], (int, float)): mercancia['PesoEnKg'] = f"{mercancia['PesoEnKg']:.2f}" - mercancias['PesoBrutoTotal'] = f"{total_weight:.2f}" + mercancia['Cantidad'] = f"{mercancia['Cantidad']:.2f}" + + info['mercancias'] = {} + info['mercancias']['UnidadPeso'] = values['unidad_peso'] + info['mercancias']['PesoBrutoTotal'] = f"{total_weight:.2f}" + info['mercancias']['NumTotalMercancias'] = f"{len(mercancias):,}" + info['mercancias']['mercancias'] = mercancias ubicaciones = values['ubicaciones'] for ubicacion in ubicaciones: @@ -5608,12 +5629,15 @@ class Facturas(BaseModel): 'CodigoPostal': cp, } - values['TotalDistRec'] = f"{total_distance:.2f}" - # ~ print(2, values) + info['TotalDistRec'] = f"{total_distance:.2f}" + info['ubicaciones'] = ubicaciones + info['tiposfigura'] = values['tiposfigura'] + + # ~ print(2, info) data = { 'factura': invoice, 'nombre': 'cartaporte', - 'valores': utils.dumps(values), + 'valores': utils.dumps(info), } FacturasComplementos.create(**data) return diff --git a/source/static/js/controller/invoices.js b/source/static/js/controller/invoices.js index 03b2c05..125fb21 100644 --- a/source/static/js/controller/invoices.js +++ b/source/static/js/controller/invoices.js @@ -100,9 +100,11 @@ var invoices_controllers = { //~ CartaPorte $$('grid_ccp_ubicaciones').attachEvent('onBeforeEditStop', grid_ccp_ubicaciones_before_edit_stop) $$('grid_ccp_ubicaciones').attachEvent('onItemClick', grid_ccp_ubicaciones_click) - $$('cmd_ccp_agregar_ubicacion').attachEvent('onItemClick', cmd_ccp_agregar_ubicacion_click) $$('grid_ccp_mercancias').attachEvent('onItemClick', grid_ccp_mercancias_click) + $$('grid_ccp_remolques').attachEvent('onItemClick', grid_ccp_remolques_click) + $$('cmd_ccp_agregar_ubicacion').attachEvent('onItemClick', cmd_ccp_agregar_ubicacion_click) $$('cmd_ccp_add_product').attachEvent('onItemClick', cmd_ccp_add_product_click) + $$('cmd_ccp_agregar_remolque').attachEvent('onItemClick', cmd_ccp_agregar_remolque_click) //~ $$('cmd_carta_copy_from_invoice').attachEvent('onItemClick', cmd_carta_copy_from_invoice_click) $$('cmd_carta_import_json').attachEvent('onItemClick', cmd_carta_import_json_click) @@ -401,16 +403,6 @@ function validate_invoice(values){ return false } - var usar_cartaporte = $$('chk_cfdi_usar_cartaporte').getValue() - if(usar_cartaporte){ - value = $$('lst_carta_UnidadPeso').getValue() - if(!value){ - msg = 'Es necesario seleccionar una Unidad de Peso' - msg_error(msg) - return false - } - } - var tipo_comprobante = $$('lst_tipo_comprobante').getValue() if(tipo_comprobante != 'T'){ if(values.id_partner == 0){ @@ -593,10 +585,99 @@ function validate_invoice(values){ var values = _get_values_comercio_exterior() } + //~ validate carta porte + var usar_cartaporte = $$('chk_cfdi_usar_cartaporte').getValue() + if(usar_cartaporte){ + var result = _get_values_carta_porte() + if(!result.ok){ + return false + } + } + return true } +function _get_values_carta_porte(){ + var ok = false + var values = new Object() + + unidad_peso = $$('lst_carta_UnidadPeso').getValue() + if(!unidad_peso){ + msg = 'Es necesario seleccionar una Unidad de Peso' + msg_error(msg) + return {ok: ok, values: values} + } + + var ubicaciones = $$('grid_ccp_ubicaciones').data.getRange() + if (ubicaciones.length < 2){ + msg = 'Se requieren al menos dos ubicaciones' + msg_error(msg) + return {ok: ok, values: values} + } + ubicaciones.forEach(function(row, index){ + delete row['id'] + delete row['delete'] + //~ delete row['IDUbicacion'] + }) + + var mercancias = $$('grid_ccp_mercancias').data.getRange() + if (mercancias.length < 1){ + msg = 'Se requieren al menos una mercancía' + msg_error(msg) + return {ok: ok, values: values} + } + mercancias.forEach(function(row, index){ + delete row['id'] + delete row['delete'] + }) + + var autotransporte = $$('grid_ccp_autotransporte').data.getRange()[0] + delete autotransporte['id'] + if(autotransporte['PermSCT'] === undefined){ + msg = 'El campo PermSCT es requerido' + msg_error(msg) + return {ok: ok, values: values} + } + + var remolques = $$('grid_ccp_remolques').data.getRange() + remolques.forEach(function(row, index){ + delete row['id'] + }) + + var seguros = $$('grid_ccp_seguros').data.getRange()[0] + delete seguros['id'] + if(seguros['AseguraRespCivil'] === undefined){ + msg = 'El campo AseguraRespCivil es requerido' + msg_error(msg) + return {ok: ok, values: values} + } + if(seguros['PolizaRespCivil'] === undefined){ + msg = 'El campo PolizaRespCivil es requerido' + msg_error(msg) + return {ok: ok, values: values} + } + + var tipos_figuras = $$('grid_ccp_tipos_figuras').data.getRange() + tipos_figuras.forEach(function(row, index){ + delete row['id'] + }) + + values['TranspInternac'] = $$('lst_cp_TranspInternac').getValue() + values['unidad_peso'] = unidad_peso + values['ubicaciones'] = ubicaciones + values['mercancias'] = mercancias + values['autotransporte'] = autotransporte + values['remolques'] = remolques + values['seguros'] = seguros + values['tiposfigura'] = tipos_figuras + + ok = true + + return {ok: ok, values: values} +} + + function update_grid_invoices(values){ if(values.new){ gi.add(values.row) @@ -803,66 +884,66 @@ function guardar_y_timbrar(values){ if(usar_cartaporte){ //~ var total_distance = 0.00 //~ var total_weight = 0.00 - var cartaporte = { - TranspInternac: $$('lst_carta_TranspInternac').getValue(), + //~ 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'] + //~ } + //~ 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 + //~ 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 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']) + //~ 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 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 - - data['cartaporte'] = cartaporte + //~ 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() + data['cartaporte'] = result.values } var usar_comercioe = $$('chk_cfdi_usar_comercioe').getValue() @@ -933,6 +1014,11 @@ function cmd_timbrar_click(id, e, node){ msg += 'Estas usando el complemento:
Comercio Exterior

' } + usar_carta_porte = $$('chk_cfdi_usar_cartaporte').getValue() + if(usar_carta_porte){ + msg += 'Estas usando el complemento:
Carta Porte

' + } + if(tipo_comprobante == 'T'){ msg += 'El Tipo de Comprobante es Traslado, el total será puesto a 0 (Cero), asegurate de que sea el tipo de comprobante correcto

' } @@ -2822,6 +2908,14 @@ function cmd_ccp_add_product_click(){ } +function cmd_ccp_agregar_remolque_click(){ + var g = $$('grid_ccp_remolques') + if(g.count() < 2){ + g.add({delete: '-'}) + } +} + + function _copy_from_invoice(){ var g1 = $$('grid_details') var g2 = $$('grid_carta_mercancias') @@ -2881,6 +2975,14 @@ function grid_ccp_mercancias_click(id, e, node){ } +function grid_ccp_remolques_click(id, e, node){ + if(id.column != 'delete'){ + return + } + this.remove(id.row) +} + + function _set_carta_porte_from_json(data){ try{ var values = JSON.parse(data) @@ -2894,26 +2996,17 @@ function _set_carta_porte_from_json(data){ return } - var mercancias = values['mercancias'] + $$('lst_cp_TranspInternac').setValue(values['TranspInternac']) + $$('lst_carta_UnidadPeso').setValue(values['UnidadPeso']) + var ubicaciones = values['ubicaciones'] + var mercancias = values['mercancias'] var autotransporte = values['autotransporte'] - var operador = values['operador'] + var remolques = values['remolques'] + var seguros = values['seguros'] + var figura = values['figura'] - $$('lst_carta_UnidadPeso').setValue(values['unidad_de_peso']) - var grid = $$('grid_carta_mercancias') - grid.clearAll() - mercancias.forEach(function(row, index){ - var data = new Object() - data['delete'] = '-' - data['BienesTransp'] = row.clave_sat - data['Descripcion'] = row.descripcion - data['Cantidad'] = row.cantidad - data['ClaveUnidad'] = row.clave_unidad - data['PesoEnKg'] = row.peso_en_kg - grid.add(data) - }) - - var grid = $$('grid_carta_ubicaciones') + var grid = $$('grid_ccp_ubicaciones') grid.clearAll() ubicaciones.forEach(function(row, index){ var data = new Object() @@ -2932,32 +3025,55 @@ function _set_carta_porte_from_json(data){ grid.add(data) }) - var grid = $$('grid_carta_autotransporte') + var grid = $$('grid_ccp_mercancias') + grid.clearAll() + mercancias.forEach(function(row, index){ + var data = new Object() + data['delete'] = '-' + data['BienesTransp'] = row.clave_sat + data['Descripcion'] = row.descripcion + data['Cantidad'] = row.cantidad + data['ClaveUnidad'] = row.clave_unidad + data['PesoEnKg'] = row.peso_en_kg + grid.add(data) + }) + + var grid = $$('grid_ccp_autotransporte') grid.clearAll() var data = new Object() - data['PermSCT'] = autotransporte.tipo_permiso - data['NumPermisoSCT'] = autotransporte.numero - data['ConfigVehicular'] = autotransporte.clave - data['PlacaVM'] = autotransporte.placa - data['AnioModeloVM'] = autotransporte.modelo - if('remolque' in autotransporte){ - data['SubTipoRem'] = autotransporte.remolque - data['Placa'] = autotransporte.placa_remolque - } - data['AseguraRespCivil'] = autotransporte.aseguradora - data['PolizaRespCivil'] = autotransporte.poliza + data['PermSCT'] = autotransporte.PermSCT + data['NumPermisoSCT'] = autotransporte.NumPermisoSCT + data['ConfigVehicular'] = autotransporte.ConfigVehicular + data['PesoBrutoVehicular'] = autotransporte.PesoBrutoVehicular + data['PlacaVM'] = autotransporte.PlacaVM + data['AnioModeloVM'] = autotransporte.AnioModeloVM grid.add(data) - var grid = $$('grid_carta_tipos_figuras') + var grid = $$('grid_ccp_remolques') + //~ if(remolques.length > 0){ + grid.clearAll() + remolques.forEach(function(row, index){ + var data = new Object() + data['SubTipoRem'] = row.SubTipoRem + data['Placa'] = row.Placa + grid.add(data) + }) + //~ } + + var grid = $$('grid_ccp_seguros') grid.clearAll() var data = new Object() - data['TipoFigura'] = '01' - if('tipo' in operador){ - data['TipoFigura'] = operador.tipo - } - data['RFCFigura'] = operador.rfc - data['NombreFigura'] = operador.nombre - data['NumLicencia'] = operador.licencia + data['AseguraRespCivil'] = seguros.AseguraRespCivil + data['PolizaRespCivil'] = seguros.PolizaRespCivil + grid.add(data) + + var grid = $$('grid_ccp_tipos_figuras') + grid.clearAll() + var data = new Object() + data['TipoFigura'] = figura.TipoFigura + data['RFCFigura'] = figura.RFCFigura + data['NumLicencia'] = figura.NumLicencia + data['NombreFigura'] = figura.NombreFigura grid.add(data) $$('chk_cfdi_usar_cartaporte').setValue(1) diff --git a/source/static/js/ui/admin.js b/source/static/js/ui/admin.js index 3c3f04c..43a3c17 100644 --- a/source/static/js/ui/admin.js +++ b/source/static/js/ui/admin.js @@ -604,6 +604,7 @@ var opt_templates_cfdi = [ {id: '_4.0_cn_1.2.ods', value: 'CFDI v4.0 - Nómina v1.2'}, {id: '_4.0_cp_2.0.ods', value: 'CFDI v4.0 - Pagos v2.0'}, {id: '_4.0_ccp_2.0.ods', value: 'CFDI v4.0 - Carta Porte v2.0'}, + {id: '_4.0_ccp_3.0.ods', value: 'CFDI v4.0 - Carta Porte v3.0'}, {id: '_4.0_cd_1.1.ods', value: 'CFDI v4.0 - Donativos v1.1'}, {id: '_4.0_cce_2.0.ods', value: 'CFDI v4.0 - Comercio Exterior v2.0'}, {id: '_4.0.json', value: 'CFDI v4.0 - JSON'}, diff --git a/source/static/js/ui/invoices.js b/source/static/js/ui/invoices.js index 70834d4..78823a3 100644 --- a/source/static/js/ui/invoices.js +++ b/source/static/js/ui/invoices.js @@ -965,16 +965,16 @@ var grid_cols_ccp_ubicaciones = [ {id: 'id', header: 'ID', hidden: true}, {id: 'delete', header: '', width: 30, css: 'delete'}, {id: 'TipoUbicacion', header: 'TipoUbicacion', editor: 'select', options: opt_ccp_origen_destino, fillspace: 1}, - {id: 'IDUbicacion', header: 'IDUbicacion', hidden: true, editor: 'text', fillspace: 1}, + //~ {id: 'IDUbicacion', header: 'IDUbicacion', hidden: true, editor: 'text', fillspace: 1}, {id: 'RFCRemitenteDestinatario', header: 'RFC Rem/Des', editor: 'text', fillspace: 1}, {id: 'NombreRemitenteDestinatario', header: 'Nombre Rem/Des', editor: 'text', fillspace: 1}, - {id: 'NumRegIdTrib', header: 'NumRegIdTrib', hidden: true, editor: 'text', fillspace: 1}, - {id: 'ResidenciaFiscal', header: 'ResidenciaFiscal', hidden: true, editor: 'text', fillspace: 1}, - {id: 'NumEstacion', header: 'NumEstacion', hidden: true, editor: 'text', fillspace: 1}, - {id: 'NombreEstacion', header: 'NombreEstacion', hidden: true, editor: 'text', fillspace: 1}, - {id: 'NavegacionTrafico', header: 'NavegacionTrafico', hidden: true, editor: 'text', fillspace: 1}, + //~ {id: 'NumRegIdTrib', header: 'NumRegIdTrib', hidden: true, editor: 'text', fillspace: 1}, + //~ {id: 'ResidenciaFiscal', header: 'ResidenciaFiscal', hidden: true, editor: 'text', fillspace: 1}, + //~ {id: 'NumEstacion', header: 'NumEstacion', hidden: true, editor: 'text', fillspace: 1}, + //~ {id: 'NombreEstacion', header: 'NombreEstacion', hidden: true, editor: 'text', fillspace: 1}, + //~ {id: 'NavegacionTrafico', header: 'NavegacionTrafico', hidden: true, editor: 'text', fillspace: 1}, {id: 'FechaHoraSalidaLlegada', header: 'Fecha/Hora', editor: 'date', suggest: date_suggest, format: webix.Date.dateToStr("%D, %d-%M-%Y %h:%i"), footer: 'Total distancia:', fillspace: 1}, - {id: 'TipoEstacion', header: 'TipoEstacion', hidden: true, editor: 'text', fillspace: 1}, + //~ {id: 'TipoEstacion', header: 'TipoEstacion', hidden: true, editor: 'text', fillspace: 1}, {id: 'DistanciaRecorrida', header: 'Distancia (KM)', editor: 'text', format: webix.i18n.numberFormat, css: 'right', footer: {content: 'summColumn', css: 'right'}, fillspace: 1}, {id: 'Municipio', header: 'Municipio', editor: 'text', fillspace: 1}, {id: 'Estado', header: 'Estado', editor: 'select', options: opt_ccp_carta_estados, fillspace: 1}, @@ -1135,6 +1135,7 @@ var grid_cols_ccp_autotransporte = [ ] var grid_cols_ccp_remolques = [ {id: 'id', header: 'ID', hidden: true}, + {id: 'delete', header: '', width: 30, css: 'delete'}, {id: 'SubTipoRem', header: 'SubTipo Remolque', editor: 'select', options: opt_ccp_tipo_remolque, fillspace: 1}, {id: 'Placa', header: 'Placa', editor: 'text', fillspace: 1}, ] @@ -1167,10 +1168,10 @@ var grid_cols_ccp_tipos_figuras = [ {id: 'NombreFigura', header: 'NombreFigura', editor: 'text', fillspace: 1}, //~ {id: 'NumRegIdTribFigura', header: 'NumRegIdTribFigura', editor: 'text', fillspace: 1}, //~ {id: 'ResidenciaFiscalFigura', header: 'ResidenciaFiscalFigura', editor: 'text', fillspace: 1}, - {id: 'Municipio', header: 'Municipio', editor: 'text', fillspace: 1}, - {id: 'Estado', header: 'Estado', editor: 'select', options: opt_ccp_carta_estados, fillspace: 1}, - {id: 'Pais', header: 'País', editor: 'select', options: opt_ccp_countries, fillspace: 1}, - {id: 'CodigoPostal', header: 'C.P.', editor: 'text', fillspace: 1}, + //~ {id: 'Municipio', header: 'Municipio', editor: 'text', fillspace: 1}, + //~ {id: 'Estado', header: 'Estado', editor: 'select', options: opt_ccp_carta_estados, fillspace: 1}, + //~ {id: 'Pais', header: 'País', editor: 'select', options: opt_ccp_countries, fillspace: 1}, + //~ {id: 'CodigoPostal', header: 'C.P.', editor: 'text', fillspace: 1}, ] @@ -1220,7 +1221,6 @@ var grid_ccp_remolques = { headermenu: true, editable: true, columns: grid_cols_ccp_remolques, - data: [{id: 0}, {id: 1}], } var grid_ccp_seguros = { view: 'datatable', @@ -1275,9 +1275,14 @@ var body_ccp_mercancias = {rows:[ var body_ccp_autotransporte = {rows:[ grid_ccp_autotransporte, - {maxHeight: 10}, + {minHeight: 10}, + {cols: [ + {view: 'button', id: 'cmd_ccp_agregar_remolque', label: 'Agregar Remolque', icon: 'plus', + type: 'iconButton', autowidth: true, align: 'center'}, + {}]}, + {minHeight: 10}, grid_ccp_remolques, - {maxHeight: 10}, + {minHeight: 10}, grid_ccp_seguros, ]} From 29bfb42abc9eeb0ce78cafdcaf1b10f84d6009fe Mon Sep 17 00:00:00 2001 From: El Mau Date: Tue, 2 Apr 2024 00:20:44 -0600 Subject: [PATCH 4/4] PDF from Carta Porte v3 --- source/app/controllers/util.py | 64 +++++++++++-------- source/app/controllers/utils.py | 79 ++++++++++++++++++++++++ source/app/models/main.py | 10 --- source/static/js/controller/invoices.js | 61 +----------------- source/templates/plantilla_ccp.ods | Bin 0 -> 49733 bytes 5 files changed, 119 insertions(+), 95 deletions(-) create mode 100644 source/templates/plantilla_ccp.ods diff --git a/source/app/controllers/util.py b/source/app/controllers/util.py index b1e8d46..87944ea 100644 --- a/source/app/controllers/util.py +++ b/source/app/controllers/util.py @@ -30,6 +30,7 @@ import requests import sqlite3 import socket import subprocess +import sys import tempfile import textwrap import threading @@ -44,7 +45,6 @@ from pathlib import Path from xml.etree import ElementTree as ET from xml.dom.minidom import parseString - try: import uno from com.sun.star.beans import PropertyValue @@ -52,9 +52,20 @@ try: from com.sun.star.view.PaperFormat import LETTER APP_LIBO = True 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 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 from settings import USAR_TOKEN, API, DECIMALES_TAX -# ~ from .configpac import AUTH from .utils import get_qr @@ -951,6 +961,7 @@ class LIBO(object): return # ~ print(data) + qr = data.pop('qr', False) figuras = data.pop('figuras') mercancias = data.pop('mercancias') detalle = mercancias.pop('detalle') @@ -1019,7 +1030,27 @@ class LIBO(object): cell_3 = self._set_cell(v=unidad, cell=cell_3) cell_4 = self._set_cell(v=cantidad, cell=cell_4) 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 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}' if 'carta_porte' in data: - default = 'plantilla_factura_ccp.ods' + default = 'plantilla_ccp.ods' version = '{}_ccp_{}'.format(version, data['carta_porte']['version']) if data.get('pagos', False): @@ -1844,24 +1875,6 @@ def to_letters(value, currency): 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): node = doc.find('{}CfdiRelacionados'.format(PRE[version])) if node is None: @@ -3146,7 +3159,8 @@ def parse_xml2(xml_str): def get_idccp(): - uuid_v4 = uuid.uuid4() - 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()}" + uuid4 = str(uuid.uuid4()).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 diff --git a/source/app/controllers/utils.py b/source/app/controllers/utils.py index 313a788..5ef7bb1 100644 --- a/source/app/controllers/utils.py +++ b/source/app/controllers/utils.py @@ -261,9 +261,11 @@ class CfdiToDict(object): 'cfdi4.0': 'http://www.sat.gob.mx/cfd/4', } NS = { + 'tfd': 'http://www.sat.gob.mx/TimbreFiscalDigital', 'divisas': 'http://www.sat.gob.mx/divisas', 'leyendasFisc': 'http://www.sat.gob.mx/leyendasFiscales', 'cartaporte20': 'http://www.sat.gob.mx/CartaPorte20', + 'cartaporte30': 'http://www.sat.gob.mx/CartaPorte30', 'nomina12': 'http://www.sat.gob.mx/nomina12', 'cce20': 'http://www.sat.gob.mx/ComercioExterior20', } @@ -397,11 +399,23 @@ class CfdiToDict(object): self.version = self._root.attrib['Version'] ns = f'cfdi{self.version}' self.NS['cfdi'] = self.NS_VERSION[ns] + self._timbre_fiscal() self._informacion_global() self._receptor() self._complementos() 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): self._values['informacion_global'] = {} @@ -514,10 +528,75 @@ class CfdiToDict(object): self._values['carta_porte'] = values + self._complemento_carta_porte(complemento) self._complemento_comercio_exterior(complemento) 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): path = '//cce20:ComercioExterior' comercio_exterior = complemento.xpath(path, namespaces=self.NS) diff --git a/source/app/models/main.py b/source/app/models/main.py index 4551753..072ca1a 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -4823,16 +4823,6 @@ class Facturas(BaseModel): obj = SATTipoRelacion.get(SATTipoRelacion.key==invoice.tipo_relacion) 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 def _get_not_in_xml2(self, invoice, data): diff --git a/source/static/js/controller/invoices.js b/source/static/js/controller/invoices.js index 125fb21..67db55a 100644 --- a/source/static/js/controller/invoices.js +++ b/source/static/js/controller/invoices.js @@ -882,68 +882,9 @@ function guardar_y_timbrar(values){ var usar_cartaporte = $$('chk_cfdi_usar_cartaporte').getValue() 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() data['cartaporte'] = result.values + $$('chk_cfdi_usar_cartaporte').setValue(false) } var usar_comercioe = $$('chk_cfdi_usar_comercioe').getValue() diff --git a/source/templates/plantilla_ccp.ods b/source/templates/plantilla_ccp.ods new file mode 100644 index 0000000000000000000000000000000000000000..2339002f2581db2383bd6b4fd33634f341bc1278 GIT binary patch literal 49733 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 eqGSH%bs!@S@-