Soporte basico para complemento Comercio Exterior

This commit is contained in:
El Mau 2022-03-28 21:34:10 -06:00
commit de856f28ab
9 changed files with 185 additions and 30 deletions

View File

@ -1,3 +1,8 @@
v 1.47.0 [28-Mar-2022]
----------------------
- Mejora: Soporte basico para complemento Comercio Exterior.
v 1.46.5 [10-Mar-2022]
----------------------
- Error: Al timbrar nómina con Comercio Digital

View File

@ -1,2 +1 @@
1.46.5
1.47.0

View File

@ -102,6 +102,12 @@ SAT = {
'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',
},
'comercioe': {
'version': '1.1',
'prefix': 'cce11',
'xmlns': 'http://www.sat.gob.mx/ComercioExterior11',
'schema': ' http://www.sat.gob.mx/ComercioExterior11 http://www.sat.gob.mx/sitio_internet/cfd/ComercioExterior11/ComercioExterior11.xsd',
}
}
@ -122,6 +128,7 @@ class CFDI(object):
self._is_nomina = False
self._leyendas = False
self._carta_porte = False
self._comercio_exterior = False
self._divisas = ''
self.error = ''
@ -174,6 +181,7 @@ class CFDI(object):
self._pagos = bool(datos['complementos'].get('pagos', False))
self._leyendas = bool(datos['complementos'].get('leyendas', False))
self._carta_porte = bool(datos['complementos'].get('cartaporte', False))
self._comercio_exterior = bool(datos['complementos'].get('comercioe', False))
self._divisas = datos['comprobante'].pop('divisas', '')
@ -245,10 +253,16 @@ class CFDI(object):
attributes[name] = SAT['cartaporte']['xmlns']
schema_carta_porte = SAT['cartaporte']['schema']
schema_comercioe = ''
if self._comercio_exterior:
name = 'xmlns:{}'.format(SAT['comercioe']['prefix'])
attributes[name] = SAT['comercioe']['xmlns']
schema_carta_porte = SAT['comercioe']['schema']
attributes['xsi:schemaLocation'] = self._sat_cfdi['schema'] + \
schema_locales + schema_donativo + schema_ine + schema_edu + \
schema_divisas + schema_nomina + schema_pagos + schema_leyendas + \
schema_carta_porte
schema_carta_porte + schema_comercioe
attributes.update(datos)
if not 'Version' in attributes:
@ -556,57 +570,59 @@ class CFDI(object):
for leyend in datos['leyendas']:
ET.SubElement(node_leyend, '{}:Leyenda'.format(pre), leyend)
if 'ce' in datos:
pre = 'cce11'
datos = datos.pop('ce')
if self._comercio_exterior:
prefix = SAT['comercioe']['prefix']
datos = datos.pop('comercioe')
emisor = datos.pop('emisor')
propietario = datos.pop('propietario')
# ~ propietario = datos.pop('propietario')
receptor = datos.pop('receptor')
destinatario = datos.pop('destinatario')
conceptos = datos.pop('conceptos')
conceptos = datos.pop('mercancias')
attributes = {}
attributes['xmlns:{}'.format(pre)] = \
'http://www.sat.gob.mx/ComercioExterior11'
attributes['xsi:schemaLocation'] = \
'http://www.sat.gob.mx/ComercioExterior11 ' \
'http://www.sat.gob.mx/sitio_internet/cfd/ComercioExterior11/ComercioExterior11.xsd'
attributes.update(datos)
# ~ attributes = {}
# ~ attributes['xmlns:{}'.format(pre)] = \
# ~ 'http://www.sat.gob.mx/ComercioExterior11'
# ~ attributes['xsi:schemaLocation'] = \
# ~ 'http://www.sat.gob.mx/ComercioExterior11 ' \
# ~ 'http://www.sat.gob.mx/sitio_internet/cfd/ComercioExterior11/ComercioExterior11.xsd'
attr = {'Version': SAT['comercioe']['version']}
attr.update(datos)
ce = ET.SubElement(
complemento, '{}:ComercioExterior'.format(pre), attributes)
self._complemento, f'{prefix}:ComercioExterior', attr)
attributes = {}
if 'Curp' in emisor:
attributes = {'Curp': emisor.pop('Curp')}
node = ET.SubElement(ce, '{}:Emisor'.format(pre), attributes)
ET.SubElement(node, '{}:Domicilio'.format(pre), emisor)
node = ET.SubElement(ce, '{}:Emisor'.format(prefix), attributes)
ET.SubElement(node, '{}:Domicilio'.format(prefix), emisor)
if propietario:
ET.SubElement(ce, '{}:Propietario'.format(pre), propietario)
# ~ if propietario:
# ~ ET.SubElement(ce, '{}:Propietario'.format(prefix), propietario)
attributes = {}
if 'NumRegIdTrib' in receptor:
attributes = {'NumRegIdTrib': receptor.pop('NumRegIdTrib')}
node = ET.SubElement(ce, '{}:Receptor'.format(pre), attributes)
ET.SubElement(node, '{}:Domicilio'.format(pre), receptor)
node = ET.SubElement(ce, '{}:Receptor'.format(prefix), attributes)
ET.SubElement(node, '{}:Domicilio'.format(prefix), receptor)
attributes = {}
if 'NumRegIdTrib' in destinatario:
attributes = {'NumRegIdTrib': destinatario.pop('NumRegIdTrib')}
if 'Nombre' in destinatario:
attributes.update({'Nombre': destinatario.pop('Nombre')})
node = ET.SubElement(ce, '{}:Destinatario'.format(pre), attributes)
ET.SubElement(node, '{}:Domicilio'.format(pre), destinatario)
node = ET.SubElement(ce, '{}:Destinatario'.format(prefix), attributes)
ET.SubElement(node, '{}:Domicilio'.format(prefix), destinatario)
node = ET.SubElement(ce, '{}:Mercancias'.format(pre))
node = ET.SubElement(ce, '{}:Mercancias'.format(prefix))
fields = ('Marca', 'Modelo', 'SubModelo', 'NumeroSerie')
for row in conceptos:
detalle = {}
for f in fields:
if f in row:
detalle[f] = row.pop(f)
concepto = ET.SubElement(node, '{}:Mercancia'.format(pre), row)
concepto = ET.SubElement(node, '{}:Mercancia'.format(prefix), row)
if detalle:
ET.SubElement(
concepto, '{}:DescripcionesEspecificas'.format(pre), detalle)
concepto, '{}:DescripcionesEspecificas'.format(prefix), detalle)
return

View File

@ -344,6 +344,7 @@ def config_timbrar():
'cfdi_ine': Configuracion.get_bool('chk_config_ine'),
'cfdi_edu': Configuracion.get_bool('chk_config_edu'),
'cfdi_carta_porte': Configuracion.get_bool('chk_config_carta_porte'),
'cfdi_comercioe': Configuracion.get_bool('chk_config_comercio_exterior'),
'cfdi_divisas': Configuracion.get_bool('chk_config_divisas'),
'cfdi_metodo_pago': Configuracion.get_bool('chk_config_ocultar_metodo_pago'),
'cfdi_condicion_pago': Configuracion.get_bool('chk_config_ocultar_condiciones_pago'),
@ -482,6 +483,7 @@ class Configuracion(BaseModel):
'chk_config_ine',
'chk_config_edu',
'chk_config_carta_porte',
'chk_config_comercio_exterior',
'chk_config_pagos',
'chk_config_divisas',
'chk_cfg_pays_data_bank',
@ -5398,6 +5400,21 @@ class Facturas(BaseModel):
FacturasComplementos.create(**data)
return
def _save_comercioe(self, invoice, valores):
if not valores:
return
# ~ values = utils.loads(valores)
data = {
'factura': invoice,
'nombre': 'comercioe',
# ~ 'valores': utils.dumps(values),
'valores': valores,
}
FacturasComplementos.create(**data)
return
def _get_serie(self, user, default_serie):
if user.sucursal is None:
return default_serie
@ -5410,6 +5427,7 @@ class Facturas(BaseModel):
relacionados = util.loads(values.pop('relacionados'))
ine = values.pop('ine', {})
cartaporte = values.pop('cartaporte', {})
comercioe = values.pop('comercioe', {})
tipo_comprobante = values['tipo_comprobante']
folio_custom = values.pop('folio_custom', '')
divisas = values.pop('divisas', '')
@ -5453,6 +5471,7 @@ class Facturas(BaseModel):
cls._guardar_relacionados(cls, obj, relacionados)
cls._guardar_ine(cls, obj, ine)
cls._save_cartaporte(cls, obj, cartaporte)
cls._save_comercioe(cls, obj, comercioe)
cls._save_leyendas_fiscales(cls, obj, leyendas_fiscales)
obj.subtotal = totals['subtotal']
obj.descuento = totals['descuento']
@ -11480,4 +11499,3 @@ if __name__ == '__main__':
args = _process_command_line_arguments()
main(args)

View File

@ -42,7 +42,7 @@ except ImportError:
DEBUG = DEBUG
VERSION = '1.46.5'
VERSION = '1.47.0'
EMAIL_SUPPORT = ('soporte@empresalibre.mx',)
TITLE_APP = '{} v{}'.format(TITLE_APP, VERSION)

View File

@ -115,6 +115,7 @@ var controllers = {
$$('chk_config_ine').attachEvent('onItemClick', chk_config_item_click)
$$('chk_config_edu').attachEvent('onItemClick', chk_config_item_click)
$$('chk_config_carta_porte').attachEvent('onItemClick', chk_config_item_click)
$$('chk_config_comercio_exterior').attachEvent('onItemClick', chk_config_item_click)
$$('chk_config_leyendas_fiscales').attachEvent('onItemClick', chk_config_item_click)
$$('cmd_admin_leyendas_fiscales').attachEvent('onItemClick', cmd_admin_leyendas_fiscales_click)

View File

@ -22,6 +22,7 @@ var tipo_relacion = ''
var anticipo = false
var donativo = false
var cfg_invoice = new Object()
var values_comercioe = null
function init_config_invoices(){
@ -94,6 +95,7 @@ var invoices_controllers = {
$$('cmd_carta_add_product').attachEvent('onItemClick', cmd_carta_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)
$$('cmd_import_json_comercioe').attachEvent('onItemClick', cmd_import_json_comercioe_click)
webix.extend($$('grid_invoices'), webix.ProgressBar)
@ -224,12 +226,17 @@ function default_config(){
if(!values.cfdi_carta_porte){
$$('tv_invoice').getTabbar().hideOption('Carta Porte')
}else{
get_leyendas_fiscales()
$$('tv_invoice').getTabbar().showOption('Carta Porte')
}
if(!values.cfdi_comercioe){
$$('tv_invoice').getTabbar().hideOption('Comercio Exterior')
}else{
$$('tv_invoice').getTabbar().showOption('Comercio Exterior')
}
cfg_invoice['leyendasfiscales'] = values.cfdi_leyendasfiscales
cfg_invoice['edu'] = values.cfdi_edu
cfg_invoice['carta_porte'] = values.cfdi_carta_porte
cfg_invoice['comercioe'] = values.cfdi_comercioe
cfg_invoice['open_pdf'] = values.cfdi_open_pdf
cfg_invoice['tax_locales'] = values.cfdi_tax_locales
cfg_invoice['tax_decimals'] = values.cfdi_tax_decimals
@ -769,10 +776,18 @@ function guardar_y_timbrar(values){
data['cartaporte'] = cartaporte
}
var usar_comercioe = $$('chk_cfdi_usar_comercioe').getValue()
if(usar_comercioe){
data['comercioe'] = values_comercioe
}
if(!save_invoice(data)){
return
}
values_comercioe = null
$$('chk_cfdi_usar_comercioe').setValue(false)
table_relaciones.clear()
tipo_relacion = ''
anticipo = false
@ -816,11 +831,21 @@ function cmd_timbrar_click(id, e, node){
}
msg += '<BR><BR>'
}
usar_ine = $$('chk_cfdi_usar_ine').getValue()
if(usar_ine){
msg += 'Estas usando el complemento INE<BR><BR>'
}
if($$('chk_cfdi_usar_comercioe').getValue()){
msg += 'Estas usando el complemento Comercio Exterior<BR><BR>'
if(values_comercioe === null){
msg = 'El complemento de Comercio Exterior esta vacío'
msg_error(msg)
return
}
}
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<BR><BR>'
}
@ -2815,3 +2840,36 @@ function up_invoice_json_on_after_file_add(obj){
}
$$('win_carta_import_json').close()
}
function _set_from_json_comercioe(data){
try{
values_comercioe = JSON.parse(data)
}catch(e){
msg_error('Revisa el archivo JSON')
webix.alert({
title: 'Error al cargar JSON',
text: e.message,
type: 'alert-error'
})
return
}
msg = 'Valores cargados correctamente'
msg_ok(msg)
}
function cmd_import_json_comercioe_click(){
win_import_json_comercioe.init()
$$('win_import_json_comercioe').show()
}
function up_invoice_json_comercioe_on_after_file_add(obj){
let reader = new FileReader()
reader.readAsText(obj.file)
reader.onload = function(){
_set_from_json_comercioe(reader.result)
}
$$('win_import_json_comercioe').close()
}

View File

@ -887,6 +887,11 @@ var options_admin_complements = [
{view: 'checkbox', id: 'chk_config_carta_porte', labelWidth: 0,
labelRight: 'Usar el complemento Carta Porte'},
{maxWidth: 15}]},
{template: 'Complemento para Comercio Exterior', type: 'section'},
{cols: [{maxWidth: 15},
{view: 'checkbox', id: 'chk_config_comercio_exterior', labelWidth: 0,
labelRight: 'Usar el complemento Comercio Exterior'},
{maxWidth: 15}]},
]

View File

@ -1198,6 +1198,16 @@ var controls_carta_porte = [
]
var controls_comercio_exterior = [
{cols: [{maxWidth: 15},
{view: 'checkbox', id: 'chk_cfdi_usar_comercioe', labelWidth: 0,
labelRight: 'Usar el complemento Comercio Exterior'}, {},
{view: 'button', id: 'cmd_import_json_comercioe', label: 'Importar JSON',
icon: 'upload', type: 'iconButton', autowidth: true, align: 'center'},
{maxWidth: 15}]}
]
var form_carta_porte = {
type: 'space',
responsive: true,
@ -1211,6 +1221,19 @@ var form_carta_porte = {
}
var form_comercio_exterior = {
type: 'space',
responsive: true,
cols: [{
view: 'form',
id: 'form_comercio_exterior',
complexData: true,
scroll: true,
elements: controls_comercio_exterior,
}]
}
var controls_invoices = [
{
view: 'tabview',
@ -1222,6 +1245,7 @@ var controls_invoices = [
{id: 'INE', rows: controls_ine},
{id: 'Leyendas Fiscales', rows: controls_leyendas_fiscales},
{id: 'Carta Porte', rows: [form_carta_porte]},
{id: 'Comercio Exterior', rows: [form_comercio_exterior]},
]
},
]
@ -1368,3 +1392,32 @@ var win_carta_import_json = {
$$('up_invoice_json').attachEvent('onAfterFileAdd', up_invoice_json_on_after_file_add)
}
}
var body_upload_json_comercioe = {rows: [
{view: 'form', id: 'form_upload_comercioe', rows: [
{cols: [{},
{view: 'uploader', id: 'up_invoice_json', autosend: false,
link: 'lst_upload_invoice', value: 'Seleccionar Archivo',
accept:'application/json', upload: ''}, {}]},
{cols: [
{view: 'list', id: 'lst_upload_invoice', name: 'lst_upload_invoice',
type: 'uploader', autoheight: true, borderless: true}]},
]},
]}
var win_import_json_comercioe = {
init: function(){
webix.ui({
view: 'window',
id: 'win_import_json_comercioe',
width: 400,
modal: true,
position: 'center',
head: 'Importar Comerio Exterior JSON',
body: body_upload_json_comercioe,
})
$$('up_invoice_json').attachEvent('onAfterFileAdd', up_invoice_json_comercioe_on_after_file_add)
}
}