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'},
]