From 1991c68b3ba8123bb2cf268b98f98bf7247fd1ca Mon Sep 17 00:00:00 2001 From: El Mau Date: Thu, 10 Mar 2022 20:29:50 -0600 Subject: [PATCH] Soporte basico para Comercio Exterior --- CHANGELOG.md | 6 + VERSION | 2 +- source/app/controllers/cfdi_xml.py | 25 +++- source/app/controllers/main.py | 12 ++ source/app/controllers/util.py | 11 +- source/app/controllers/utils.py | 8 +- source/app/main.py | 2 + source/app/models/db.py | 3 + source/app/models/main.py | 144 +++++++++++++++++++++--- source/app/settings.py | 5 +- source/static/js/controller/invoices.js | 13 +++ source/static/js/controller/partners.js | 41 +++++++ source/static/js/ui/invoices.js | 5 + source/static/js/ui/partners.js | 10 +- 14 files changed, 257 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6843a0..8961f43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +v 2.0.0 [31-Mar-2022] +---------------------- + - Primera versión de timbrado con CFDI4 + - **IMPORTANTE** NO intentes timbrar si **antes** no has validado en nuestro demo que puedes timbrar tus CFDIs habituales. + + v 1.47.0 [28-Mar-2022] ---------------------- - Mejora: Soporte basico para complemento Comercio Exterior. diff --git a/VERSION b/VERSION index 21998d3..227cea2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.47.0 +2.0.0 diff --git a/source/app/controllers/cfdi_xml.py b/source/app/controllers/cfdi_xml.py index 5e17926..3dafadd 100644 --- a/source/app/controllers/cfdi_xml.py +++ b/source/app/controllers/cfdi_xml.py @@ -25,16 +25,21 @@ from logbook import Logger log = Logger('XML') -CFDI_ACTUAL = 'cfdi33' +CFDI_ACTUAL = 'cfdi40' NOMINA_ACTUAL = 'nomina12' +DEFAULT = { + 'exportacion': '01', +} + + SAT = { 'xsi': 'http://www.w3.org/2001/XMLSchema-instance', - 'cfdi32': { - 'version': '3.2', + 'cfdi40': { + 'version': '4.0', 'prefix': 'cfdi', - 'xmlns': 'http://www.sat.gob.mx/cfd/3', - 'schema': 'http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd', + 'xmlns': 'http://www.sat.gob.mx/cfd/4', + 'schema': 'http://www.sat.gob.mx/cfd/4 http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd', }, 'cfdi33': { 'version': '3.3', @@ -42,6 +47,12 @@ SAT = { 'xmlns': 'http://www.sat.gob.mx/cfd/3', 'schema': 'http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv33.xsd', }, + 'cfdi32': { + 'version': '3.2', + 'prefix': 'cfdi', + 'xmlns': 'http://www.sat.gob.mx/cfd/3', + 'schema': 'http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd', + }, 'nomina11': { 'version': '1.1', 'prefix': 'nomina', @@ -270,6 +281,10 @@ class CFDI(object): if not 'Fecha' in attributes: attributes['Fecha'] = self._now() + # ~ cfdi4 + if not 'Exportacion' in attributes: + attributes['Exportacion'] = DEFAULT['exportacion'] + self._cfdi = ET.Element('{}:Comprobante'.format(self._pre), attributes) return diff --git a/source/app/controllers/main.py b/source/app/controllers/main.py index 1b333ed..5c25183 100644 --- a/source/app/controllers/main.py +++ b/source/app/controllers/main.py @@ -797,3 +797,15 @@ class AppSATUnidadesPeso(object): user = req.env['beaker.session']['userobj'] req.context['result'] = self._db.sat_unidades_peso_post(values, user) resp.status = falcon.HTTP_200 + + +class AppSATRegimenes(object): + + def __init__(self, db): + self._db = db + + def on_get(self, req, resp): + values = req.params + user = req.env['beaker.session']['userobj'] + req.context['result'] = self._db.sat_regimenes_get(values, user) + resp.status = falcon.HTTP_200 diff --git a/source/app/controllers/util.py b/source/app/controllers/util.py index 548bbf1..68023b5 100644 --- a/source/app/controllers/util.py +++ b/source/app/controllers/util.py @@ -78,6 +78,7 @@ import segno from .pacs.cfdi_cert import SATCertificate from settings import ( + CFDI_VERSIONS, EXT, MXN, PATHS, @@ -1754,7 +1755,7 @@ def _comprobante(doc, options): data['tiporelacion'] = options.get('tiporelacion', '') return data - if data['version'] == '3.3': + if data['version'] in CFDI_VERSIONS: tipos = { 'I': 'ingreso', 'E': 'egreso', @@ -1857,7 +1858,7 @@ def _conceptos(doc, version, options): data.append(values) continue - if version == '3.3': + if version in CFDI_VERSIONS: if 'noidentificacion' in values: values['noidentificacion'] = '{}\n(SAT {})'.format( values['noidentificacion'], values['ClaveProdServ']) @@ -1921,7 +1922,7 @@ def _totales(doc, cfdi, version): # ~ for n in node.getchildren(): for n in list(node): tmp = CaseInsensitiveDict(n.attrib.copy()) - if version == '3.3': + if version in CFDI_VERSIONS: tasa = round(float(tmp['tasaocuota']), DECIMALES) title = 'Traslado {} {}'.format(tn.get(tmp['impuesto']), tasa) else: @@ -1933,7 +1934,7 @@ def _totales(doc, cfdi, version): # ~ for n in node.getchildren(): for n in list(node): tmp = CaseInsensitiveDict(n.attrib.copy()) - if version == '3.3': + if version in CFDI_VERSIONS: title = 'Retención {} {}'.format( tn.get(tmp['impuesto']), '') else: @@ -1965,7 +1966,7 @@ def _totales(doc, cfdi, version): def _timbre(doc, version, values, pdf_from='1'): CADENA = '||{version}|{UUID}|{FechaTimbrado}|{selloCFD}|{noCertificadoSAT}||' - if version == '3.3': + if version in CFDI_VERSIONS: CADENA = '||{Version}|{UUID}|{FechaTimbrado}|{SelloCFD}|{NoCertificadoSAT}||' node = doc.find('{}Complemento/{}TimbreFiscalDigital'.format( PRE[version], PRE['TIMBRE'])) diff --git a/source/app/controllers/utils.py b/source/app/controllers/utils.py index 6df126f..4b14959 100644 --- a/source/app/controllers/utils.py +++ b/source/app/controllers/utils.py @@ -255,8 +255,11 @@ class SendMail(object): class CfdiToDict(object): + NS_VERSION = { + 'cfdi3.3': 'http://www.sat.gob.mx/cfd/3', + 'cfdi4.0': 'http://www.sat.gob.mx/cfd/4', + } NS = { - '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', @@ -318,6 +321,9 @@ class CfdiToDict(object): return self._values def _get_values(self): + version = self._root.attrib['Version'] + ns = f'cfdi{version}' + self.NS['cfdi'] = self.NS_VERSION[ns] self._complementos() return diff --git a/source/app/main.py b/source/app/main.py index 6346cd4..9eddc7a 100644 --- a/source/app/main.py +++ b/source/app/main.py @@ -25,6 +25,7 @@ from controllers.main import (AppEmpresas, AppWareHouse, AppWareHouseProduct, AppSATUnidadesPeso, + AppSATRegimenes, ) @@ -78,6 +79,7 @@ api.add_route('/warehouseproduct', AppWareHouseProduct(db)) api.add_route('/ticketsdetails', AppTicketsDetails(db)) api.add_route('/users', AppUsers(db)) api.add_route('/satunidadespeso', AppSATUnidadesPeso(db)) +api.add_route('/satregimenes', AppSATRegimenes(db)) session_options = { diff --git a/source/app/models/db.py b/source/app/models/db.py index 3d55374..80a0ba3 100644 --- a/source/app/models/db.py +++ b/source/app/models/db.py @@ -526,6 +526,9 @@ class StorageEngine(object): def sat_unidades_peso_post(self, args, user): return main.SATUnidadesPeso.post(args, user) + def sat_regimenes_get(self, filters, user): + return main.SATRegimenes.get_data(filters, user) + # Companies only in MV def _get_empresas(self, values): return main.companies_get() diff --git a/source/app/models/main.py b/source/app/models/main.py index afd8add..8f01c77 100644 --- a/source/app/models/main.py +++ b/source/app/models/main.py @@ -939,6 +939,26 @@ class SATRegimenes(BaseModel): ) return tuple(rows) + @classmethod + def _get_actives(cls, filters, user): + where = ((SATRegimenes.activo==True) & (SATRegimenes.fisica==True)) + if (filters['morales']=='true'): + where = ((SATRegimenes.activo==True) & (SATRegimenes.moral==True)) + + rows = (SATRegimenes + .select( + SATRegimenes.id, + SATRegimenes.name.alias('value')) + .where(where) + .dicts() + ) + return tuple(rows) + + @classmethod + def get_data(cls, filters, user): + opt = filters['opt'] + return getattr(cls, f'_get_{opt}')(filters, user) + class Emisor(BaseModel): rfc = TextField(unique=True) @@ -1027,8 +1047,6 @@ class Emisor(BaseModel): 'ong_autorizacion': obj.autorizacion, 'ong_fecha': obj.fecha_autorizacion, 'ong_fecha_dof': obj.fecha_dof, - # ~ 'correo_timbrado': obj.correo_timbrado, - # ~ 'token_timbrado': obj.token_timbrado, 'token_soporte': obj.token_soporte, 'emisor_registro_patronal': obj.registro_patronal, 'regimenes': [row.id for row in obj.regimenes] @@ -2787,6 +2805,13 @@ class Socios(BaseModel): if fields['pais'] != 'México': fields['pais'] = fields['pais'].upper() + if 'regimenes' in fields: + fields['regimenes'] = utils.loads(fields['regimenes']) + if isinstance(fields['regimenes'], list): + fields['regimenes'] = tuple(map(int, fields['regimenes'])) + else: + fields['regimenes'] = (fields['regimenes'],) + return fields @classmethod @@ -2802,18 +2827,9 @@ class Socios(BaseModel): str(CondicionesPago.get(id=row['condicion_pago'])) row['partner_balance'] = row.pop('saldo_cliente') row['partner_email_fp'] = row.pop('correo_facturasp') + row['regimenes'] = SociosRegimenes.get_by_socio(row['id']) return row - #~ return {'data': data['rows'][:100], 'pos':0, 'total_count': 1300} - #~ start = 0 - #~ count = 0 - #~ end = 100 - #~ if values: - #~ {'start': '100', 'count': '100', 'continue': 'true'} - #~ start = int(values['start']) - #~ cont = int(values['count']) - #~ end = start + count - total = Socios.select().count() rows = (Socios @@ -2829,19 +2845,23 @@ class Socios(BaseModel): @classmethod def get_by_client(cls, values): id = int(values.get('id', 0)) + if id: row = (Socios .select( Socios.id, Socios.nombre, Socios.rfc, SATFormaPago.key.alias('forma_pago'), - SATUsoCfdi.key.alias('uso_cfdi')) + SATUsoCfdi.key.alias('uso_cfdi'), + Socios.codigo_postal) .join(SATFormaPago, JOIN.LEFT_OUTER).switch(Socios) .join(SATUsoCfdi, JOIN.LEFT_OUTER).switch(Socios) .where((Socios.id==id) & (Socios.es_cliente==True)) .dicts() ) if len(row): - return {'ok': True, 'row': row[0]} + client = row[0] + client['regimenes'] = SociosRegimenes.get_by_key(client['id']) + return {'ok': True, 'row': client} return {'ok': False} name = values.get('name', '') @@ -2849,7 +2869,8 @@ class Socios(BaseModel): rows = (Socios .select(Socios.id, Socios.nombre, Socios.rfc, SATFormaPago.key.alias('forma_pago'), - SATUsoCfdi.key.alias('uso_cfdi')) + SATUsoCfdi.key.alias('uso_cfdi'), + Socios.codigo_postal) .join(SATFormaPago, JOIN.LEFT_OUTER).switch(Socios) .join(SATUsoCfdi, JOIN.LEFT_OUTER).switch(Socios) .where((Socios.es_cliente==True & Socios.es_activo==True) & @@ -2863,6 +2884,7 @@ class Socios(BaseModel): def add(cls, values): accounts = util.loads(values.pop('accounts', '[]')) fields = cls._clean(cls, values) + regimenes = fields.pop('regimenes', ()) w = ((Socios.rfc==fields['rfc']) & (Socios.slug==fields['slug'])) if Socios.select().where(w).exists(): @@ -2892,6 +2914,16 @@ class Socios(BaseModel): except IntegrityError: pass + for regimen in regimenes: + try: + fields = { + 'socio': obj, + 'regimen': regimen, + } + SociosRegimenes.create(**fields) + except IntegrityError: + pass + row = { 'id': obj.id, 'rfc': obj.rfc, @@ -2905,6 +2937,8 @@ class Socios(BaseModel): def actualizar(cls, values, id): fields = cls._clean(cls, values) fields.pop('accounts', '') + regimenes = fields.pop('regimenes', ()) + try: q = Socios.update(**fields).where(Socios.id==id) q.execute() @@ -2913,6 +2947,19 @@ class Socios(BaseModel): data = {'ok': False, 'row': {}, 'new': True, 'msg': msg} return data + obj = Socios.get(Socios.id==id) + q = SociosRegimenes.delete().where(SociosRegimenes.socio==id) + q.execute() + for regimen in regimenes: + try: + fields = { + 'socio': obj, + 'regimen': regimen, + } + SociosRegimenes.create(**fields) + except IntegrityError: + pass + obj = Socios.get(Socios.id==id) row = { 'id': id, @@ -2934,6 +2981,8 @@ class Socios(BaseModel): q = SociosCuentasBanco.delete().where(SociosCuentasBanco.socio==id) q.execute() + q = SociosRegimenes.delete().where(SociosRegimenes.socio==id) + q.execute() q = Socios.delete().where(Socios.id==id) return bool(q.execute()) @@ -3040,6 +3089,41 @@ class SociosCuentasBanco(BaseModel): return account.socio == invoice.cliente +class SociosRegimenes(BaseModel): + socio = ForeignKeyField(Socios) + regimen = ForeignKeyField(SATRegimenes) + + class Meta: + indexes = ( + (('socio', 'regimen'), True), + ) + + @classmethod + def get_by_key(self, socio): + fields = (SATRegimenes.key.alias('id'), SATRegimenes.name.alias('value')) + where = (SociosRegimenes.socio == socio) + regimenes = (SociosRegimenes + .select(*fields) + .where(where) + .join(SATRegimenes).switch(SociosRegimenes) + .dicts() + ) + return tuple(regimenes) + + @classmethod + def get_by_socio(self, socio): + fields = (SATRegimenes.id,) + where = (SociosRegimenes.socio == socio) + regimenes = (SociosRegimenes + .select(*fields) + .where(where) + .join(SATRegimenes).switch(SociosRegimenes) + .tuples() + ) + regimenes = [r[0] for r in regimenes] + return regimenes + + class Contactos(BaseModel): socio = ForeignKeyField(Socios) titulo = ForeignKeyField(TipoTitulo) @@ -3806,6 +3890,7 @@ class Productos(BaseModel): cantidad_empaque = DecimalField(default=0.0, max_digits=14, decimal_places=4, auto_round=True) is_discontinued = BooleanField(default=False) + objeto_impuesto = TextField(default='02') class Meta: order_by = ('descripcion',) @@ -4389,6 +4474,8 @@ class Facturas(BaseModel): egreso_anticipo = BooleanField(default=False) tipo_relacion = TextField(default='') error = TextField(default='') + exportacion = TextField(default='01') + receptor_regimen = TextField(default='') class Meta: order_by = ('fecha',) @@ -5590,6 +5677,8 @@ class Facturas(BaseModel): 'Rfc': invoice.cliente.rfc, 'Nombre': invoice.cliente.nombre, 'UsoCFDI': invoice.uso_cfdi, + 'DomicilioFiscalReceptor': invoice.cliente.codigo_postal, + 'RegimenFiscalReceptor': invoice.receptor_regimen } if invoice.cliente.tipo_persona == 4: if invoice.cliente.pais: @@ -5701,6 +5790,16 @@ class Facturas(BaseModel): taxes['retenciones'] = retenciones concepto['impuestos'] = taxes + + # cfdi4 + if row.producto.objeto_impuesto: + concepto['ObjetoImp'] = row.producto.objeto_impuesto + else: + if taxes: + concepto['ObjetoImp'] = '02' + else: + concepto['ObjetoImp'] = '01' + conceptos.append(concepto) impuestos = {} @@ -5749,11 +5848,14 @@ class Facturas(BaseModel): if tax_decimals: xml_importe = FORMAT_TAX.format(tax.importe) + xml_tax_base = FORMAT_TAX.format(tax.base) else: xml_importe = FORMAT.format(tax.importe) + xml_tax_base = FORMAT.format(tax.base) if tax.impuesto.tipo == 'T': traslado = { + "Base": xml_tax_base, "Impuesto": tax.impuesto.key, "TipoFactor": tipo_factor, "TasaOCuota": str(tax.impuesto.tasa), @@ -10546,6 +10648,7 @@ def _crear_tablas(rfc): PartnerInvoices, WareHouseProduct, SATUnidadesPeso, + SociosRegimenes, ] log.info('Creando tablas...') database_proxy.create_tables(tablas, True) @@ -10604,6 +10707,7 @@ def _migrate_tables(rfc=''): PartnerInvoices, WareHouseProduct, SATUnidadesPeso, + SociosRegimenes, ] log.info('Creando tablas nuevas...') database_proxy.create_tables(tablas, True) @@ -10729,6 +10833,10 @@ def _migrate_tables(rfc=''): is_discontinued = BooleanField(default=False) migrations.append(migrator.add_column( table, 'is_discontinued', is_discontinued)) + if not 'objeto_impuesto' in columns: + objeto_impuesto = TextField(default='02') + migrations.append(migrator.add_column(table, 'objeto_impuesto', objeto_impuesto)) + if 'almacen_id' in columns: migrations.append(migrator.drop_column(table, 'almacen_id')) @@ -10745,6 +10853,12 @@ def _migrate_tables(rfc=''): if not 'divisas' in columns: divisas = TextField(default='') migrations.append(migrator.add_column(table, 'divisas', divisas)) + if not 'exportacion' in columns: + new_field = TextField(default='01') + migrations.append(migrator.add_column(table, 'exportacion', new_field)) + if not 'receptor_regimen' in columns: + receptor_regimen = TextField(default='') + migrations.append(migrator.add_column(table, 'receptor_regimen', receptor_regimen)) table = 'almacenes' columns = [c.name for c in database_proxy.get_columns(table)] diff --git a/source/app/settings.py b/source/app/settings.py index 00624bc..1f404ea 100644 --- a/source/app/settings.py +++ b/source/app/settings.py @@ -42,7 +42,8 @@ except ImportError: DEBUG = DEBUG -VERSION = '1.47.0' +VERSION = '2.0.0' + EMAIL_SUPPORT = ('soporte@empresalibre.mx',) TITLE_APP = '{} v{}'.format(TITLE_APP, VERSION) @@ -133,6 +134,7 @@ PRE = { '3.0': '{http://www.sat.gob.mx/cfd/3}', '3.2': '{http://www.sat.gob.mx/cfd/3}', '3.3': '{http://www.sat.gob.mx/cfd/3}', + '4.0': '{http://www.sat.gob.mx/cfd/4}', 'TIMBRE': '{http://www.sat.gob.mx/TimbreFiscalDigital}', 'DONATARIA': '{http://www.sat.gob.mx/donat}', 'INE': '{http://www.sat.gob.mx/ine}', @@ -193,6 +195,7 @@ CURRENCY_MN = 'MXN' # ~ v2 CANCEL_VERSION = ('3.3', '4.0') +CFDI_VERSIONS = CANCEL_VERSION IS_MV = MV DB_COMPANIES = os.path.abspath(os.path.join(BASE_DIR, '..', 'db', 'rfc.db')) diff --git a/source/static/js/controller/invoices.js b/source/static/js/controller/invoices.js index e060d42..22949b6 100644 --- a/source/static/js/controller/invoices.js +++ b/source/static/js/controller/invoices.js @@ -685,6 +685,7 @@ function guardar_y_timbrar(values){ data['metodo_pago'] = $$('lst_metodo_pago').getValue() data['uso_cfdi'] = $$('lst_uso_cfdi').getValue() data['regimen_fiscal'] = $$('lst_regimen_fiscal').getValue() + data['receptor_regimen'] = $$('lst_invoice_client_regimen').getValue() data['relacionados'] = ids data['tipo_relacion'] = tipo_relacion data['anticipo'] = anticipo @@ -904,6 +905,12 @@ function search_client_by_id(id){ function set_client(row){ + if(!row.codigo_postal){ + msg = 'El cliente no tiene capturado su Código Postal, es obligatorio.' + msg_error(msg) + return + } + var form = $$('form_invoice') var html = '' form.setValues({ @@ -913,6 +920,12 @@ function set_client(row){ html += row.nombre + ' (' + row.rfc + ')' $$('lbl_client').setValue(html) $$('cmd_cfdi_relacionados').enable() + + var lst = $$('lst_invoice_client_regimen') + lst.getList().clearAll() + lst.getList().parse(row.regimenes) + lst.setValue(lst.getPopup().getList().getFirstId()) + form.focus('search_product_id') } diff --git a/source/static/js/controller/partners.js b/source/static/js/controller/partners.js index e6dd2ab..87d2269 100644 --- a/source/static/js/controller/partners.js +++ b/source/static/js/controller/partners.js @@ -95,6 +95,7 @@ function cmd_new_partner_click(id, e, node){ $$('partner_balance').define('readonly', !cfg_partners['chk_config_change_balance_partner']) get_partner_banks() get_partner_accounts_bank(0) + get_sat_regimenes() } @@ -108,6 +109,8 @@ function cmd_edit_partner_click(){ var msg = '' var row = $$('grid_partners').getSelectedItem() + get_sat_regimenes() + $$('form_partner_account_bank').clearValidation() if (row == undefined){ @@ -145,6 +148,7 @@ function cmd_edit_partner_click(){ $$('cuenta_proveedor').enable() } get_partner_accounts_bank(row['id']) + $$('lst_receptor_regimenes_fiscales').select(values.regimenes) } }) @@ -239,7 +243,17 @@ function cmd_save_partner_click(id, e, node){ } } + var ids_regimenes = $$('lst_receptor_regimenes_fiscales').getSelectedId() + if(values.tipo_persona < 3){ + if(!ids_regimenes){ + msg = 'Selecciona al menos un Regimen Fiscal' + msg_error(msg) + return + } + } + values['accounts'] = $$('grid_partner_account_bank').data.getRange() + values['regimenes'] = ids_regimenes webix.ajax().post('/partners', values, { error:function(text, data, XmlHttpRequest){ @@ -343,9 +357,16 @@ function opt_tipo_change(new_value, old_value){ $$('id_fiscal').define('value', '') show('id_fiscal', new_value == 4) + $$('lst_receptor_regimenes_fiscales').clearAll() + if (new_value == 1 || new_value == 2){ $$("rfc").define("value", "") $$("rfc").define("readonly", false) + moral = false + if(new_value == 2){ + moral = true + } + get_sat_regimenes(moral) } else if (new_value == 3) { $$("rfc").define("value", RFC_PUBLICO) $$("nombre").define("value", PUBLICO) @@ -376,6 +397,8 @@ function opt_tipo_change(new_value, old_value){ } $$('lst_uso_cfdi_socio').getList().parse(query) $$('lst_uso_cfdi_socio').refresh() + + } @@ -619,3 +642,21 @@ function partner_delete_account_bank(row){ } }) } + + +function get_sat_regimenes(morales=false){ + var data = {opt: 'actives', morales: morales} + webix.ajax().get('/satregimenes', data, { + error: function(text, data, xhr) { + msg = 'Error al consultar' + msg_error(msg) + }, + success: function(text, data, xhr) { + var values = data.json() + $$('lst_receptor_regimenes_fiscales').clearAll() + $$('lst_receptor_regimenes_fiscales').parse(values) + } + }) + +} + diff --git a/source/static/js/ui/invoices.js b/source/static/js/ui/invoices.js index 4e488f2..9369461 100644 --- a/source/static/js/ui/invoices.js +++ b/source/static/js/ui/invoices.js @@ -418,6 +418,7 @@ var suggest_partners = { {id: 'rfc', adjust: 'data'}, {id: 'forma_pago', hidden: true}, {id: 'uso_cfdi', hidden: true}, + {id: 'codigo_postal', hidden: true}, ], dataFeed:function(text){ if (text.length > 2){ @@ -596,6 +597,10 @@ var controls_generate = [ autowidth:true}, {view: 'label', id: 'lbl_client', name: 'lbl_client', label: 'Ninguno'}, + ]}, + {cols: [{ + view: 'richselect', id: 'lst_invoice_client_regimen', + label: 'Regimen Fiscal: ', labelWidth: 150, options: []} ]} ]}}, {view: 'fieldset', label: 'Buscar Producto', body: {rows: [ diff --git a/source/static/js/ui/partners.js b/source/static/js/ui/partners.js index d7aeab2..7a125c0 100644 --- a/source/static/js/ui/partners.js +++ b/source/static/js/ui/partners.js @@ -96,7 +96,7 @@ var controls_fiscales = [ {cols: [{view: 'text', id: 'no_interior', name: 'no_interior', width: 300, label: 'No Interior: '},{}]}, {cols: [{view: 'search', id: 'codigo_postal', name: 'codigo_postal', - width: 300, label: 'C.P.: ', attributes: {maxlength: 5}},{}]}, + width: 300, label: 'C.P.: ', attributes: {maxlength: 5}, required: true},{}]}, {view: 'text', id: 'colonia', name: 'colonia', label: 'Colonia: '}, {view: 'text', id: 'municipio', name: 'municipio', label: 'Municipio: '}, {view: 'text', id: 'estado', name: 'estado', label: 'Estado: '}, @@ -122,6 +122,12 @@ var controls_fiscales = [ {view: 'richselect', id: 'lst_uso_cfdi_socio', name: 'uso_cfdi_socio', label: 'Uso del CFDI', options: []}, {}, + ]}, + {template: 'Regimenes Fiscales', type: 'section'}, + {cols: [ + {view: 'list', id: 'lst_receptor_regimenes_fiscales', data: [], + select: 'multiselect', width: 600, height: 125, required: true}, + {}, ]} ] @@ -159,7 +165,7 @@ var controls_others = [ label: 'Cuenta Proveedor: ', disabled: true}, {}] }, {view: 'checkbox', name: 'es_ong', label: 'Es ONG: ', value: false}, - {view: 'text', name: 'tags', label: 'Etiquetas', + {view: 'text', name: 'tags', label: 'Etiquetas', disabled: true, tooltip: 'Utiles para filtrados rápidos. Separa por comas.'}, {view: 'textarea' , height: 200, name: 'notas', label: 'Notas'}, ]